spring對bean的高級裝配之基於@Conditional條件化裝配


  上篇介紹了如何基於profile來條件化創建bean,spring會根據profile的激活狀態來進行創建;這篇介紹如何基於spring4.0引入的@Conditional和Condition接口來更加完美的創建bean;

  假設你希望一個或多個bean只有在應用的類路徑下包含特定的庫時才創建。或者我們希望某個bean只有當另外某個特定的bean也聲明了之后才會創建。我們還可能要求只有某個特定的環境變量設置之后,才會創建某個bean。在Spring 4之前,很難實現這種級別的條件化配置,但是Spring 4引入了一個新的@Conditional注解,它可以用到帶有@Bean注解的方法上。如果給定的條件計算結果為true,就會創建這個bean,否則的話,這個bean會被忽略。下面舉例說明:

  假設有一個名為MagicBean的類,我們希望只有設置了magic環境屬性的時候,Spring才會實例化這個類。如果環境中沒有這個屬性,那么MagicBean將會被忽略。下面使用@Conditional注解條件化地配置MagicBean:

 代碼中給@Conditional注解傳了一個 我們自己開發的MagicExistsCondition的class,MagicExistsCondition必須要實現Condition接口,因為@Conditional就是基於Condition接口來進行條件比對的,下面是Condition接口的關鍵代碼:

可以看到此接口有一個matches方法.當其返回true就會創建帶有@Conditional注解的bean。如果matches()方法返回false,將不會創建這些bean;所以我們的MagicExistsCondition只要實現這個方法就可以了,下面是MagicExistsCondition代碼:

matches()方法很簡單但功能強大。它通過給定的ConditionContext對象進而得到Environment對象,並使用這個對象檢查環境中是否存在名為magic的環境屬性。在本例中,屬性的值是什么無所謂,只要屬性存在即可滿足要求。如果滿足這個條件的話,matches()方法就會返回true。所帶來的結果就是條件能夠得到滿足,所有@Conditional注解上引用MagicExistsCondition的bean都會被創建。如果magic這個屬性不存在方法就會返回false從而不會創建這些bean;

下面記錄下matches這個方法的兩個強大的參數ConditionContext和AnnotatedTypeMetadata

一、ConditionContext

關鍵源碼:

通過ConditionContext,我們可以做到如下幾點:

  1、借助getRegistry()返回的BeanDefinitionRegistry檢查bean定義;

  2、借助getBeanFactory()返回的ConfigurableListableBeanFactory檢查bean是否存在,甚至探查bean的屬性;

  3、借助getEnvironment()返回的Environment檢查環境變量是否存在以及它的值是什么;

  4、讀取並探查getResourceLoader()返回的ResourceLoader所加載的資源;

  5、借助getClassLoader()返回的ClassLoader加載並檢查類是否存在。

 二、AnnotatedTypeMetadata(能夠讓我們檢查帶有@Bean注解的方法上還有什么其他的注解)

關鍵源碼:

借助isAnnotated()方法,我們能夠判斷帶有@Bean注解的方法是不是還有其他特定的注解。借助其他的那些方法,我們能夠檢查@Bean注解的方法上其他注解的屬性。

需要 注意的是,從spring4開始,上篇提到@Profile注解的實現原理也是基於@Conditional和Condition的實現了,下面是Profile的源碼:

可以看到@Profile提供了ProfileCondition來實現了Condition接口,下面我們看下ProfileCondition是如何實現matches方法的:

我們可以看到,ProfileCondition通過AnnotatedTypeMetadata得到了用於@Profile注解的所有屬性。借助該信息,它會明確地檢查value屬性,該屬性包含了bean的profile名稱。然后,它根據通過ConditionContext得到的Environment來檢查[借助acceptsProfiles()方法]該profile是否處於激活狀態

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM