Spring註解開發總結

1,@Configuration 

//配置類==配置文件

@Configuration  //告訴Spring這是一個配置類

一句話概括就是 @Configuration 中所有帶 @Bean 註解的方法都會被動態代理,因此調用該方法返回的都是同一個實例。

@Configuration 註解:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {
    String value() default "" ;
}

從定義來看, @Configuration 註解本質上還是 @Component,因此 <context:component-scan/> 或者 @ComponentScan 都能處理@Configuration 註解的類。

@Configuration 標記的類必須符合下面的要求:

  • 配置類必須以類的形式提供(不能是工廠方法返回的實例),允許通過生成子類在運行時增強(cglib 動態代理)。
  • 配置類不能是 final 類(沒法動態代理)。
  • 配置註解通常爲了通過 @Bean 註解生成 Spring 容器管理的類,
  • 配置類必須是非本地的(即不能在方法中聲明,不能是 private)。
  • 任何嵌套配置類都必須聲明爲static
  • @Bean 方法可能不會反過來創建進一步的配置類(也就是返回的 bean 如果帶有 @Configuration,也不會被特殊處理,只會作爲普通的 bean)。

 

加載過程

Spring 容器在啓動時,會加載默認的一些 PostPRocessor,其中就有 ConfigurationClassPostProcessor,這個後置處理程序專門處理帶有 @Configuration 註解的類,這個程序會在 bean 定義加載完成後,在 bean 初始化前進行處理。主要處理的過程就是使用 cglib 動態代理增強類,而且是對其中帶有 @Bean 註解的方法進行處理。

2,@Bean

Spring@Bean註解用於告訴方法,產生一個Bean對象,然後這個Bean對象交給Spring管理。產生這個Bean對象的方法Spring只會調用一次,隨後這個Spring將會將這個Bean對象放在自己的IOC容器中。默認bean的名稱就是其方法名。但是也可以指定名稱;

使用@Bean註解的好處就是能夠動態獲取一個Bean對象,能夠根據環境不同得到不同的Bean對象。或者說將Spring和其他組件分離(其他組件不依賴Spring,但是又想Spring管理生成的bean)。

//給容器中註冊一個Bean;類型爲返回值的類型,id默認是用方法名作爲id

   @Bean("person")

   public Person person01(){

      return new Person("lisi", 20);

   }

類似beans.xml

 

 

3,@ComponentScans

@ComponentScan是告訴Spring 哪個packages 的用註解標識的類 會被spring自動掃描並且裝入bean容器。

基本的basePackages參數是用於掃描帶註釋組件的基本包。那麼excludeFilters呢?其他參數呢?

basePackageClasses:對basepackages()指定掃描註釋組件包類型安全的替代。

excludeFilters:指定不適合組件掃描的類型。

includeFilters:指定哪些類型有資格用於組件掃描。

lazyInit:指定是否應註冊掃描的beanslazy初始化。

nameGenerator:用於在Spring容器中的檢測到的組件命名。

resourcePattern:控制可用於組件檢測的類文件。

scopedProxy:指出代理是否應該對檢測元件產生,在使用過程中會在代理風格時尚的範圍是必要的。

scopeResolver:用於解決檢測到的組件的範圍。

useDefaultFilters:指示是否自動檢測類的註釋 

@ComponentScans(

      value = {

           @ComponentScan(value="com.dths",includeFilters = {

/*               @Filter(type=FilterType.ANNOTATION,classes={Controller.class}),

                 @Filter(type=FilterType.ASSIGNABLE_TYPE,classes={BookService.class}),*/

                 @Filter(type=FilterType.CUSTOM,classes={MyTypeFilter.class})

           },useDefaultFilters = false)  

      }

      )

//@ComponentScan  value:指定要掃描的包

//excludeFilters = Filter[] :指定掃描的時候按照什麼規則排除那些組件

//includeFilters = Filter[] :指定掃描的時候只需要包含哪些組件

//FilterType.ANNOTATION:按照註解

//FilterType.ASSIGNABLE_TYPE:按照給定的類型;

//FilterType.ASPECTJ:使用ASPECTJ表達式

//FilterType.REGEX:使用正則指定

//FilterType.CUSTOM:使用自定義規則

自定義TypeFilter指定過濾規則

 

4,@Scope, @Lazy

Scope,也稱作用域,在 Spring IoC 容器是指其創建的 Bean 對象相對於其他 Bean 對象的請求可見範圍。在 Spring IoC 容器中具有以下幾種作用域:基本作用域(singletonprototype),Web 作用域(reqeustsessionglobalsession),自定義作用域。 
1
Spring 的作用域在裝配 Bean 時就必須在配置文件中指明,配置方式如下(以 xml 配置文件爲例):

<!-- 具體的作用域需要在 scope 屬性中定義 -->
<bean id="XXX" class="com.XXX.XXXXX" scope="XXXX" />

singleton:單例模式,在整個Spring IoC容器中,使用singleton定義的Bean將只有一個實例。

prototype:原型模式,每次通過容器的getBean方法獲取prototype定義的Bean時,都將產生一個新的Bean實例。

request:對於每次HTTP請求,使用request定義的Bean都將產生一個新實例,即每次HTTP請求將會產生不同的Bean實例。只有在Web應用中使用Spring時,該作用域纔有效。

session:對於每次HTTP Session,使用session定義的Bean豆漿產生一個新實例。同樣只有在Web應用中使用Spring時,該作用域纔有效。

