什么是代理
代理是为其它对象提供一种代理以控制这个对象的访问,Java中的代理分为下面三种角色:
Subject(抽象角色): 通过接口或抽象类声明真实角色实现的业务方法。
RealSubject(目标角色): 实现抽象角色,定义目标角色所要实现的业务逻辑,供代理角色调用。
Proxy(代理角色): 实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作。
代理模式根据生成代理类时机
的不同分为两种,分为静态代理
和动态代理
,静态代理在编译期就已经生成代理类,动态代理是在程序运行的时候动态生成代理类。
静态代理
静态代理要求委托类(RealSubject)和代理角色(Proxy)必须实现同一个接口或者继承同一个父类,否则无法生成代理类。
抽象角色
1 | public interface Action { |
目标角色
1 | public class RealObject implements Action { |
代理角色
1 | public class ProxyObject implements Action { |
测试类
1 | public class StaticProxyTest { |
运行结果
1 | proxy do |
动态代理
动态代理相比静态代理来说,它在一定程度上减少了代码冗余,它通过反射机制
来创建代理类。它不要求
委托类和代理类必须实现同一个接口或者继承同一个父类
,但是委托类需要实现接口,代理类需要实现InvocationHandler
接口。JDK动态代理主要涉及到两个类:java.lang.reflect.Proxy
和java.lang.reflect.InvocationHandler
。比如说我们要代理同一个接口的不同实现,如果使用静态代理,我们就要生成多个代理类,而使用动态代理我们只需要一个代理类。
JDK动态代理
抽象角色
1 | public interface UserDao { |
目标角色
1 | public class UserDaoImpl implements UserDao { |
代理角色
1 | public class JdkProxy implements InvocationHandler { |
测试类
1 | public class JdkDynamicProxyTest { |
运行结果
1 | 方法执行前 |
CGLIB动态代理
Cglib是一个强大的高性能的代码生成包,它可以在运行期扩展java类与实现java接口。它通过字节码技术
为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑,来完成动态代理的实现。它广泛的被许多AOP的框架使用,例如Spring AOP和synaop,为他们提供方法的拦截。使用CGLIB需要引入如下jar包。CGLIB代理方式不要求委托类必须实现接口或者继承一个父类,它通过继承委托类来实现代理,所以这也是它的一个缺点,它不能代理被final修饰的类
。
1 | <dependency> |
目标角色
1 | public class CglibDelegateClass { |
代理角色
1 | public class CglibProxyClass implements MethodInterceptor { |
测试类
1 | public class CglibTest { |
运行结果
1 | before |