JAVA动态代理

动态代理 静态代理 静态代理是由业务实现类、业务代理类两部分组成。业务实现类负责实现组主要的业务方法,业务代理类负责对调用的业务方法进行拦截、过滤、预处理,主要是在方法中首先进行预处理动作,然后调用业务实现类的方法,还可以规定调用后的操作。我们在需要调用业务时,不是直接通过调用业务实现类来调用的,而是通过业务代理类的同名方法来调用被代理类处理过的方法。
代码实现:

定义接口:Subject.class
public interface Subject {public void request(); }

业务实现类:SubjectImpl.java
public class SubjcetImpl implements Subject{@Override public void request() { System.out.println("真实请求"); }}

代理类:ProxySubjcet.java
public class ProxySubject implements Subject {private SubjcetImpl subjectImpl; public ProxySubject(SubjcetImpl subjectImpl) { this.subjectImpl = subjectImpl; }@Override public void request() { System.out.println("调用前,进行操作"); subjectImpl.request(); System.out.println("调用后,进行操作"); }}

使用代理类 Main.java
public static void main(String[] args) { ProxySubject proxySubject = new ProxySubject(new SubjcetImpl()); proxySubject.request(); }

静态代理的缺点很明显:一个代理类只能对一个业务接口的实现类进行包装,如果有多个业务接口的话就需要定义很多实现类和代理类才可以。
如果代理类对业务方法的预处理、调用操作都一样的话,那对多个代理类就会出现很多重复的代码、
JDK动态代理 JDK动态代理所用到代理类在程序调用对象是才有JVM真正创建,JVM根据传进来的业务实现类对象一级方法名、动态地创建了一个代理类的class文件并被子解码引擎执行,然后通过该代理类对象进行方法丢调用。
定义业务接口及定义业务实现类,见上面静态代理的业务接口及业务实现类
实现 调用管理接口InvocationHandler,创建动态代理类
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; /** * 调用自定义的代理hander的构造器来获取代理对象实例 * * @author houzhengming */ public class DynamicProxyHandler implements InvocationHandler { // 这其实业务实现类对象,用来调用具体的业务方法 private Object object; public DynamicProxyHandler(Object object) { this.object = object; }@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("代理运行前" + method.getName()); Object result = method.invoke(object, args); System.out.println("代理运行后"); return result; } }

执行 Main.java
public static void main(String[] args) {//创建代理对象时,需要传递该业务类的类加载器(用来获取业务实现类的元数据,在包装方法是调用真正的业务方法)、接口、handler实现类 Subject subject = (Subject) Proxy.newProxyInstance(Subject.class.getClassLoader(), new Class[]{Subject.class}, new DynamicProxyHandler(new SubjcetImpl())); subject.request(); }

优化:
定义接口应用(使用向上转型),并用代理对象绑定业务实现类对象,
修改为:
/** * @author houzhengming */ public class MyInvocationHandler implements InvocationHandler {private Object object; public MyInvocationHandler(Object object) { this.object = object; }public T bind() { Object proxy = Proxy.newProxyInstance(this.object.getClass().getClassLoader(), this.object.getClass().getInterfaces(), this); return (T) proxy; }@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("开始执行"); Object o = method.invoke(object, args); return o; } }

执行:
public static void main(String[] args) { Subject subject = new MyInvocationHandler(new SubjcetImpl()).bind(); subject.request(); }

JDK动态代理的代理对象在创建是,需要业务实现类所在的接口作为参数(因为后面代理方法时需要根据接口的方法名进行调用),如果业务实现类是没有实现接口而是直接定义业务方法的话,就无法使用JDK动态代理了,并且在业务实现类中新增了业务接口中没有打方法,这些方法也是无法被动态代理的(因为无法调用)。
CGLIB动态代理 cglib是针对类来实现代理的,原理是对指定的业务类生成一个子类,并覆盖其中的业务方法实现代理。因为采用的是继承,所有不能对final修饰的类进行代理
直接定义业务类,SubjectImpl.java
public static void main(String[] args) {SubjectImpl subjectImpl = (SubjectImpl) new MyMethodsInterceptor().getInstance(new SubjectImpl()); subjectImpl.request(); }

实现MethodInterceptor方法代理接口,创建代理类
/** * 自定义实现cglib中的methodInterceptor */ public class MyMethodsInterceptor implements MethodInterceptor {/** * 业务对象 */ private Object target; /** * 获取动态代理中的示例,类似于JDK中的动态代理的绑定 * @param target * @return */ public Object getInstance(Object target) { // 业务对象赋值 this.target = target; // 创建加强器,用来创建代理类 Enhancer enhancer = new Enhancer(); // 为加强器指定要代理的类,即为下面要生成的代理类指定父类 enhancer.setSuperclass(this.target.getClass()); // 设置回调,对于代理类上所有的方法的回调,都会调用callback。而callback需要实现intercept enhancer.setCallback(this); // 创建代理对象 return enhancer.create(); }/** * 实现回调方法 * @param o * @param method * @param objects * @param methodProxy * @return * @throws Throwable */ @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("调用操作前"); //调用业务类的父类 Object o1=methodProxy.invokeSuper(o,objects); System.out.println("调用操作后,方法执行结果为:"+o1); return o1; }}

调用:Main.java
【JAVA动态代理】通过代理类对象.getInstance(业务对象)返回一个动态代理类对象(它是业务类的子类。可以用业务类引用指向它)。通过动态代理类对象进行方法引用。
public static void main(String[] args) {SubjectImpl subjectImpl = (SubjectImpl) new MyMethodInterceptor().getInstance(new SubjectImpl()); subjectImpl.request(); }

比较 静态代理是通过在代码中显式定义一个业务实现类,一个代理,在代理类中对同名的业务方法进行包装,用户通过代理类调用被包装过的业务方法。
JDK动态代理是通过接口的方法名,在动态生成的代理类中调用业务实现类的同名方法。
CGLIB动态代理是通过继承业务类,生成的动态代理类是业务类的子类,通过重写业务方法实现的。、

    推荐阅读