Spring AOP使用JDK动态代理或者CGLIB来为目标对象创建代理。(建议优先使用JDK的动态代理)
如果被代理的目标对象实现了至少一个接口,则会使用JDK动态代理。所有该目标类型实现的接口都将被代理。 若该目标对象没有实现任何接口,则创建一个CGLIB代理。
如果你希望强制使用CGLIB代理,(例如:希望代理目标对象的所有方法,而不只是实现自接口的方法) 那也可以。但是需要考虑以下问题:
强制使用CGLIB代理需要将<aop:config>的proxy-target-class属性设为true:
1 |
< aop:config proxy-target-class = "true" >
|
当使用@AspectJ自动代理时要强制使用CGLIB,请将<aop:aspectj-autoproxy>的proxy-target-class属性设置为true:
<aop:aspectj-autoproxy proxy-target-class="true"/>
Spring AOP是基于代理机制的。深刻领会这一句的意思是非常重要的。
考虑如下场景,当你拿到一个无代理的、无任何特殊之处的POJO对象引用时,如以下代码段所示
01 |
public class SimplePojo implements Pojo {
|
当你调用一个对象引用的方法时,此对象引用上的方法直接被调用,如下所示
1 |
public static void main(String[] args) {
|
2 |
Pojo pojo = new SimplePojo();
|
当客户代码所持有的引用是一个代理的时候则略有不同了。请考虑如下图示和代码段片断
1 |
ProxyFactory proxyFactory = new ProxyFactory( new SimplePojo());
|
2 |
proxyFactory.addInterface(Pojo. class );
|
4 |
proxyFactory.addAdvice( new BeforeAdviceImpl());
|
6 |
Pojo pojo = (Pojo) proxyFactory.getProxy(); |
理解此处的关键方法中的客户代码 拥有一个代理的引用。这意味着对这个对象引用中方法的调用就是对代理的调用, 而这个代理能够代理所有跟特定方法调用相关的拦截器。不过,一旦调用最终抵达了目标对象 (此处为SimplePojo类的引用),任何对自身的调用例如this.bar()或者this.foo()将对this引用进行调用而非代理。这一点意义重大, 它意味着自我调用将不会导致和方法调用关联的通知得到执行的机会。
那好,为此要怎么办呢?最好的办法就是重构你的代码使自我调用不会出现。 当然,这的确需要你做一些工作,但却是最好的,最少侵入性的方法。另一个方法则很可怕, 也正因为如此我几乎不愿指出这种方法。你可以象如下这样完全把业务逻辑写在你的Spring AOP类中:
01 |
public class SimplePojo implements Pojo {
|
04 |
((Pojo) AopContext.currentProxy()).bar();
|
这样完全将你的代码交给了Spring AOP, 并且让类本身知道它正被用于一个AOP的上下文中, 而它其中的文件直接面对AOP。当代理在被创建时也需要一些额外的配置:
01 |
public static void main(String[] args) {
|
02 |
ProxyFactory factory = new ProxyFactory( new SimplePojo());
|
03 |
factory.adddInterface(Pojo. class );
|
04 |
factory.addAdvice( new RetryAdvice());
|
05 |
factory.setExposeProxy( true );
|
07 |
Pojo pojo = (Pojo) factory.getProxy();
|
上面的例子中用到了Spring AOP中ProxyFactory这些特定的API。在使用Spring容器配置的环境下也同样有此问题,同样以之前的支付为例:
01 |
public interface IPayService {
|
02 |
String pay( long userId, long money);
|
07 |
public class RMBPayService implements IPayService {
|
08 |
private static final Logger LOGGER = LoggerFactory.getLogger(RMBPayService. class );
|
11 |
public String pay( long userId, long money) {
|
12 |
LOGGER.info( "用户:" + userId + "使用人民币支付金额:" + money);
|
18 |
public String inner() {
|
19 |
LOGGER.info( "inner method,can you see the aop advice...." );
|
这样从容器中获取RMBPayService实例对象时,调用pay()方法,则只能在pay()方法环境下看到aop的特性,而在inner()中则看不到,可以使用如下方法来解决(虽然不建议):
02 |
public class RMBPayService implements IPayService {
|
03 |
private static final Logger LOGGER = LoggerFactory.getLogger(RMBPayService. class );
|
06 |
public String pay( long userId, long money) {
|
07 |
LOGGER.info( "用户:" + userId + "使用人民币支付金额:" + money);
|
09 |
ApplicationContext ctx = new ClassPathXmlApplicationContext( "applicationContext.xml" );
|
11 |
IPayService service = ctx.getBean(RMBPayService. class );
|
17 |
public String inner() {
|
19 |
LOGGER.info( "inner method,can you see the aop advice...." );
|
分享到:
相关推荐
Spring-AOP-利用java中的动态代理和Spring的拦截器做到AOP
AOP之JDK动态代理和CGLib动态代理 ,具体效果和过程看博文 http://blog.csdn.net/evankaka/article/details/45195383
spring之AOP(动态代理),包括jdk动态代理和CGLib动态代理
Spring框架的AOP中重要的一个知识点,动态代理,springAOP框架会根绝实际情况选择使用jdk的动态代理还是cglib的动态代理
本资源将深入探讨Spring框架中使用的两种关键的动态代理方式:JDK动态代理和CGLib动态代理。这两种代理方式在Spring AOP中起到关键作用,用于实现横切关注点的切面编程。通过学习它们的原理和实际应用,您将能够更好...
SpringAOP动态代理 Spring AOP 使用的动态代理主要有两种方式:JDK 动态代理和 CGLIB 代理。 JDK 动态代理:用于代理实现了接口的类。Spring 会使用 java.lang.reflect.Proxy 类来创建代理对象。 CGLIB 代理:用于...
主要对Spring AOP的相关概念和简单的静态代理、动态代理以及常见的几种AOP配置方式做总结学习。主要包括:1. AOP的常见概念 2. 静态代理 3. jdk动态代理 4. Aspectj and Aspectjweaver 5. **aop-config** 6. CGLIB ...
如果一个类实现了一个或多个接口,那么Spring就会使用默认的JDK动态代理,如果没有实现任何接口,就会使用cglib来代理。当然我们也可以手动改变这些设置。这也是比较容易掉坑的部分,如果设置错了代理方式,那么在...
静态代理--不适合企业开发,适合初学者理解代理。 jdk动态代理--适合企业级开发,但是它要求必须面向接口编程,假如目标类没有实现接口...spring 的AOP功能中 会根据目标类是否实现了接口来判断使用 jdk Proxy还是cglib
3、如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换 如何强制使用CGLIB实现AOP? * 添加CGLIB库,SPRING_HOME/cglib/*.jar * 在spring配置文件中加入<aop:aspectj-...
SpringAop面向切面编程
Spring框架是一个开放源代码的J2EE应用程序框架,是对bean的生命周期进行管理的轻量...Spring框架主要由七部分组成,分别是Spring Core,Spring AOP,Spring ORM,Spring DAO,Spring Context,Spring Web和Spring Web MVC。
动态代理是实现AOP的基础,它通过JDK动态代理或CGLIB代理生成被代理对象的子类。通知是织入到目标对象连接点上的一段程序,例如@Before、@After等。 切点定义了通知应该在哪些连接点上触发。而切面则是通知和切点的...
使用JDK中的Proxy技术实现AOP功能与使用CGLIB实现AOP功能
写了SpringAop的两种代理的实现,jdk动态代理和cglib代理的代码,及测试。
哪怕没有看过源码的同学也应该知道,AOP是通过动态代理实现的,动态代理又分为两个部分:JDK动态代理和CGLIB动态代理 确实,Spring也就是通过这两种方式来实现AOP相关功能,下面就通过源码来简单求证下
一 AOP的基本概念 (1)Aspect(切面):通常是一个类,里面可以定义切入点和通知 (2)JointPoint(连接点):程序执行过程中明确的点,...Spring中的AOP代理可以使JDK动态代理,也可以是CGLIB代理,前者基于接口,后者基于子类
SpringBoot下的Spring——DAY04——动态代理总结、AOP、自定义注解进行拦截、动态获取注解参数、通知方法 1.动态代理总结 1.1 JDK动态代理特点 1.2 CGlib动态代理 1.2.1 CGLib特点说明 1.3 动态代理的作用 2 Spring...
spring中动态代理机制的实现原理及AOP实现原理,JDK的反射,cglib类。
1、编写切面类,包含权限审核方法和日志记录方法,这两个方法将来会织入到...5、编写案例,运用Spring AOP技术,要求包含前置通知、后置通知、环绕通知、返回通知、异常返回通知。请掌握这五种通知的特点,及应用场景