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 中 JDK 和 CGLib 动态代理哪个更快?
5. **配置代理**:Spring会根据目标对象是否实现了接口来决定使用JDK动态代理还是CGLIB代理。如果目标对象实现了接口,Spring会选择JDK动态代理。动态代理类会继承自`java.lang.reflect.Proxy`,并实现目标对象的...
JDK 动态代理是 Java 自带的动态代理机制,它只能代理接口,而不能代理类。这是因为 JDK 动态代理是基于接口的代理,它需要一个接口来生成代理类。如果我们想使用 JDK 动态代理,必须提供一个接口,并且将其实现类...
Spring框架是AOP实现的一个典范,它提供了两种主要的动态代理方式:JDK动态代理和CGLib动态代理。 **JDK动态代理**: JDK动态代理基于Java的反射API实现,适用于接口代理。当目标对象实现了至少一个接口时,Spring...
Spring AOP主要通过两种方式实现:JDK动态代理和CGLIB代理。 - **JDK动态代理**: - 当目标对象实现了至少一个接口时,Spring会使用JDK的java.lang.reflect.Proxy类创建一个代理对象。 - 代理对象在调用实际方法...
总结一下,Spring的AOP机制通过JDK动态代理和CGLIB动态代理提供了强大的横切关注点管理功能。开发者可以轻松地定义切面和通知,以实现如日志、事务管理等功能,同时保持核心业务代码的清晰和简洁。在Spring Boot项目...
Spring AOP提供了两种代理方式:JDK动态代理和Cglib代理。 Cglib代理是Spring AOP在无法使用JDK动态代理(例如代理的目标对象没有实现接口)时的另一种选择。Cglib是一个强大的、高性能的代码生成库,它基于ASM库来...
Spring AOP则是在Spring框架中对AOP概念的实现,它利用了JDK动态代理或CGLIB(字节码增强)来实现。Spring AOP的主要目标是分离关注点,将非业务逻辑(如日志、事务管理)从核心业务代码中解耦出来。以下是Spring ...
在 Spring 中,AOP 的实现主要依赖于代理模式,有两种代理方式:JDK 动态代理和 CGLIB 动态代理。 JDK 动态代理是基于接口的,它要求被代理的目标对象必须实现至少一个接口。Spring 使用 `java.lang.reflect.Proxy`...
总的来说,Spring AOP通过CGLIB提供了一种强大的动态代理机制,允许我们在不修改源代码的情况下,为已有类添加额外的行为。在实际项目中,根据需求和性能考虑,我们可以灵活选择JDK动态代理或CGLIB代理来实现面向切...
本文将深入探讨Spring AOP中的JDK动态代理机制。 首先,我们要理解什么是动态代理。动态代理是在运行时创建一个实现了一组给定接口的代理类,这个代理类可以拦截并处理方法调用,从而实现一些额外的功能。JDK的动态...
当目标对象实现了至少一个接口时,Spring将使用JDK的动态代理机制。JDK动态代理通过实现InvocationHandler接口,并在运行时动态生成一个实现了目标对象所有接口的代理类。 - **JDK动态代理**:JDK的java.lang....
在"通过Configuration文件实现AOP.docx"文档中,可能会详细讲述如何在Spring配置文件中配置AOP代理,包括如何选择使用JDK动态代理还是CGLIB。 总结来说,JDK动态代理简单且高效,适合接口驱动的设计,而CGLIB适用于...
Spring AOP支持不同的代理策略,包括JDK动态代理和CGLIB代理。如果被代理的类没有实现接口,Spring AOP会采用CGLIB来生成代理对象。CGLIB(Code Generation Library)是一个开源的代码生成库,它允许运行时在内存中...
本资源将深入探讨Spring框架中使用的两种关键的动态代理方式:JDK动态代理和CGLib动态代理。这两种代理方式在Spring AOP中起到关键作用,用于实现横切关注点的切面编程。通过学习它们的原理和实际应用,您将能够更好...
2. **动态代理**:为了解决静态代理的局限性,Spring提供了基于Java动态代理(JDK Proxy)和CGLIB的动态代理机制。在动态代理中,我们不再需要手动创建代理类,而是通过实现`InvocationHandler`接口创建一个代理对象...
总的来说,Spring AOP通过代理和通知机制,实现了横切关注点的模块化,使得业务逻辑与系统服务(如日志、事务等)解耦,提高了代码的可读性和可维护性。同时,引介功能进一步增强了切面的功能,可以为对象动态地添加...
总的来说,Java动态代理机制为我们提供了灵活的代码扩展性,可以根据需要选择JDK、CGLIB、Javassist或ASM来实现不同的代理需求。理解并掌握这些技术,能帮助我们在开发过程中更加高效地实现功能扩展和代码解耦。在...
1. **代理**:Spring AOP支持两种类型的代理:JDK动态代理和CGLIB代理。JDK代理用于实现了接口的类,而CGLIB代理则用于没有接口或不希望使用接口的类。代理对象在调用目标方法时会执行切面逻辑。 2. **织入**:织入...
如果一个类实现了一个或多个接口,那么Spring就会使用默认的JDK动态代理,如果没有实现任何接口,就会使用cglib来代理。当然我们也可以手动改变这些设置。这也是比较容易掉坑的部分,如果设置错了代理方式,那么在...