globalsession:每個全局的HTTP Session,使用session定義的Bean都將產生一個新實例。典型情況下,僅在使用portlet context的時候有效。同樣只有在Web應用中使用Spring時,該作用域纔有效。

  其中比較常用的是singletonprototype兩種作用域。對於singleton作用域的Bean,每次請求該Bean都將獲得相同的實例。容器負責跟蹤Bean實例的狀態,負責維護Bean實例的生命週期行爲;如果一個Bean被設置成prototype作用域,程序每次請求該idBeanSpring都會新建一個Bean實例,然後返回給程序。在這種情況下,Spring容器僅僅使用new 關鍵字創建Bean實例,一旦創建成功,容器不在跟蹤實例,也不會維護Bean實例的狀態。

  如果不指定Bean的作用域,Spring默認使用singleton作用域。Java在創建Java實例時,需要進行內存申請;銷燬實例時,需要完成垃圾回收,這些工作都會導致系統開銷的增加。因此,prototype作用域Bean的創建、銷燬代價比較大。而singleton作用域的Bean實例一旦創建成功,可以重複使用。因此,除非必要,否則儘量避免將Bean被設置成prototype作用域。 
   
 2、基於註解開發時,@scope完成bean的作用域配置默認是單例模式(singleton)如果需要設置的話可以修改對應值與以上提到的一致例如:@scope(“prototype”)

// 默認是單實例的

   /**

    * ConfigurableBeanFactory#SCOPE_PROTOTYPE

    *

    * @see ConfigurableBeanFactory#SCOPE_SINGLETON

    * @see org.springframework.web.context.WebApplicationContext#SCOPE_REQUEST

    *      request

    * @see org.springframework.web.context.WebApplicationContext#SCOPE_SESSION

    *      sesssion @return\

    * @Scope:調整作用域 prototype:多實例的:ioc容器啓動並不會去調用方法創建對象放在容器中。 每次獲取的時候纔會調用方法創建對象;

    *              singleton:單實例的(默認值):ioc容器啓動會調用方法創建對象放到ioc容器中。

    *              以後每次獲取就是直接從容器(map.get())中拿, request:同一次請求創建一個實例

    *              session:同一個session創建一個實例

    *

    *              懶加載: 單實例bean:默認在容器啓動的時候創建對象;

    *              懶加載:容器啓動不創建對象。第一次使用(獲取)Bean創建對象,並初始化;

    *

    */

// @Scope("prototype")

   @Lazy

   @Bean("person")

   public Person person() {

      System.out.println("給容器中添加Person....");

      return new Person("張三", 25);

   }

@Lazy用於指定該Bean是否取消預初始化。主要用於修飾Spring Bean類,用於指定該Bean的預初始化行爲,使用該Annotation時可以指定一個boolean型的value屬性,該屬性決定是否要預初始化該Bean

  • lazy代表延時加載,lazy=false,代表不延時,如果對象A中還有對象B的引用,會在A的xml映射文件中配置b的對象引用,多對一或一對多,不延時代表查詢出對象A的時候,會把B對象也查詢出來放到A對象的引用中,A對象中的B對象是有值的。
  • lazy=true代表延時,查詢A對象時,不會把B對象也查詢出來,只會在用到A對象中B對象時纔會去查詢,默認好像是false,你可以看看後臺的sql語句的變化就明白了,一般需要優化效率的時候會用到。

5,@Conditional

條件註解,可以根據不同的條件來做出不同的事情。在Spring中條件註解可以說是設計模式中狀態模式的一種體現方式,同時也是面向對象編程中多態的應用部分。

Spring框架中,當我們使用條件註解時,我們會爲每種獨立的條件創建一個類,根據這個類對應的條件的成立情況我們來選擇不同的任務來執行。當然我們在聲明任務時,一般使用接口來聲明。因爲我們會在Spring的配置類中指定具體條件下的具體類。接下來,我們將來看一下Spring框架中@Conditional註解的具體使用方式。

//類中組件統一設置。滿足當前條件,這個類中配置的所有bean註冊才能生效;

@Conditional({ WindowsCondition.class })

6,@Import

通過導入的方式實現把實例加入springIOC容器中,通過查看@Import源碼可以發現@Import註解只能註解在類上,以及唯一的參數value上可以配置3種類型的值ConfigurationImportSelectorImportBeanDefinitionRegistrar,源碼如下:

 

接下來就分別來看看三種方式具體使用:

a,基於Configuration也就是直接填對應的class數組

bean目錄下新增兩個類SquareCircular如下:

 

MainConfig註解配置中增加@Import註解如下:

 

b,基於自定義ImportSelector的使用

定義一個MyImportSelector如下:

 

MainConfig註解配置修改如下

 

 

三角形 實例同樣加入到spring容器中了

c,基於ImportBeanDefinitionRegistrar的使用

新建一個ImportBeanDefinitionRegistrar如下:

 

修改MainConfig註解配置如下:

 

//@Import導入組件,id默認是組件的全類名

/**

    * 給容器中註冊組件;

    * 1)、包掃描+組件標註註解(@Controller/@Service/@Repository/@Component[自己寫的類]

    * 2)、@Bean[導入的第三方包裏面的組件]

    * 3)、@Import[快速給容器中導入一個組件]

    *    1)、@Import(要導入到容器中的組件);容器中就會自動註冊這個組件,id默認是全類名

    *    2)、ImportSelector:返回需要導入的組件的全類名數組;

    *    3)、ImportBeanDefinitionRegistrar:手動註冊bean到容器中

    *    4)、使用Spring提供的

    * FactoryBean(工廠Bean;

    *    1)、默認獲取到的是工廠bean調用getObject創建的對象

    *    2)、要獲取工廠Bean本身,我們需要給id前面加一個& &colorFactoryBean

    */

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章