2017-01-03 162 views
1

我有以下類別:使用Spring @Lazy和@PostConstruct註解

@Repository 
class A { 

    public void method1() { 
     ... 
    } 
} 

@Component 
class B implements C { 

    @Autowired 
    @Lazy 
    private A a; 

    public void method2() { 
     a.method1(); 
    } 
} 

@Component 
class D { 

    @Autowired 
    private List<C> c; 

    @PostConstruct 
    public void method3() { 
     // iterate on list c and call method2() 
    } 
} 

讓我們假設初始化春豆如下:創建
1.首先bean B實例。當bean B正在創建時,由於@Lazy註釋,字段a將不會被初始化。
2.下一個bean D被創建。然後method3()將被執行,因爲它被標記爲@PostConstruct,但bean A尚未被Spring觸及。所以當a.method1()被調用時,Spring會創建bean A並將其注入到字段a中,否則它會拋出一個NullPointerException

+2

您是否嘗試過運行相同的設置? – Arpit

+0

@Arpit是的,我做了,它確實注入到一個。但是我不能保證Spring是先來到A還是去D.如果先來到A,它將能夠在執行method3()的同時注入A.如果它首先出現在D,那麼問題可能會出現。 – rohanagarwal

回答

4

您需要了解當您將@Lazy指定爲注射的一部分時發生了什麼。根據documentation

除了其對組件初始化作用下,@Lazy 註釋也可放置在標有 @Autowired@Inject注入點。在這種情況下,它導致注入一個懶惰解析代理。

這意味着在開始時Spring將注入代理類的實例而不是類A的實例。代理類是自動生成的類,與類A具有相同的接口。任何方法代理的第一次調用將在自己內部創建類A的實例。之後,所有方法的調用將被重定向到代理內部的A類的這個實例。

所以沒有理由擔心任何問題。

+1

我確實測試過,是的它的工作原理。我已經驗證過NPE不會被拋出,並且在第一次調用時創建(A的實例)。添加一些關於代理的解釋,以使事情更加清晰: 代理是另一個對象的替代對象或佔位符,用於控制對其的訪問。由於代理位於對象的調用者和實際對象本身之間,它可以決定阻止調用真實(或目標)對象,或者在調用目標對象之前執行某些操作。 – rohanagarwal