Spring Aop的原理

Spring的AOP就是通过动态代理实现的。当为某个Bean或者某些Bean配置切面时,Spring会为其创建代理对象,当调用该对象的某个方法时,实际是调用生成的代理类的对象方法。Spring的Aop主要是使用了两个动态代理,分别是JDK的动态代理和CGLIB动态代理。

1. JDK动态代理

 如果代理类实现了接口,Spring默认会使用JDK动态代理。JDK的动态代理是基于反射实现。JDK通过反射,生成一个代理类,这个代理类实现了原来那个类的全部接口,并对接口中定义的所有方法进行了代理。当我们通过代理对象执行原来那个类的方法时,代理类底层会通过反射机制,调用我们实现的InvocationHandler接口的invoke方法。
点击查看代码
/*
* 接口类
*/
public interface Person { void say();
} /*
* 接口实现类
*/
public class Man implements Person { private String word; public Man(String word){ this.word = word;
} public Man(){ } public void say(){ System.out.println("Man Can Say " + word);
}
} public class ManJDKProxy implements InvocationHandler { /**
* 需要的代理对象
*/
private Object o; public Object bind(Object o){ this.o = o;
return Proxy.newProxyInstance(o.getClass().getClassLoader(), o.getClass().getInterfaces(), this);
} @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("JDK Proxy Design");
return method.invoke(o, args);
}
} /**
* JDK动态代理
*/
public class ProxyDesign_2 { public static void main(String[] args) { Man man = new Man("Hello"); Person p = (Person)new ManJDKProxy().bind(man); p.say();
}
}

* JDK动态代理的优缺点

优点:
1. JDK动态代理是JDK原生的,不需要任何依赖即可使用
2. 通过反射机制生成代理类的速度要比CGLib操作字节码生成代理类的速度更快
缺点:
1. 如果要使用JDK动态代理,被代理的类必须实现了接口,否则无法代理(InvocationHandler)
2. JDK动态代理无法为没有在接口中定义的方法实现代理
3. JDK动态代理执行代理方法时,需要通过反射机制进行回调,此时方法执行的效率比较低

2. CGLIB动态代理

 若需要代理的类没有实现接口,JDK的动态代理就无法使用,Spring会使用CGLiB动态代理来生成代理对象。CGLiB直接操作字节码,生成类的子类,重写类的方法完成代理。
点击查看代码
/*
* 接口类
*/
public interface Person { void say();
} /*
* 接口实现类
*/
public class Man implements Person { private String word; public Man(String word){ this.word = word;
} public Man(){ } public void say(){ System.out.println("Man Can Say " + word);
}
} public class ManCGLIBProxy { public Object bind(Object target){ Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass()); enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("CGLIB Proxy Design");
return method.invoke(target, objects);
}
}); return enhancer.create();
}
} /**
* CGLIB动态代理
*/
public class ProxyDesign_3 { public static void main(String[] args) { Man man = new Man("Hello"); Person p = (Person)new ManCGLIBProxy().bind(man); p.say();
}
}

* CGLiB动态代理的优缺点

优点:
1. 使用CGLiB代理的类,不需要实现接口,因为CGLib生成的代理类是直接继承自需要被代理的类
2. 因为CGLiB实现方式是重写父类的方法,所以对final方法,或者private方法是没有办法代理的
3. CGLiB是通过修改字节码生成的代理类,所以CGLib执行代理方法的效率要高于JDK的动态代理
缺点:
1. 因为CGLiB实现方式是重写父类的方法,所以对final方法,或者private方法是没有办法代理的
2. 因为CGLiB生成代理类的方式是通过操作字节码(asm工具包),这种生成的代理类的方式比JDK通过反射生成代理类的方式的效率低

3. Spring项目中如何强制使用CGLIB代理方式

* xml方式

<!-- aop:config用来在xml中配置切面,指定proxy-target-class="true" -->
<aop:config proxy-target-class="true">
<!-- AOP相关配置 -->
</aop:config>

* @Aspect注解方式

<!-- 将proxy-target-class配置设置为true -->
<aop:aspectj-autoproxy proxy-target-class="true"/>

* 配置类注解方式

添加@EnableAspectJAutoProxy(proxyTargetClass = true)

