Spring 温习笔记(三)动态代理

灰太狼 2023-01-10 15:59 208阅读 0赞

引言

上两章小猿复习的是有关springIOC的有关内容,其实在本质上来讲,什么是IOC,IOC(inverse of control)可以通俗的理解程序在运行过程中,我们将更多的实例创建权交由spring容器来管理,这种管理能较大程度上减少硬编码导致的耦合,提高代码质量。这是java编程中的核心思想之一。
然而接下来问题又出现了,当我们需要修改某项功能比如代码增强,是直接对原有类进行重新编写吗?
答案肯定是否定的,因为在一个项目中我们是不能轻易去改动一个类的内容,如果直接改动可能会导致跟该类有联系的类都需要修改,这样就导致改动代码的复杂度较大程度上提高,那么还有没有其他办法呢,办法当然有,那就是我们的先辈圣者们提出的AOP(aspect oriented programming)思想。在学习动态代理之前我们需要明白反射原理,需要了解反射原理的童鞋请参考小猿的笔记java程序运行过程及反射
下文小猿开始复习AOP之动态代理。

AOP 动态代理

AOP意思为面向切面编程,是通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。通过AOP编程我们可以了达到在不修改程序源代码的情况系,对程序实现代码增强。
AOP动态代理包含jdk动态代理和cglib

公共类

增强类

  1. public class Advice {
  2. public void before(){
  3. System.out.println("前置增强");
  4. }
  5. public void after(){
  6. System.out.println("后置增强");
  7. }
  8. }

目标类

  1. public class TargetImpl implements Target {
  2. public void save() {
  3. System.out.println("执行了targetSave方法");
  4. }
  5. }

目标接口

  1. public interface Target {
  2. public void save();
  3. }

jdk动态代理

  1. public class JdkProxy {
  2. public static void main(String[] args) {
  3. final Target target = new TargetImpl();
  4. final Advice advice = new Advice();
  5. Target proxyInstance = (Target) Proxy.newProxyInstance(target.getClass().getClassLoader(),
  6. target.getClass().getInterfaces(),
  7. new InvocationHandler() {
  8. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  9. advice.before();
  10. Object invoke = method.invoke(target, args);
  11. advice.after();
  12. return null;
  13. }
  14. });
  15. proxyInstance.save();
  16. }
  17. }

cgilib 动态代理

  1. public class CglibProxy {
  2. public static void main(final String[] args) {
  3. final Target target = new TargetImpl();
  4. final Advice advice = new Advice();
  5. //1.创建增强器
  6. Enhancer enhancer = new Enhancer();
  7. //设置父类
  8. enhancer.setSuperclass(target.getClass());
  9. //设置回调
  10. enhancer.setCallback(new MethodInterceptor() {
  11. public Object intercept(Object o, Method method, Object[] objects,
  12. MethodProxy methodProxy) throws Throwable {
  13. advice.before();
  14. Object invoke = method.invoke(target, args);
  15. advice.after();
  16. return null;
  17. }
  18. });
  19. //创建代理对象
  20. Target proxy = (Target) enhancer.create();
  21. proxy.save();
  22. }

jdk动态代理和cgilib动态动态代理的区别

  1. jdk中代理对象和原对象是兄弟关系,即用原对象不可以直接接受代理对象,
  2. CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法,因为是继承,所以该类或方法最好不要声明成final 。
  3. 另外从一些大猿的文章中小猿的是jdk动态代理创建代理对象的速度略大于cgilib创建代理的速度,cgilb需要对目标对象的字节码进行解析,所以其创建代理对象的速度略慢一些。
  4. cglib 运行速度较快,但是CGLIB的大部分类是直接对Java字节码进行操作,这样生成的类会在Java的永久堆中,这样就可能导致永久堆满,触发OutOfMemory异常。

发表评论

表情:
评论列表 (有 0 条评论,208人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Spring4笔记----动态代理

    代理设计模式的原理: 使用一个代理将对象包装起来, 然后用该代理对象取代原始对象. 任何对原始对象的调用都要通过代理. 代理对象决定是否以及何时将方法调用转到原始对象上. 也