成都建设网站 scgckj,重庆平台网站推广,拼多多网站,wordpress 主题和插件下载失败静态代理的缺点#xff1a;
1、由于静态代理中的代理类是针对某一个类去做代理的#xff0c;那么假设一个系统中有100个Service#xff0c;则需要创建100个代理类 2、如果一个Service中有很多方法需要事务#xff08;增强动作#xff09;#xff0c;发现代理对象的方法中…静态代理的缺点
1、由于静态代理中的代理类是针对某一个类去做代理的那么假设一个系统中有100个Service则需要创建100个代理类 2、如果一个Service中有很多方法需要事务增强动作发现代理对象的方法中还是有很多重复的代码 3、由第一点和第二点可以得出静态代理的重用性不强 那怎么解决呢 用动态代理就可以很好的解决上述问题本篇介绍一下Java中的动态代理 动态代理实现的目的和静态代理一样都是对目标方法进行增强而且让增强的动作和目标动作分开达到解耦的目的 动态代理分为JDK的动态代理和cglib动态代理他俩有略微的差别cglib动态代理产生的代理对象是目标对象的子类。 下面分别介绍JDK的动态代理是JDK的代码实现的和cglib动态代理是cglib的jar包实现的
JDK的动态代理
Interface
package com.itheima.proxy;/*** 对生产常见的要求*/
public interface IProducer {/*** 销售* param money*/public void saleProduct(float money);/*** 售后* param money*/public void afterServer(float money);
}
Producer
package com.itheima.proxy;/*** 一个生产者[需要符合代理商的要求代理商的要求是 要有销售和售后]*/
public class Producer implements IProducer {/*** 销售** param money*/public void saleProduct(float money) {System.out.println(拿到钱卖出产品money);}/*** 售后** param money*/public void afterServer(float money) {System.out.println(提供售后服务并拿到钱money);}
}
client
package com.itheima.proxy;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;/*** 模拟一个消费者*/
public class client {public static void main(String[] args) {//生产者final Producer producer new Producer();/*** 动态代理* 特点字节码 随用随创建随用随加载* 作用不修改源码的基础上对方法增强* 分类基于接口的动态代理* 设计的类 peoxy* 提供者JDK官方** 基于子类的动态代理*如何创建代理对象* 使用Proxy类中的newProxyInstance方法*创建代理对象的要求* 被代理类必须实现一个接口如果没有则不能使用* newProxyInstance 参数* ClassLoader:类加载器* 它是用于加载代理对象的字节码的和被代理对象使用相同的类加载器 固定写法* class[]字节码数组* 它是用于让代理对象和被代理对象有相同的方法。 固定写法* InvocationHandler :用于提供增强的代码* 它是让我们写如何代理我们一般都是写一个该接口的实现类通常情况下都是匿名内部类但不是必须的* 此接口的实现类都是谁用谁写**//*代理对象为 iProducer。被代理对象producer*/IProducer iProducer (IProducer) Proxy.newProxyInstance(producer.getClass().getClassLoader(), producer.getClass().getInterfaces(), new InvocationHandler() {/*** 作用执行被代理对象的任何接口方法都会经过该方法* param proxy 代理对象的引用* param method 当前执行的方法* param args 当前执行方法的参数* return 和被代理对象方法有相同的返回值* throws Throwable*/public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 提供增强的代码Object returnValue null;
// 获取方法执行的参数Float money (Float) args[0];
// 判断当前的方法是不是销售if (saleProduct.equals(method.getName())) {returnValue method.invoke(producer, money * 0.8f);} else {returnValue method.invoke(producer, money * 0.08f);}return returnValue;}});iProducer.saleProduct(10000f);iProducer.afterServer(1000f);}
}
结果
拿到钱卖出产品8000.0
提供售后服务并拿到钱80.0cglib动态代理
client
package com.itheima.cglib;import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;import java.lang.reflect.Method;public class client {public static void main(String[] args) {final Producer producer new Producer();/*动态代理特点字节码随用随创建随用随加载作用在不修改源码的基础上对方法增强分类基于接口的动态代理基于子类的动态代理涉及的类Enhancer提供者: 第三方cglib库如何创建代理对象使用Enhance类中的create方法创建代理对象的要求被代理对象的类不能是最终类create方法的参数class:字节码它是用于指定被代理对象的字节码CallBack用于提供增强的代码它是让我们写如何代理我们一般都是写一个该接口的实现类通常情况下采用匿名内部类但是不是必须的我们一般写的都是该接口的子接口的实现类MethodInterceptor*/Producer producerProxy (Producer) Enhancer.create(producer.getClass(), new MethodInterceptor() {/*** 执行被代理对象的任何方法都会经过该方法 具有拦截作用** param proxy* param method* param args 以上是哪个参数和基于接口的动态代理中的invoke方法的参数是一样的* param methodProxy 当前执行方法的代理对象* return* throws Throwable*/public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {Object returnValue null;Float money (Float) args[0];if (saleProduct.equals(method.getName())) {returnValue method.invoke(producer, money * 0.8f);}else {returnValue method.invoke(producer, money * 0.08f);}return returnValue;}});producerProxy.saleProduct(10000f);producerProxy.afterServer(1000f);}
}
Producer
package com.itheima.cglib;public class Producer {/*** 销售** param money*/public void saleProduct(float money) {System.out.println(拿到钱卖出产品money);}/*** 售后** param money*/public void afterServer(float money) {System.out.println(提供售后服务并拿到钱money);}
}
结果
拿到钱卖出产品8000.0
提供售后服务并拿到钱80.0以上就是动态代理的两种实现。
我们用上边的做法去实现目标方法的增强实现代码的解耦是没有问题的但是还是需要自己去生成代理对象自己手写拦截器在拦截器里自己手动的去把要增强的内容和目标方法结合起来这用起来还是有点繁琐有更好的解决方案吗
答案是有的那就是Spring的AOP这才是咱们最终想引出来的重点
有了Spring的AOP后就不用自己去写了只需要在配置文件里进行配置配置好后Spring按照你的配置去帮你生成代理对象按照你的配置把增强的内容和目标方法结合起来。就相当于自己写代码也能实现和aop类似的功能但是有了Spring aop以后有些事情Spring帮你做了而且人家Spring做成了可配置化用起来非常简单而且很灵活
咱们上边用的JDK动态代理和cglib动态代理这两种在Spring的AOP里都有用到Spring是根据不同的情况去决定是使用JDK的动态代理生成代理对象还是使用cglib去生成代理对象。