SpringAop实现原理及代理模式的更多相关文章

  1. 大话设计模式C++实现-文章7章-代理模式

    一个.UML画画 二.概念 代理模式:为其它对象提供一种代理以控制对这个对象的訪问. 三.应用场景 (1)远程代理.也就是为一个对象在不同的地址空间提供局部代表.这样能够隐藏一个对象存在于不同地址空间 ...

  2. 代理模式(静态代理、JDK动态代理原理分析、CGLIB动态代理)

    代理模式 代理模式是设计模式之一,为一个对象提供一个替身或者占位符以控制对这个对象的访问,它给目标对象提供一个代理对象,由代理对象控制对目标对象的访问. 那么为什么要使用代理模式呢? 1.隔离,客户端 ...

  3. AOP 技术原理——代理模式全面总结

    前言 非常重要的一个设计模式,也很常见,很多框架都有它的影子.定义就不多说了.两点: 1.为其它对象提供一个代理服务,间接控制对这个对象的访问,联想 Spring 事务机制,在合适的方法上加个 tra ...

  4. springAOP之代理模式

    springAOP指的是在spring中的AOP,什么是AOP,相对于java中的面向对象(oop),在面向对象中一些公共的行为,像日志记录,权限验证等如果都使用面向对象来做,会在每个业务方法中都写上 ...

  5. 带你入门代理模式/SpringAop的运行机制

    SpringAop 是spring框架中最重要的一项功能之一,同时也是企业级开发记录事物日志等不可或缺的一部分,如果说你的系统需要记录用户访问接口的操作,那SpringAop是很完美的了,当然,拦截器 ...

  6. Java设计模式——代理模式实现及原理

    简介 Java编程的目标是实现现实不能完成的,优化现实能够完成的,是一种虚拟技术.生活中的方方面面都可以虚拟到代码中.代理模式所讲的就是现实生活中的这么一个概念:中介. 代理模式的定义:给某一个对象提 ...

  7. 重学 Java 设计模式:实战代理模式「模拟mybatis-spring中定义DAO接口,使用代理类方式操作数据库原理实现场景」

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 难以跨越的瓶颈期,把你拿捏滴死死的! 编程开发学习过程中遇到的瓶颈期,往往是由于看不 ...

  8. 从代理模式 到 SpringAOP

    前言 Spring AOP 就是通过代理模式来实现切面编程的.代理模式用来为其他对象提供一种代理,以控制对这个对象的访问. 代理对象在客户端和目标对象之间起到中介的作用.通过控制对这个对象的访问,可以 ...

  9. JAVA动态代理模式(从现实生活角度理解代码原理)

    所谓动态代理,即通过代理类:Proxy的代理,接口和实现类之间可以不直接发生联系,而可以在运行期(Runtime)实现动态关联. java动态代理主要是使用java.lang.reflect包中的两个 ...

随机推荐

  1. windows 应用商店常用软件

    QuickLook 这个应用可以让你,用空格键查看几乎任何文件的信息. 例如快速查看图片,播放视频,阅读 PDF 等等,支持的格式多到吓人.  Python 没错,就是那个非常火的编程语言,Pytho ...

  2. 跟k8s工作负载Deployments的缘起缘灭

    跟k8s工作负载Deployments的缘起缘灭 考点之简单介绍一下什么是Deployments吧? 考点之怎么查看 Deployment 上线状态? 考点之集群中能不能设置多个Deployments ...

  3. Spark学习笔记(详细)

    Spark Core 第1章 Spark 概述 Spark是一种基于内存的快速.通用.可扩展的大数据分析计算引擎 Spark和Hadoop 的根本差异是多个作业之间的数据通信问题: Spark多个作业 ...

  4. 60天shell脚本计划-9/12-渐入佳境

    --作者:飞翔的小胖猪 --创建时间:2021年3月8日 --修改时间:2021年3月12日 说明 每日上传更新一个shell脚本,周期为60天.如有需求的读者可根据自己实际情况选用合适的脚本,也可在 ...

  5. 报错:net::err_unknown_url_scheme的解决办法

    在项目中设置了api请求和web页面请求的地址,如下图: 控制台报错,如下图: 问题是:没有加入"http://"这个头,因此访问不到. 解决办法: 再次访问正常

  6. 一个更好用的.NET Core程序瘦身器,减小程序尺寸到1/3

    一.为什么要开发.NET Core程序瘦身器? .NET Core具有[剪裁未使用的代码]的功能,但是由于它是使用静态分析来实现的,因此它的剪裁效果并不是最优的.它有如下两个缺点: 不支持Window ...

  7. winform中更新UI控件的方案介绍

    这是一个古老的话题...直入主题吧! 对winfrom的控件来说,多线程操作非常容易导致复杂且严重的bug,比如不同线程可能会因场景需要强制设置控件为不同的状态,进而引起并发.加锁.死锁.阻塞等问题. ...

  8. Lua中如何实现类似gdb的断点调试—08支持通过包名称添加断点

    在前一篇中我们支持了通过函数名称来添加断点,我们同时也提到了在Lua中一个函数的名称的并不是确定的.准确的说,Lua中的函数并没有名称,所谓名称其实是保存这个函数值的变量的名称. 于是通过函数名称添加 ...

  9. Linux性能优化实战内存篇(五)

    一.Linux内存工作原理 1,内存映射 Linux内核给每个进程都提供了一个独立的虚拟空间,并且这个地址空间是连续的.这样,进程就可以很方便地访问内存,更确切地说是访问虚拟内存. 虚拟地址空间的内部 ...

  10. vue学习过程总结(05) - vue的重要插件vue-router

    vue-router的中文文档:https://router.vuejs.org/zh/installation.html(基于文档的摘抄) 1.vue中的组件与插件 转载:https://blog. ...