概念
- 代理模式即:提供一个代理类来控制对目标对象的访问
- 代理模式分为静态代理和动态代理,动态代理又有JDK动态代理和CGLIB动态代理。
静态代理
- 静态代理指代理类在程序运行前就存在,代理类和目标类的关系也已经确定
- 代理类和目标类需要实现同一个接口
优点
- 可以在不修改目标对象的情况下,扩展目标对象的功能(符合对修改封闭,对扩展开放的原则)
缺点
- 代码维护复杂度增加:代理类和目标类实现同一接口,接口增加方法的话目标类和代理类都需要修改。
- 代码冗余度高:代理类只能代理一种类型的目标类
实例
- 接口
public interface Workable { /** * 工作 */ void work();}复制代码
- 目标对象
public class Star implements Workable{ @Override public void work() { System.out.println("明星演戏。"); }}复制代码
- 代理对象
public class Agent implements Workable{ private Workable workable; public Agent(Workable workable){ this.workable = workable; } @Override public void work() { System.out.println("经纪人帮明星谈片酬然后让他去演戏"); workable.work(); System.out.println("经纪人帮明星收钱"); }}复制代码
- 测试类
public class Director { public static void main(String... arg){ Workable star = new Star(); Workable agent = new Agent(star); agent.work(); }}结果:经纪人帮明星谈片酬然后让他去演戏明星演戏。经纪人帮明星收钱演戏的话需要找经纪人,经纪人控制对明星的访问(是不是接你的戏)明星只需要演戏就可以,剩下其他不想做的事都可以交给经纪人复制代码
动态代理
- 代理类是程序运行时动态生成的
- 实现AOP的基础
JDK动态代理
- 又称接口代理,要求目标类必须实现接口
- 主要涉及Proxy和InvocationHandler两个类 通过实现InvocationHandler接口定义横切逻辑,并通过反射调用目标类的代码。将横切逻辑和业务逻辑编织在一起。
- 代理对象的所有接口方法调用都会转发到InvocationHandler.invoke()方法
实例
- 横切逻辑
public class AgentHandler implements InvocationHandler { private Workable workable; public AgentHandler(Workable workable){ this.workable = workable; } // 将横切逻辑和业务代码编织在一起 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("经纪人帮明星谈片酬然后让他去演戏"); Object object = method.invoke(workable, args); System.out.println("经纪人帮明星收钱"); return object; }}复制代码
- 测试
public class Director { public static void main(String... arg){ Workable star = new Star(); // 创建代理类对象 Workable proxyInstance = (Workable)Proxy.newProxyInstance(star.getClass().getClassLoader(), star.getClass().getInterfaces(), new AgentHandler(star)); proxyInstance.work(); }}结果:和静态代理一样经纪人帮明星谈片酬然后让他去演戏明星演戏。经纪人帮明星收钱复制代码
动态代理可以代理多种类型的对象。
CGLib 动态代理
- CGLib 采用底层的字节码技术,可以为一个类创建子类,在子类中通过方法拦截的方式拦截所有父类方法的调用,并织入横切逻辑。
- 通过创建目标类的子类的方式
- 涉及的类Enhancer 和 MethodInterceptor
实例
- 横切逻辑
public class AgentInterceptor implements MethodInterceptor { private Enhancer enhancer = new Enhancer(); /** * 设置目标类来创建子类实例 * @param clazz 目标类 * @return obj */ public Object getProxy(Class clazz){ enhancer.setSuperclass(clazz); enhancer.setCallback(this); return enhancer.create(); } @Override public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { System.out.println("经纪人帮明星谈片酬然后让他去演戏"); // 通过代理类调用父类的方法 Object result = methodProxy.invokeSuper(object, args); System.out.println("经纪人帮明星收钱"); return result; }}复制代码
- 测试
public class Director { public static void main(String... arg){ AgentInterceptor agentInterceptor = new AgentInterceptor(); // 创建代理类对象 Star star = (Star) agentInterceptor.getProxy(Star.class); star.work(); }}结果:和静态代理一样经纪人帮明星谈片酬然后让他去演戏明星演戏。经纪人帮明星收钱复制代码
通过生成目标类的子类,并实现MethodInterceptor接口的方法,拦截所有目标类的调用。