spring 注解
多選擇是好事嘛?
Spring 經過十多年的快速發展和更新,以其獨特的創新帶來了大量的擁躉者,在選擇方面還帶來了更多選擇!譬如spring bean的裝配(在XML中進行顯式配置、在Java中進行顯式配置、隱式的bean發現機制和自動裝配),注解的多元化(基本注解、jsr250、jsr330)等等!
而這么多重復的選擇難道真的是好事嗎?這是否也以為學習與成本提高,掌握的難度加大?
打個比喻:同樣可以救國,某個叫spring的神經病告訴你可以從醫救國(xml顯式配置),當你學醫正酣的時候,它又告訴你還可以從軍救國(Java顯示配置),當你練習擒拿射擊快要成功的時候,它來告訴你,其實有更簡單的方法可以教育救國(bean的自動裝配)!
作為一個初學者,個人認為,從學 servlet 到 jsp 再到 struts 到現在的 spring ,坑是越挖越大越挖越多!
注解分類:
spring自帶注解:
@Autowired、@Qualifier、@Value、@Primary、@Required、@Component、@Repository、@Service、@Controller
JSR-250注解:
@Resource、@PostConstruct、@PreDestory
JSR-330注解:
@Inject、@Named
注解關系:
(1) @Autowired =@Resource
(2)@Component=@Repository=@Service=@Controller
-----------------------------------------------------------------------------------------------------------------------------
@Autowired注解:實現自動裝配。
1.在 spring xml 配置文件中需要注入如下兩個類:
<beans> <bean id="testA" class="..../TestA" /> <bean id="testUtil" class="..../TestUtil" /> </beans>
2.若想要在 testUtil 類中裝配 testA 類,則可以在 testUtil 類中使用@Autowired注解;
如果想將 TestA 注入到 TestUtil 中,代碼如下:
public class TestUtil{ @Autowired private Test testA; ....... }
簡單來說,自動裝配就是讓Spring自動滿足bean依賴的一種方法,在滿足依賴的過程中,會在Spring應用上下文中尋找匹配某個bean需求的其他bean。
@Autowired注解不僅能夠用在構造器上,還能用在方法上,和屬性上。如果沒有匹配的bean,那么在應用上下文創建的時候,Spring會拋出一個異常。為了避免異常的出現,你可以將@Autowired的required屬性設置為false:但是,把required屬性設置為false時,你需要謹慎對待。如果在你的代碼中沒有進行null檢查的話,這個處於未裝配狀態的屬性有可能會出現NullPointerException。
@Autowired他是spring特有的注解,如果你不願意在代碼中到處使用Spring的特定注解來完成自動裝配任務的話,那么你可以考慮將其替換為@Inject。
在自動裝配中,Spring同時支持@Inject(JSR330注解)和@Autowired。盡管@Inject和@Autowired之間有着一些細微的差別,但是在大多數場景下,它們都是可以互相替換的。
注意:1.它只是提供自動裝配,並不提供注入;而注入是前提。
2. 若要實現自動裝配還需要導入<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>支持
或者也可以使用<context:annotation-config />
-----------------------------------------------------------------------------------------------------------------------------
@Qualifier注解:對依賴注入的條件進行限制。
如果@Autowired標注的依賴在容器中只能找到一個實例與之對應,則萬事OK,但是如果存在多個同一類型的對象實例,則 @Qualifier 注解將其作用。
假如 Test 類有兩個實現,TestA 和 TestB,在 spring 配置文件中配置代碼如下:
<beans> <bean id="testA" class="..../TestA" /> <bean id="testB" class="..../TestB" /> <bean id="testUtil" class="..../TestUtil" /> </beans>
如果想將 TestA 注入到 TestUtil 中,代碼如下:
public class TestUtil{ @Autowired @Qualifier("testA") private Test testA; private Test testB; ....... }
-----------------------------------------------------------------------------------------------------------------------------
@Resource注解:實現對 bean 的注入。
@resource 它的作用與@Autowired注解類似。只不過@Autowired按byType 類型自動注入,而@resource默認byName進行自動注入。
@resource有兩個重要的屬性:name 和 type,故而name可以解析為Bean的名字,從而按照byName進行注入,type可以解析為Bean的類型,從而按照byType進行注入。若沒有這兩個屬性,則使用默認的byName進行自動注入。
1.由於該注解是由JSR250引入的,故而在使用它之前需要導入jsr250相關jar包的支持,在pom.xml文件中加入以下內容:
<!-- jsr250注解包的引入 --> <dependency> <groupId>javax.annotation</groupId> <artifactId>jsr250-api</artifactId> <version>1.0</version> </dependency>
2.在spring配置文件中注入相關類:
假如 testUtil 類中需要引入 testA 類,在 spring 配置文件中配置代碼如下:
<beans> <bean id="testA" class="..../TestA" /> <bean id="testUtil" class="..../TestUtil" /> </beans>
3.在 testUtil 中加入 @Resource(name=“”)注解:
如果想將 TestA 注入到 TestUtil 中,代碼如下:
public class TestUtil{ @Resource(name=“testA”) private Test testA; private Test testB; ....... }
注意:@Resource(name=“”) 中的name 為指定要注入的對象,testA 為 spring 配置文件中所定義 bean 的id。
4.以下兩個解釋注解的包至少要引入一個到 spring 配置文件,本着偷懶的原則,個人喜歡 context 元素。
<context:annotation-config /> <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
備注:JSR250注解有 @PostConstruct,@PreDestroy 。
JSR330注解有 @Inject (代替 @AutoWired)、@Named (代替 @Component)
-----------------------------------------------------------------------------------------------------------------------------
@PostConstruct,@PreDestroy注解
spring 容器中的bean是有生命周期的,spring 允許bean 在初始化完成后及bean銷毀之前執行特定的操作。
你既可以通過實現 InitializingBean/DisposableBean 接口來定制初始化之后/銷毀之前的操作方法,也可以通過<bean>元素的 init-method/destory-method 屬性來指定初始化之后/銷毀之前操作的方法。
jsr-250 指定了@PostConstruct,@PreDestroy這兩個注解用於初始化之后/銷毀之前方法的指定。
備注:1.這兩個注解只能應用與方法之上。
2.@PostConstruct注解的方法將在類實例化后調用。
3.@PreDestroy注解的方法將在類銷毀之前調用。
-----------------------------------------------------------------------------------------------------------------------------
@Component注解:啟用組件掃描基礎包。
@Resource 與 @Autowired 雖然可以使用自動注入功能,但是還需要在xml配置文件中通過<bean>對 bean 進行定義。也就是說,在xml配置文件中定義bean,通過 @Autowired 或 @Resource 為bean的成員變量、方法或構造器提供自動的注入功能。
那么,能否也通過注釋定義 bean ,從xml 配置文件中完全移除 bean 定義的配置呢?答案是肯定的,這就引入了@component注解。
使用:
1.在 spring 配置文件中加入 <context:component-scan>實現自動掃描。
<context:component-scan base-package="com.lh" />
配置完成后,<context:component-scan>會掃描 com.lh 路徑下的所有標注了的相應注解的類,並添加到IOC容器中,實現依賴注入。
備注:加入該元素后,就不需要再向 spring 配置文件中注入相關的類,即不需要再使用如下配置:
<beans> <bean id="testA" class="..../TestA" /> <bean id="testUtil" class="..../TestUtil" /> </beans>
2.<context:component-scan> 默認掃描的注解類型是 @Component ,所以需要在相應的類中應用這個注解進行標注。
//類A
@Component public class TestUtil{ @Autowired private Test testA; ....... } //類B @Component public class TestA{ private int a; private String ss; ... }
備注:
(1)該注解是類級別的,它添加在類之上。
(2)由@Component注解派生出來的注解有@Respository、@Service和@Controller三個,他們所實現的功能與@Component注解完全一樣,只是名字看上起更為專業。
@Respository:用來表示DAO類。
@Service:用來標識service類。
@Controller:用來表示控制器類。
-----------------------------------------------------------------------------------------------------------------------------
@Primary注解:
在使用@Component注解的時候,有可能根據類型可以匹配到多個符合要求的類。比如注入了實現同一個接口的多個類,此時可以讓@Primary注解對spring中類進行特別標識,使它在存在相同類型的時候優先使用該注解下的類。
-----------------------------------------------------------------------------------------------------------------------------
@Value注解:
注入基本類型的數據與字符串類型的數據。
-----------------------------------------------------------------------------------------------------------------------------
自定義注解:
如何自己實現一個自己的注解呢?
我們可以查看源碼中關於注解的格式,以@Value注解為例:
@Target({ElementType.FIELD,ElementType.METHOD,ElementTyp.PARAMEHER,ElementTyp.ANNOTION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Value{ String value(); }
其中:
@Target標注了該注解可以使用的地方,如可以使用在屬性、方法、參數及注解類型上。
@Retention存在的生命周期。
@Documented是否寫入幫助文檔中去。
////end