posts - 495,comments - 227,trackbacks - 0

          spring 注釋功相當(dāng)于

          以前在spring的配置文件的bean頭中加入了:

          default-autowire="byName"

          default-autowire="byType"

           

          Spring 通過(guò)一個(gè) BeanPostProcessor 對(duì) @Autowired 進(jìn)行解析,所以要讓 @Autowired 起作用必須事先在 Spring 容器中聲明 AutowiredAnnotationBeanPostProcessor Bean。

           

          @Autowired  默讓是byType

          它可以注釋到方法,也可以注釋到成員域:

          如下兩種:

          1、

          package com.web.userManagser.action;
          import org.springframework.beans.factory.annotation.Autowired;
          import com.web.userManagser.services.UserManagerService;
          public class UserManagerAction {
          @Autowired
          private UserManagerService userManagerService;
          public void sayHello(){
          this.userManagerService.sayHello();
          }
          }

           2、

          package com.web.userManagser.action;
          import org.springframework.beans.factory.annotation.Autowired;
          import com.web.userManagser.services.UserManagerService;
          public class UserManagerAction {
          private UserManagerService userManagerService;
          public void sayHello(){
          this.userManagerService.sayHello();
          }
          public UserManagerService getUserManagerService() {
          return userManagerService;
          }
          @Autowired
          public void setUserManagerService(UserManagerService userManagerService) {
          this.userManagerService = userManagerService;
          }
          }
          

           

           

          當(dāng)候選 Bean 數(shù)目不為1個(gè)時(shí)個(gè)時(shí)的應(yīng)對(duì)方法

          1、bean 數(shù)目為0個(gè)時(shí):

           

          也就是spring 找不到一個(gè)匹配的bean, spring 就會(huì)拋出BeanCreationException 異常

           

          如上述的情況怎么解決呢。如果想讓spring 找不到bean 不報(bào)錯(cuò)那么你在注釋的時(shí)候可以如下的注釋方法:

          @Autowired(required = false)

          當(dāng)然,一般情況下,使用 @Autowired 的地方都是需要注入 Bean 的,使用了自動(dòng)注入而又允許不注入的情況一般僅會(huì)在開(kāi)發(fā)期或測(cè)試期碰到(如為了快速啟動(dòng) Spring 容器,僅引入一些模塊的 Spring 配置文件),所以 @Autowired(required = false) 會(huì)很少用到。

           

           

          2、bean 數(shù)目不只一個(gè),而是多個(gè)時(shí)呢?

          如果我們?cè)趕pring 中配置了兩個(gè)相同的類(lèi)型時(shí),而我們的注釋又同時(shí)是通過(guò)byType時(shí)

          那么spring 就會(huì)出錯(cuò),它不知道哪個(gè)bean 是它要的。

          那么我們就可以將@Qualifier 和@Autowired 一起用

           

          用的同時(shí)就是把自動(dòng)配置的方式從byType 轉(zhuǎn)向 byName,

          如下使用:

           

          配置文件中有:

          <bean id="userManagerService" class="com.web.userManagser.services.UserManagerService"/>
          <bean id="userManagerAction" class="com.web.userManagser.action.UserManagerAction"/>
          <bean id="userManagerAction1" class="com.web.userManagser.action.UserManagerAction"/>
          

           

           

          此時(shí)我們就可以:

          public class UserManagerAction {
          @Autowired
          @Qualifier("userManagerService")
          private UserManagerService userManagerService;
          public void sayHello(){
          this.userManagerService.sayHello();
          }
          }
          

           

          @Qualifier 只能和 @Autowired 結(jié)合使用,是對(duì) @Autowired 有益的補(bǔ)充。一般來(lái)講,@Qualifier 對(duì)方法簽名中入?yún)⑦M(jìn)行注釋會(huì)降低代碼的可讀性,而對(duì)成員變量注釋則相對(duì)好一些。

           

           

           我們還可以用使用 JSR-250 的注釋

           

          要讓 JSR-250 的注釋生效,除了在 Bean 類(lèi)中標(biāo)注這些注釋外,還需要在 Spring 容器中注冊(cè)一個(gè)負(fù)責(zé)處理這些注釋的 BeanPostProcessor

          <?xml version="1.0" encoding="UTF-8" ?>
          <beans xmlns="http://www.springframework.org/schema/beans"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://www.springframework.org/schema/beans
          http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
          <!-- 該 BeanPostProcessor 將自動(dòng)起作用,對(duì)標(biāo)注 @Autowired 的 Bean 進(jìn)行自動(dòng)注入 -->
          <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
          <!-- 該 BeanPostProcessor 將自動(dòng)起作用,對(duì)標(biāo)注的 @Resource、@PostConstruct 以及 @PreDestroy-->
          <bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"/>
          
          <!-- 移除 boss Bean 的屬性注入配置的信息 -->
          <bean id="userManagerService" class="com.web.userManagser.services.UserManagerService"/>
          <bean id="userManagerService1" class="com.web.userManagser.services.UserManagerService"/>
          <bean id="userManagerAction" class="com.web.userManagser.action.UserManagerAction"/>
          </beans>
          

           

           

          @Resource@PostConstruct 以及 @PreDestroy

           

           1、@Resource 有兩個(gè)屬性。

            name spring 將它解釋成bean的名字

            type spring 將它解釋成bean 的類(lèi)型

           

          如果我們定義了name那么spring 就使用byName 方式注入

          如果我們定義了type 那么spring 就用byTyte方式注入

          如果兩者都沒(méi)有定義那么就默為byName

           

          @PostConstruct 和 @PreDestroy

           

          這兩個(gè)注釋定義在方法上,

          被@PostConstruct 注釋的方法,bean 被實(shí)例化后調(diào)用的。

          而被@PreDestroy 注釋的方法,bean 被銷(xiāo)毀時(shí)調(diào)用的。

          public class UserManagerAction {
          @Resource(name="userManagerService")
          private UserManagerService userManagerService;
          public void sayHello(){
          this.userManagerService.sayHello();
          }
          @PostConstruct
          public void ct(){
          System.out.println("ct");
          }
          @PreDestroy
          public void pro(){
          System.out.println("ct");
          }
          }

           

           

          我們知道,不管是通過(guò)實(shí)現(xiàn) InitializingBean/DisposableBean 接口,還是通過(guò) <bean> 元素的 init-method/destroy-method 屬性進(jìn)行配置,都只能為 Bean 指定一個(gè)初始化 / 銷(xiāo)毀的方法。但是使用 @PostConstruct@PreDestroy 注釋卻可以指定多個(gè)初始化 / 銷(xiāo)毀方法,那些被標(biāo)注 @PostConstruct@PreDestroy 注釋的方法都會(huì)在初始化 / 銷(xiāo)毀時(shí)被執(zhí)行。

           

           

           

          使用 <context:annotation-config/> 簡(jiǎn)化配置

           

          Spring 2.1 添加了一個(gè)新的 context 的 Schema 命名空間,該命名空間對(duì)注釋驅(qū)動(dòng)、屬性文件引入、加載期織入等功能提供了便捷的配置。我們知道注釋本身是不會(huì)做任何事情的,它僅提供元數(shù)據(jù)信息。要使元數(shù)據(jù)信息真正起作用,必須讓負(fù)責(zé)處理這些元數(shù)據(jù)的處理器工作起來(lái)。

          而我們前面所介紹的 AutowiredAnnotationBeanPostProcessorCommonAnnotationBeanPostProcessor 就是處理這些注釋元數(shù)據(jù)的處理器。但是直接在 Spring 配置文件中定義這些 Bean 顯得比較笨拙。Spring 為我們提供了一種方便的注冊(cè)這些 BeanPostProcessor 的方式,這就是 <context:annotation-config/>。

           

          <?xml version="1.0" encoding="UTF-8" ?>
          <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xmlns:context="http://www.springframework.org/schema/context"
          xsi:schemaLocation="http://www.springframework.org/schema/beans
          http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
          http://www.springframework.org/schema/context
          http://www.springframework.org/schema/context/spring-context-2.5.xsd">
           <context:annotation-config/>
          <bean id="userManagerService" class="com.web.userManagser.services.UserManagerService"/>
          <bean id="userManagerAction" class="com.web.userManagser.action.UserManagerAction"/>
          </beans>
          

           

          <context:annotationconfig/> 將隱式地向 Spring 容器注冊(cè) AutowiredAnnotationBeanPostProcessorCommonAnnotationBeanPostProcessorPersistenceAnnotationBeanPostProcessor 以及 equiredAnnotationBeanPostProcessor 這 4 個(gè) BeanPostProcessor。

          在配置文件中使用 context 命名空間之前,必須在 <beans> 元素中聲明 context 命名空間。

           

           

           

          使用 @Component

          雖然我們可以通過(guò) @Autowired@Resource 在 Bean 類(lèi)中使用自動(dòng)注入功能,但是 Bean 還是在 XML 文件中通過(guò) <bean> 進(jìn)行定義 —— 也就是說(shuō),在 XML 配置文件中定義 Bean,通過(guò) @Autowired@Resource 為 Bean 的成員變量、方法入?yún)⒒驑?gòu)造函數(shù)入?yún)⑻峁┳詣?dòng)注入的功能。能否也通過(guò)注釋定義 Bean,從 XML 配置文件中完全移除 Bean 定義的配置呢?答案是肯定的,我們通過(guò) Spring 2.5 提供的 @Component 注釋就可以達(dá)到這個(gè)目標(biāo)了。

           

          下面,我們完全使用注釋定義 Bean 并完成 Bean 之間裝配:

          package com.web.userManagser.services;
          import org.springframework.stereotype.Component;
          @Component
          public class UserManagerService {
          public void sayHello(){
          System.out.println("fuck you!");
          }
          }

           

          @Component("userManagerAction")
          public class UserManagerAction {
          @Resource(name="userManagerService")
          private UserManagerService userManagerService;
          public void sayHello(){
          this.userManagerService.sayHello();
          }
          }
          

           

          @Component 有一個(gè)可選的入?yún)ⅲ糜谥付?Bean 的名稱(chēng),在 Boss 中,我們就將 Bean 名稱(chēng)定義為“boss”。一般情況下,Bean 都是 singleton 的,需要注入 Bean 的地方僅需要通過(guò) byType 策略就可以自動(dòng)注入了,所以大可不必指定 Bean 的名稱(chēng)。

          在使用 @Component 注釋后,Spring 容器必須啟用類(lèi)掃描機(jī)制以啟用注釋驅(qū)動(dòng) Bean 定義和注釋驅(qū)動(dòng) Bean 自動(dòng)注入的策略。Spring 2.5 對(duì) context 命名空間進(jìn)行了擴(kuò)展,提供了這一功能,請(qǐng)看下面的配置:

           

           

          <?xml version="1.0" encoding="UTF-8" ?>
          <beans xmlns="http://www.springframework.org/schema/beans"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xmlns:context="http://www.springframework.org/schema/context"
          xsi:schemaLocation="http://www.springframework.org/schema/beans
          http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
          http://www.springframework.org/schema/context
          http://www.springframework.org/schema/context/spring-context-2.5.xsd">
          <context:component-scan base-package="com.web"/>
          </beans>
          

           

           

          這里,所有通過(guò) <bean> 元素定義 Bean 的配置內(nèi)容已經(jīng)被移除,僅需要添加一行 <context:component-scan/> 配置就解決所有問(wèn)題了——Spring XML 配置文件得到了極致的簡(jiǎn)化(當(dāng)然配置元數(shù)據(jù)還是需要的,只不過(guò)以注釋形式存在罷了)。<context:component-scan/> 的 base-package 屬性指定了需要掃描的類(lèi)包,類(lèi)包及其遞歸子包中所有的類(lèi)都會(huì)被處理。

           

          <context:component-scan/> 還允許定義過(guò)濾器將基包下的某些類(lèi)納入或排除。Spring 支持以下 4 種類(lèi)型的過(guò)濾方式,通過(guò)下表說(shuō)明:


          表 1. 掃描過(guò)濾方式

          過(guò)濾器類(lèi)型 說(shuō)明
          注釋 假如 com.baobaotao.SomeAnnotation 是一個(gè)注釋類(lèi),我們可以將使用該注釋的類(lèi)過(guò)濾出來(lái)。
          類(lèi)名指定 通過(guò)全限定類(lèi)名進(jìn)行過(guò)濾,如您可以指定將 com.baobaotao.Boss 納入掃描,而將 com.baobaotao.Car 排除在外。
          正則表達(dá)式 通過(guò)正則表達(dá)式定義過(guò)濾的類(lèi),如下所示: com\.baobaotao\.Default.*
          AspectJ 表達(dá)式 通過(guò) AspectJ 表達(dá)式定義過(guò)濾的類(lèi),如下所示: com. baobaotao..*Service+

          下面是一個(gè)簡(jiǎn)單的例子:

           

          <context:component-scan base-package="com.web">
                       <context:include-filter type="aspectj" expression="com.web..action..*"/>
                      </context:component-scan>
                      

           

          值得注意的是 <context:component-scan/> 配置項(xiàng)不但啟用了對(duì)類(lèi)包進(jìn)行掃描以實(shí)施注釋驅(qū)動(dòng) Bean 定義的功能,同時(shí)還啟用了注釋驅(qū)動(dòng)自動(dòng)注入的功能(即還隱式地在內(nèi)部注冊(cè)了 AutowiredAnnotationBeanPostProcessorCommonAnnotationBeanPostProcessor),因此當(dāng)使用 <context:component-scan/> 后,就可以將 <context:annotation-config/> 移除了。

          通過(guò) @Scope 指定 Bean 的作用范圍

                        
          package com.baobaotao;
          import org.springframework.context.annotation.Scope;

          @Scope("prototype")
          @Component("boss")
          public class Boss {
              …
          }

          這樣,當(dāng)從 Spring 容器中獲取 boss Bean 時(shí),每次返回的都是新的實(shí)例了。

           

           

           

          采用具有特殊語(yǔ)義的注釋

          Spring 2.5 中除了提供 @Component 注釋外,還定義了幾個(gè)擁有特殊語(yǔ)義的注釋?zhuān)鼈兎謩e是:@Repository@Service@Controller。在目前的 Spring 版本中,這 3 個(gè)注釋和 @Component 是等效的,但是從注釋類(lèi)的命名上,很容易看出這 3 個(gè)注釋分別和持久層、業(yè)務(wù)層和控制層(Web 層)相對(duì)應(yīng)。雖然目前這 3 個(gè)注釋和 @Component 相比沒(méi)有什么新意,但 Spring 將在以后的版本中為它們添加特殊的功能。所以,如果 Web 應(yīng)用程序采用了經(jīng)典的三層分層結(jié)構(gòu)的話(huà),最好在持久層、業(yè)務(wù)層和控制層分別采用 @Repository@Service@Controller 對(duì)分層中的類(lèi)進(jìn)行注釋?zhuān)?@Component 對(duì)那些比較中立的類(lèi)進(jìn)行注釋。

           

           

           

          注釋配置和 XML 配置的適用場(chǎng)合

          是否有了這些 IOC 注釋?zhuān)覀兙涂梢酝耆鸪瓉?lái) XML 配置的方式呢?答案是否定的。有以下幾點(diǎn)原因:

          • 注釋配置不一定在先天上優(yōu)于 XML 配置。如果 Bean 的依賴(lài)關(guān)系是固定的,(如 Service 使用了哪幾個(gè) DAO 類(lèi)),這種配置信息不會(huì)在部署時(shí)發(fā)生調(diào)整,那么注釋配置優(yōu)于 XML 配置;反之如果這種依賴(lài)關(guān)系會(huì)在部署時(shí)發(fā)生調(diào)整,XML 配置顯然又優(yōu)于注釋配置,因?yàn)樽⑨屖菍?duì) Java 源代碼的調(diào)整,您需要重新改寫(xiě)源代碼并重新編譯才可以實(shí)施調(diào)整。
          • 如果 Bean 不是自己編寫(xiě)的類(lèi)(如 JdbcTemplateSessionFactoryBean 等),注釋配置將無(wú)法實(shí)施,此時(shí) XML 配置是唯一可用的方式。
          • 注釋配置往往是類(lèi)級(jí)別的,而 XML 配置則可以表現(xiàn)得更加靈活。比如相比于 @Transaction 事務(wù)注釋?zhuān)褂?aop/tx 命名空間的事務(wù)配置更加靈活和簡(jiǎn)單。

          所以在實(shí)現(xiàn)應(yīng)用中,我們往往需要同時(shí)使用注釋配置和 XML 配置,對(duì)于類(lèi)級(jí)別且不會(huì)發(fā)生變動(dòng)的配置可以?xún)?yōu)先考慮注釋配置;而對(duì)于那些第三方類(lèi)以及容易發(fā)生調(diào)整的配置則應(yīng)優(yōu)先考慮使用 XML 配置。Spring 會(huì)在具體實(shí)施 Bean 創(chuàng)建和 Bean 注入之前將這兩種配置方式的元信息融合在一起。

          posted on 2010-12-15 22:05 SIMONE 閱讀(522) 評(píng)論(0)  編輯  收藏 所屬分類(lèi): JAVA
          主站蜘蛛池模板: 水城县| 榕江县| 醴陵市| 昌平区| 沅江市| 清苑县| 渑池县| 西充县| 镇平县| 营山县| 南岸区| 石渠县| 皋兰县| 湟中县| 普洱| 丹阳市| 微博| 抚顺县| 宜君县| 汝城县| 灵璧县| 高阳县| 锦屏县| 海门市| 固安县| 凭祥市| 山西省| 大连市| 阳西县| 房山区| 南昌县| 博湖县| 静安区| 精河县| 高清| 平陆县| 额尔古纳市| 巫溪县| 阿瓦提县| 沽源县| 迁西县|