Java基础:动态代理
系列閱讀
- Java基礎:類加載器
- Java基礎:反射
- Java基礎:注解
- Java基礎:動態代理
概述
在運行時,動態創建一組指定的接口的實現類對象(代理對象)!
代理是實現AOP(面向切面編程)的核心和關鍵技術,動態代理的用途與裝飾模式很相似,就是為了對某個對象進行增強。所有使用裝飾者模式的案例都可以使用動態代理來替換。
代理:本來應該自己做的事情,卻請了別人來做,被請的人就是代理對象。
舉例:春季回家買票讓人代買
動態代理:在程序運行過程中產生的這個對象
而程序運行過程中產生對象其實就是我們剛才反射講解的內容,所以,動態代理其實就是通過反射來生成一個代理
工作原理
- client調用代理
- 代理的構造方法接收一個invocationhandler參數
- client調用代理的各個方法,代理的各個方法會把調用請求轉發給invocationhandler
- invocationhandler通過invoke()方法把調用請求分發給目標對象的各個方法
1、在Java中java.lang.reflect包下提供了一個Proxy類和一個InvocationHandler接口,通過使用這個類和接口就可以生成動態代理對象。JDK提供的代理只能針對接口做代理。我們有更強大的代理cglib。
2、Proxy類中的方法創建動態代理類對象
public static Object newProxyInstance(ClassLoader loader,Class<?>[]interfaces,InvocationHandler h)返回一個指定接口的代理類實例,該接口可以將方法調用指派到指定的調用處理程序。最終會調用InvocationHandler的方法
3、InvocationHandler
Object invoke(Object proxy,Method method,Object[] args)在代理實例上處理方法調用并返回結果。
4、Proxy類中創建動態代理對象的方法的三個參數
ClassLoader對象
定義了由哪個ClassLoader對象來對生成的代理對象進行加載Interface對象的數組
表示的是我將要給我需要代理的對象提供一組什么接口,如果我提供了一組接口給它,那么這個代理對象就宣稱實現了該接口(多態),這樣我就能調用這組接口中的方法了InvocationHandler對象
表示的是當我這個動態代理對象在調用方法的時候,會關聯到哪一個InvocationHandler對象上
每一個動態代理類都必須要實現InvocationHandler這個接口,并且每個代理類的實例都關聯到了一個handler,當我們通過代理對象調用一個方法的時候,這個方法的調用就會被轉發為由InvocationHandler這個接口的invoke 方法來進行調用。
5、InvocationHandler接口中invoke()方法的三個參數:
- Object proxy:代表動態代理對象
- Method method:代表正在執行的方法
- Object[] args:代表調用目標方法時傳入的實參
6、Proxy.newProxyInstance()
創建的代理對象是在jvm運行時動態生成的一個對象,它并不是我們的InvocationHandler類型,也不是我們定義的那組接口的類型,而是在運行是動態生成的一個對象,并且命名方式都是這樣的形式,以$開頭,proxy為中,最后一個數字表示對象的標號
動態代理的實現
package cn.itcast_06;/** 用戶操作接口*/ public interface UserDao {public abstract void add();public abstract void delete();public abstract void update();public abstract void find(); } package cn.itcast_06;public interface StudentDao {public abstract void login();public abstract void regist(); } package cn.itcast_06; public class UserDaoImpl implements UserDao {@Overridepublic void add() {System.out.println("添加功能");}@Overridepublic void delete() {System.out.println("刪除功能");}@Overridepublic void update() {System.out.println("修改功能");}@Overridepublic void find() {System.out.println("查找功能");} } package cn.itcast_06;public class StudentDaoImpl implements StudentDao {@Overridepublic void login() {System.out.println("登錄功能");}@Overridepublic void regist() {System.out.println("注冊功能");} } package cn.itcast_06;import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method;public class MyInvocationHandler implements InvocationHandler {private Object target; // 目標對象public MyInvocationHandler(Object target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args)throws Throwable {System.out.println("權限校驗");Object result = method.invoke(target, args);System.out.println("日志記錄");return result; // 返回的是代理對象} } package cn.itcast_06;import java.lang.reflect.Proxy;public class Test {public static void main(String[] args) {UserDao ud = new UserDaoImpl();ud.add();ud.delete();ud.update();ud.find();System.out.println("-----------");// 我們要創建一個動態代理對象// Proxy類中有一個方法可以創建動態代理對象// public static Object newProxyInstance(ClassLoader loader,Class<?>[]// interfaces,InvocationHandler h)// 我準備對ud對象做一個代理對象MyInvocationHandler handler = new MyInvocationHandler(ud);UserDao proxy = (UserDao) Proxy.newProxyInstance(ud.getClass().getClassLoader(), ud.getClass().getInterfaces(), handler);proxy.add();proxy.delete();proxy.update();proxy.find();System.out.println("-----------");StudentDao sd = new StudentDaoImpl();MyInvocationHandler handler2 = new MyInvocationHandler(sd);StudentDao proxy2 = (StudentDao) Proxy.newProxyInstance(sd.getClass().getClassLoader(), sd.getClass().getInterfaces(), handler2);proxy2.login();proxy2.regist();} }Spring原理
public class ProxyFactoryBean {private Object mTarget;private Advice mAdvice;public Object getProxy(){Object proxy = Proxy.newProxyInstance(mTarget.getClass().getClassLoader(),mTarget.getClass().getInterfaces(),mHandler);return proxy;}private InvocationHandler mHandler = new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {mAdvice.beforeMethod(method);Object result = method.invoke(mTarget, args);mAdvice.afterMethod(method);return result;}};public void setTarget(Object target) {mTarget = target;}public void setAdvice(Advice advice) {mAdvice = advice;}public Object getTarget() {return mTarget;}public Advice getAdvice() {return mAdvice;} }public class BeanFactory {Properties mProperties = new Properties();public BeanFactory(InputStream in){try {mProperties.load(in);} catch (IOException e) {e.printStackTrace();}}public Object getBean(String name){String classname = mProperties.getProperty(name);Object bean = null;try {Class clazz = Class.forName(classname);bean = clazz.newInstance();} catch (Exception e) {e.printStackTrace();}if (bean instanceof ProxyFactoryBean){Object proxy = null;ProxyFactoryBean factoryBean = (ProxyFactoryBean) bean;Advice advice = null;try {advice = (Advice) Class.forName(mProperties.getProperty(name+".advice")).newInstance();Object target = Class.forName(mProperties.getProperty(name+".target")).newInstance();factoryBean.setAdvice(advice);factoryBean.setTarget(target);proxy = factoryBean.getProxy();} catch (Exception e) {e.printStackTrace();}return proxy;}return bean;} } public interface Advice {void beforeMethod(Method method);void afterMethod(Method method); } public class AopFrameworkTest {public static void main(String[] args) throws Exception {InputStream ips = AopFrameworkTest.class.getResourceAsStream("config.properties");Object bean = new BeanFactory(ips).getBean("xxx");System.out.println(bean.getClass().getName());((Collection)bean).clear();} }總結
以上是生活随笔為你收集整理的Java基础:动态代理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java基础:基本数据类型包装类
- 下一篇: Java基础:面向对象