动态代理的用途:java
动态代理的用途与装饰模式很类似,就是为了对某个对象进行加强。全部使用装饰者模式的案例均可以使用动态代理来替换,动态代理能够更好的解耦合ide
加强有3个手段
1. 继承
被加强对象不能变
加强内容不能变
2. 装饰者模式
被加强对象可变
但加强内容不能变
3. 动态代理
被加强对象可变
加强内容也可变测试
如何实现动态代理?this
定义一个接口Interface, 被加强的对象的类都会实现这个接口spa
public interface Interface { public void fun(); }
实现这个Interface接口:
而这个InterfaceImpl就是动态代理中被加强的内容代理
public class InterfaceImpl implements Interface { @Override public void fun() { System.out.println("目标方法调用"); } }
定义一个接口Advice, 加强内容的类都会实现这个接口
这个接口有两个未实现的方法:
before()前置加强的方法
after()后置加强的方法code
public interface Advice { public void before(); public void after(); }
而实现了Advice接口的对象就是动态代理中加强内容对象
JavaAPI:继承
java.lang.reflect.Proxy接口
Object proxyObject = Proxy.newProxyInstance(ClassLoader classLoader, Class[] interfaces, InvocationHandler h);
返回一个指定接口的代理类实例,该接口能够将方法调用指派到指定的调用处理程序
参数:
classLoader - 定义代理类的类加载器
interfaces - 代理类要实现的接口列表
h - 指派方法调用的调用处理程序
返回:
一个带有代理类的指定调用处理程序的代理实例,它由指定的类加载器定义,并实现指定的接口
java.lang.reflect.InvocationHandler
public Object invoke(Object proxy, Method method, Object[] args);
这个invoke()方法在调用代理对象所实现接口中的方法时调用
* Object proxy:当前对象,即代理对象!在调用谁的方法!
* Method method:当前被调用的方法(目标方法)
* Object[] args:目标方法参数
调用proxy实例的方法时, 都会被InvocationHandler所捕获, 所以只要实现InvocationHandler实现类的invoke()方法, 就能够实现目标方法的加强
定义一个类ProxyFactory
该类经过两个参数的public ProxyFactory(target,advice)构造方法构造ProxyFactory实例, 而后经过该实例的getProxy()方法获得代理对象
public class ProxyFactory { private Object target; // 目标对象 private Advice advice; // 加强对象 public ProxyFactory(Object target, Advice advice) { this.target = target; this.advice = advice; } /** * 获得代理对象 */ public Object getProxy() { return Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 执行前置加强 advice.before(); // 执行目标对象的目标方法, 用result接收返回值 Object result = method.invoke(target, args); // 执行后置加强 advice.after(); // 返回目标方法的返回值result return result; } }); } }
测试动态代理
public static void main(String[] args) { InterfaceImpl target = new InterfaceImpl(); // 实现一个Advice的实例对象, 这个对象就是动态代理中加强内容 Advice advice = new Advice() { @Override public void before() { System.out.println("目标方法调用以前, 执行前置加强"); } @Override public void after() { System.out.println("目标方法调用以后, 执行后置加强"); } }; ProxyFactory proxyFactory = new ProxyFactory(target, advice); Interface proxy = (Interface) proxyFactory.getProxy(); proxy.fun(); }
Console输出:
方法调用以前, 执行前置加强目标方法调用方法调用以后, 执行后置加强