静态代理的缺点:

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.0

cglib动态代理

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去生成代理对象。

动态代理JDK于cglib相关推荐

  1. java动态代理(JDK和cglib)详解

    JAVA的动态代理  代理模式  代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委 ...

  2. 使用 cglib_java动态代理(JDK和CGLIB原理解析与使用)

    CGLIB的动态代理 原理 代理为控制要访问的目标对象提供了一种途径.当访问对象时,它引入了一个间接的层.JDK自从1.3版本开始,就引入了动态代理,并且经常被用来动态地创建代理.JDK的动态代理用起 ...

  3. 动态代理jdk和cglib区别、注意事项(private,static,final)、spring aop原理

    文章目录 一.代理简聊 二.静态代理 三.动态代理 1.jdk动态代理 2.cglib动态代理 四.动态代理总结.注意事项 1.jdk动态代理与cglib的区别. 2.注意事项及分析. 五.aop原理 ...

  4. Java Spring-AOP动态代理-JDK和CGlib实现

    Java Spring-AOP CGlib和JDK动态代理实现 编码是为了解决生活中的问题,譬如现在我想用筷子吃饭的时候看手机,那么首先会有两个对象. 现在如果是面向对象编程思想,我们会new一个筷子 ...

  5. JAVA 进阶篇 动态代理 JDK动态代理和CGlib动态代理

    JDK动态代理和CGlib动态代理 JDK动态代理: 利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理. CGlib动态代理: 利用ASM(开源的Java ...

  6. Java两种动态代理JDK动态代理和CGLIB动态代理

    目录 代理模式 JDK动态代理 cglib动态代理 测试 代理模式 代理模式是23种设计模式的一种,他是指一个对象A通过持有另一个对象B,可以具有B同样的行为的模式.为了对外开放协议,B往往实现了一个 ...

  7. Spring AOP【AOP的基本实现与动态代理JDK Proxy 和 CGLIB区别】

    Spring AOP[AOP的基本实现与动态代理JDK Proxy 和 CGLIB区别]

  8. 动态代理proxy与CGLib的区别

    转载自 动态代理proxy与CGLib的区别 昨天被人问及动态代理与CGlib的区别,赶紧回顾一下: 什么是代理? 静态代理与动态代理 静态代理实例 JDK动态代理实例 CGLib 简介 CGLib ...

  9. jdk动态代理实例和cglib动态代理实例_CGLib 动态代理 原理解析

    JDK 动态代理实现与原理 首先来看一段CGLib代理的测试代码(MethodInterceptor的测试, 其他类型这里不做展开了). Util类的代码在后面给出的码云片段中 public 下面的输 ...

最新文章

  1. 分布式环境下,互斥性与幂等性问题,分析与解决思路
  2. CentOS7使用systemctl添加自定义服务
  3. 照片处理和分享的思路
  4. 2017/Province_C_C++_A/7/正则问题
  5. java mongodb gridfs_查询MongoDB GridFS元数据(Java)
  6. php软删除代码,PHP laeavel软删除以及软删除还原 易错点
  7. 【转】通过IRQL看NT内核
  8. python等待用户输入指定秒_如何在10秒后强制用户输入
  9. git rebase 合并中间的提交
  10. python3.5安装教程及环境配置_Windows7环境下Python2.7与Python3.5共存安装
  11. vmware中修改虚拟机MAC地址的方法!
  12. 多线程与多进程之间比较
  13. 数据分析实战(三) 因子分析模型挖掘CSDN优质博主
  14. 对标RTX 3060,英特尔独显或将迎来第一波主流游戏玩家
  15. PKI、X509、PKCS及证书相关等
  16. 染发染膏的认识与使用
  17. TP TN FP FN
  18. 【动手学深度学习PyTorch版】6 权重衰退
  19. App渠道推广统计:安卓渠道分析和渠道效果统计方法
  20. nginx的负载均衡模块详解

热门文章

  1. Java RMI,Socket,HttpClient
  2. 【NOI2016】循环之美【莫比乌斯反演】【整除分块】【杜教筛】【类杜教筛】
  3. CF1303F - Number of Components(并查集)
  4. Acwing 1083. Windy数
  5. Wizard of Orz CodeForces - 1467A
  6. 牛客题霸 [输出二叉树的右视图] C++题解/答案
  7. 【无码专区11】异或2(结论 / 推式子 + 哈希hash + 大整数高精度 加减乘除重载考察)
  8. [国家集训队]航班安排 (最大费用最大流)
  9. CodeForces:749(div1)750(div2)
  10. jzoj1350-游戏(某C组)【SPFA,图,最短路】