目录
代理模式
给目标对象提供一个代理对象,并由代理对象控制对目标对象的引用。
代理模式中代理对象和目标对象要实现相同的接口。
优点:
- 控制对目标对象的直接访问,可以很好的隐藏和保护目标对象。
- 最重要的一点是,在不改变目标方法的情况下对目标方法进行增强。
静态代理
静态代理就是为每一个需要代理的目标对象都创建一个代理类,程序编译后就存在代理类的class文件。
缺点:目标类和代理类是一对一的关系,当需要多个目标对象需要进行代理的时候,要创建很多的类。代理类也会实现目标类的方法,导致大量代码重复。一个代理类只可以代理一个类型的对象。
动态代理
代理类是在程序运行的时候通过反射机制创建的。可以代理各个类型的对象。
在Java中要想实现动态代理机制,需要java.lang.reflect.InvocationHandler接口和 java.lang.reflect.Proxy类的支持。
动态代理只支持代理接口,不支持代理抽象类。
JDK实现动态代理:使用reflect包中的InvocationHandler(调用处理器)和Proxy类来实现。
- 实现InvocationHandler类的invoke方法。在invoke方法中对目标方法进行增强。invoke(Object proxy(被代理的对象),Method method(方法), Object[] args(方法参数))。
//Object proxy:被代理的对象
//Method method:要调用的方法
//Object[] args:方法调用时所需要参数
public interface InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}
- Proxy则利用Inovacation实例来创建代理对象,来间接的调用代理方法。使用newProxyInstance方法(目标类的加载器,目标类的接口,InvocationHandler实例)
//CLassLoader loader:类的加载器
//Class<?> interfaces:得到全部的接口
//InvocationHandler h:得到InvocationHandler接口的子类的实例
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
最终的客户端实现:
public static void main(String[] args) {
//被代理对象
UserManagerImpl userManager = new UserManagerImpl();
//Inovacation实例
LoggerHandler1 loggerHandler1 = new LoggerHandler1(userManager);‘
//Proxy通过目标对象和Inovacation对象创建代理对象。
UserManager userManager1 = (UserManager) Proxy.newProxyInstance(userManager.getClass().getClassLoader(),userManager.getClass().getInterfaces(),loggerHandler1);
userManager1.addUser("1111","张三");
}
动态代理的应用:日志,事务,拦截器,权限控制等。
AOP中的动态代理
将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中剥离出来,改变这些代码的时候并不影响业务逻辑代码,实现解耦。
JDK中的动态代理是基于接口的,没有接口的话是不行的。最后生成的代理类继承了Proxy类,实现了代理的接口。JDK中的动态代理是动态的生成了被目标类的接口的实现类。(代理类实现了被代理的接口,继承了Proxy类)(使用接口)
cglib代理:采用第三方API实现动态代理:动态生成被代理类的子类。(使用继承)
cglib底层运用了asm这个非常强大的Java字节码生成框架来生成class, 比jdk代理效率要高。cglib的代理效率比JDK的动态代理高,但还是建议使用JDK的动态代理,因为第三方的API可能不稳定。
cglib动态代理:
编写被代理对象,被代理对象可以不实现任何接口
创建自己的MethodInterceptor类实现MethodInterceptor的intercep方法。在intercep方法中对代理对象的方法进行增强。
创建enhancer对象,通过enhancer的setSuperClass方法设置代理对象的父类
通过EnHancer的setCallback方法传入自己实现的methodInterceptor对象。
通过create方法创建代理对象。