动态代理与静态代理的比较
和静态代理一样,动态代理同样有三种角色:1.抽象角色(用于被代理类、被代理类共同实现的接口);2.被代理角色(被代理的类,是我们最终要引用的对象);3.代理角色(实现共同接口,代理被代理类完成工作,而且可以做一些额外的工作)。
动态代理的抽象角色和被代理角色与静态代理完全相通,而动态代理的代理类是动态实现的。
那么如何动态生成代理类呢?我们只需要实现InvovationHandler接口。
动态代理实现步骤
1.创建一个实现了InocationHandler接口的类,它必须实现invoke方法,去完成被代理类的调用方法。
2.创建被代理类,及被代理类所实现的接口。
3.通过Proxy.newProxyInstanse()方法动态创建一个代理类。
4.调用代理对象实现被代理类的方法。
动态代理代码演示与分析
首先还是要写一个抽象角色的接口,和静态代理不同的(静态代理的抽象角色可以是接口也可以是抽象类)是这里只能用接口,原因后面会说到。
public interface Subject { public void request(); }
然后是被代理角色,与静态代理的被代理角色可以说是完全一样
public class RealSubject implements Subject { @Override public void request() { System.out.println("RealSubject request "); } }
关键的是代理角色动态生成,与静态代理的实现方式有很大区别,需要继承invocationhandler接口,invocationhandler是
java.lang.reflect包下的接口。
public class DynamicSubject implements InvocationHandler{ private Object sub;//被代理对象 public DynamicSubject(Object obj){//构造方法用于传入被代理对象 this.sub=obj; } //实现invocationhandler接口,必须实现的方法,被代理对象的业务逻辑也在这里实现 @Override public Object invoke(Object sub, Method method, Object[] args) throws Throwable { System.out.println("before method"); method.invoke(sub,args);//实现被代理对象的业务方法 System.out.println("after method"); return null; } }
之前说静态代理的时候说过,在代理对象中有被代理对象的引用,这里被代理对象因为不知道具体是什么对象所以传入一个Object对象,这样无论被代理对象是什么类型的都可以被这个代理类所代理,也就实现了所谓的动态。
invoke方法是实现了被代理对象业务逻辑的方法,通过反射调用被代理类的方法(这里如果不清楚反射需要去查查资料,不然不好理解)。method.invoke(sub,args)表示被代理类被执行的方法,sub表示该method方法属于哪个类,args参数列表最总确定了唯一的方法(其实还是反射的内容)。invoke()方法的sub参数 和method参数是通过底层传递过来的。
代理实现:
public class Client { public static void main(String[] args) { RealSubject realSubject=new RealSubject();//真实对象 InvocationHandler invocationHandler=new DynamicSubject(realSubject);//获取最终实际完成业务逻辑handler Class<?> classType=invocationHandler.getClass(); //生成代理对象 Subject subject= (Subject) Proxy.newProxyInstance(classType.getClassLoader(),
realSubject.getClass().getInterfaces(),invocationHandler); subject.request();//调用方法 } }
Proxy.newProxyInstance()方法解析
通过Proxy.newProxyInstance方法动态获取一个代理类。该方法有三个参数:1.ClassLoader loader;2.Class<?> interfaces;
3.InvocationHandler h 。下面逐个分析三个参数的作用:
1.ClassLoader loader 动态代理,那么代理类肯定是运行时动态生成的,既然要动态生成肯定需要在运行时将生成的类加载到内存中,那么必然需要一个类加载器ClassLoader (参考JVM 类加载器)
2.Class<?> interfaces 便是该代理类实现的接口数组,实现了哪些接口也就代理了哪些类(代理类和被代理类需要实现共同的接口,这里传入的是RealSubject实现的接口的Class数组,也就是说最终生成的代理类代理了realSubject)。这里也实现了所谓的动态,因为你想让代理类代理谁那么就传入哪个接口。
3.InvocationHandler h 代理类本身是不实现业务逻辑的,业务逻辑交由实现编写好的handler执行。
代理类实现被代理类方法
subject.request();//调用方法 这句代码等价与RealSubject的request()方法。通过代理类调用request()方法,最终实现了被代理类RealSubject的request 方法。例子中RealSubject只有一个无参的request方法,如果有其他的方法,比如:request(String name),response(),也可以 通过代理类通过反射去调用(invocationHandler中的这句代码通过反射,method.invoke(sub,args),根据不同的方法名,调 用方法的对象,方法参数列表最终确定唯一的被调用方法),也就实现了所谓的动态。如何实现了动态
被代理对象RealSubject可以在运行时动态改变,调用的方法(可以随意选择被代理对象的任何方法)可以在运行时动态改变,被 代理对象可以运行时动态改变,因此实现了非常灵活的动态代理。