2011-11-01 148 views
5

我正在玩Spring AOP。Spring AOP创建额外的bean

下面是一个简单的类

public class CModel extends Car { 
    private double torqueMeasure = 1; 

    public CModel() { 
     System.out.println(" C-Model constructor");   
    } 
} 

和Spring的配置是这样的

<aop:config> 
    <aop:aspect ref="audit"> 
     <aop:before pointcut="execution(* com.test.main..*(..))" method="firstControl"/> 
      ... 
    </aop:aspect> 
</aop:config> 

现在好了;当我添加aop:config并截取CModel时,Spring会调用CModel构造函数两次。这意味着Spring会创建2个CModel对象,对吧?

如果我删除AOP配置,那么Spring只创建一个CModel对象。

任何想法为什么它是这样的?

谢谢。

+1

我认为spring为它创建了这个bean和代理。动态代理类扩展了基类,所以它应该在其构造函数中调用super()。您可以在CModel构造函数中打印堆栈跟踪,以确保(像新的Exception()。printStackTrace())。 – svaor

回答

5

虽然我不确定,但我的猜测是,Spring首先实例化常规类,然后创建一个CGLIB代理,它是一个子类。请注意,对于初始化,您应该使用@PostConstruct,这是保证使用一次。

为了验证我的假设,在构造函数中添加一个断点,看看当它被调用 - 一个时代,应该在CModel$EnhancedByCGLIB东西后是正确的

+1

我认为你是对的。我实际上在[最近]上发表了博客(http://nurkiewicz.blogspot.com/2011/10/spring-pitfalls-proxying.html),也许OP会在那里找到一些进一步的细节。顺便说一句,有更简单的方法来验证这一点:'System.out.println(this)' - 第二行打印的行会产生类似于'CModel $ EnhancedByCGLIB'的东西。 –

+3

它被记录在[7.6代理机制](http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/aop.html#aop-proxying) – axtavt

3

当春天创建一个代理类,它会使用CGLIB生成一个类CModel的子类。净影响是你的构造函数将被调用两次。

检查出详细的Spring文档(特别是第三颗子弹): - 与JDK代理机制 http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/aop.html#aop-proxying

作为一个侧面说明,Spring会,如果你的类实现一个接口使用JDK代理机制不会调用你的构造函数。

+1

Darn - 看起来像我被打了一拳:)对不起,重复的答案。 – wmkoch