Spring中不同生命週期Bean的依賴管理

2022-05-13 10:28:44 字數 2918 閱讀 5298

在使用spring時,可能會遇到這種情況:乙個單例的bean依賴另乙個非單例的bean。如果簡單的使用自動裝配來注入依賴,就可能會出現一些問題,如下所示:

@component

public class classa

}

@component

@scope(value = scope_prototype)

public class classb

}

這裡class a採用了預設的單例scope,並依賴於class b, 而class b的scope是prototype,因此不是單例的,這時候跑個測試就看出這樣寫的問題:

@runwith(springrunner.class)

@contextconfiguration(classes = )

public class mytest

}}

輸出的結果是:

this is class a: classa@282003e1

this is class b: classb@7fad8c79

this is class a: classa@282003e1

this is class b: classb@7fad8c79

this is class a: classa@282003e1

this is class b: classb@7fad8c79

可以看到,兩個類的hash code在三次輸出中都是一樣。class a的值不變是可以理解的,因為它是單例的,但是class b的scope是prototype卻也保持hash code不變,似乎也成了單例?

產生這種的情況的原因是,class a的scope是預設的singleton,因此context只會建立class a的bean一次,所以也就只有一次注入依賴的機會,容器也就無法每次給class a提供乙個新的class b

@component

public void printclass()

public classb getclassb()

}}

這樣就能夠在每次需要到class b的時候手動去context裡找到新的bean。再跑一次測試後得到了以下輸出:

this is class a: com.devhao.classa@4df828d7

this is class b: com.devhao.classb@31206beb

this is class a: com.devhao.classa@4df828d7

this is class b: com.devhao.classb@3e77a1ed

this is class a: com.devhao.classa@4df828d7

this is class b: com.devhao.classb@3ffcd140

可以看到class ahash code在三次輸出中保持不變,而class b的卻每次都不同,說明問題得到了解決,每次呼叫時用到的都是新的例項。

但是這樣的寫法就和spring強耦合在一起了,spring提供了另外兩種方法來降低侵入性。

spring提供了乙個名為@lookup的註解,這是乙個作用在方法上的註解,被其標註的方法會被重寫,然後根據其返回值的型別,容器呼叫beanfactorygetbean()方法來返回乙個bean。

@component

public class classa

@lookup

public classb getclassb()

}

可以發現簡潔了很多,而且不再和spring強耦合,再次執行測試依然可以得到正確的輸出。

被標註的方法的返回值不再重要,因為容器會動態生成乙個子類然後將這個被註解的方法重寫/實現,最終呼叫的是子類的方法。

使用的@lookup的方法需要符合如下的簽名:

[abstract] themethodname(no-arguments);
spring還提供了另外一種方法來解決這個問題。簡單來說就是如果乙個bean a對另外乙個作用域更短的bean b有依賴,那麼在例項化bean a並注入依賴時,注入的不是bean b本身,而是乙個aop**,這個**可以找到實際的bean

@component

public class classa

}

@component

@scope(value = scope_prototype, proxymode = scopedproxymode.target_class)

public class classb

}

可以看出,使用這種方法的好處是僅需對bean b進行簡單的配置,並且bean a根本不用意識到**的存在,將bean b當做乙個正常的bean來裝載就好。

spring 生命週期

spring 生命週期 ioc容器 1 載入配置檔案 2 資源定位 3 資源解析 4 生成beandefinition元資訊 5 通過工廠把beandefinition載入到容器中 初始化bean例項,由spring產生的bean預設是單例的 依賴注入,就是處理的,bean引用bean的問題 ioc...

Spring 生命週期

public void refresh throws bean ception,illegalstateexception catch bean ception ex 1.preparerefresh 用於設定spring啟動時間並且設定active flag 為true 2.configurabl...

Spring生命週期

1.容器啟動,例項化所有實現了beanfactorypostprocessor介面的類.它會在任何普通bean例項化之前載入.2.例項化剩下的bean,對這些bean進行依賴注入.3.如果bean有實現beannameaware的介面那麼對這些bean進行呼叫 4.如果bean有實現beanfact...