2011-11-01 62 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