七种常见结构型模式的描述总结与代码分析 (8)

动态代理也称:JDK 代理、接口代理,需要目标对象实现接口,否则不能用动态代理,利用 JDK 的 API(java.lang.reflect.Proxy),动态地在内存中构建代理对象

静态代理和动态代理的区别:

静态代理在编译时就已经实现,编译完后的代理类是一个实际的 class 文件

动态代理实在运行时动态生成的,编译后没有实际的 class 文件,而是在运行时动态的生成类字节码,并加载到 JVM 中

代码实现

以静态代理的情景为例,我们只需要修改代理对象的代码,代理对象不需要实现公共接口了。

public class ProxyProducer { /** * 维护一个目标对象 */ private Object target; public ProxyProducer(Object target) { this.target = target; } public Object getProxyInstance() { return Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() { /** * 执行被代理对象的任何接口方法都会经过这里 * @param proxy 代理对象的引用 * @param method 当前执行的方法 * @param args 当前执行方法的参数 * @return 和被代理对象具有相同的返回值 * @throws Throwable */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //代理过程中执行一些方法 float money = (float) args[0] * 0.8f; //反射机制调用目标对象的方法 Object invoke = method.invoke(target, money); return invoke; } }); } } Cglib 代理 介绍

Cglib 代理也叫子类代理,目标对象不需要实现任何接口,它是在内存中构建一个子类对象从而实现对目标对象功能的扩展。

Cglib 是一个强大的高性能的代码生成包,它可以在运行期间扩展 Java 类与实现 Java 接口,它广泛地被许多 AOP 的框架使用,例如 Spring AOP,用于实现方法拦截。

Cglib 包底层实通过使用字节码处理框架 ASM 来转换字节码并生成新的类。

在 AOP 编程中选择哪种代理模式?

目标对象需要实现接口,用 JDK 代理

目标对象不需要实现接口,用 Cglib 代理

代码实现

使用之前需要导入相关 jar 包,可去 maven 仓库下载

被代理对象,无需实现接口

public class Producer { public void sale(float money) { System.out.println("卖出产品,厂家获得" + money + "元"); } }

代理对象

public class ProxyProducer implements MethodInterceptor { /** * 维护一个目标对象 */ private Object target; public ProxyProducer(Object target) { this.target = target; } /** * 为目标对象生成代理对象 */ public Object getProxyInstance(){ //创建一个工具类 Enhancer enhancer = new Enhancer(); //设置父类 enhancer.setSuperclass(target.getClass()); //设置回调函数 enhancer.setCallback(this); //创建子类对象(代理对象) return enhancer.create(); } /** * 会拦截被代理对象的所有方法 * @param obj 增强对象 * @param method 被代理对象的方法 * @param args 被代理对象方法的参数 * @param methodProxy 代理对象 */ @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { System.out.println("obj:" + obj.getClass()); Object returnValue = null; float money = (float) args[0] * 0.8f; if("sale".equals(method.getName())){ returnValue = method.invoke(target, money); } return returnValue; } }

测试类

public class Client { @Test public void test() { Producer producer = new Producer(); Producer proxyInstance = (Producer) new ProxyProducer(producer).getProxyInstance(); proxyInstance.sale(1000f); } }

⭐ 所有代码和笔记均可在 我的GitHub 获取

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zywpyx.html