@Autowired和@Resource等注解是將Spring容器中的bean注入到屬性,而@Component等注解是將bean放入Spring容器中管理。
@Autowired
spring2.1中允許用戶通過@Autowired注解對Bean的屬性變量.屬性Setter方法以及構造函數進行標注,配合AutowiredAnnotationBeanProcessor完成Bean的自動配置。使用@Autowired注釋進行byType注入。
在applicationContext.xml中加入:
- <!-- 該 BeanPostProcessor 將自動對標注 @Autowired 的 Bean 進行注入 -->
- <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
通過 @Autowired的使用來消除 set ,get方法。
- @Autowired
- private UserDao userdao;
這樣就可以刪除set ,get方法和spring中的相關配制了。
- <bean id="userDao" class="..."/>
- <bean id="userService" class="...">
- <property name="userDao">
- <ref bean="userDao"/>
- </property>
- </bean>
通過@Autowired屬的Setter方法給父類中的屬性注入值。
- @Autowired
- public void setDataSource(DataSource dataSource)
- {
- super.setDataSource(dataSource);
- }
@Autowired(required = false)
當不能確定 Spring 容器中一定擁有某個類的 Bean 時,可以在需要自動注入該類 Bean 的地方可以使用 @Autowired(required = false) ,這等於告訴 Spring:在找不到匹配 Bean 時也不報錯。
當然,一般情況下,使用 @Autowired 的地方都是需要注入 Bean 的,使用了自動注入而又允許不注入的情況一般僅會在開發期或測試期碰到(如為了快速啟動 Spring 容器,僅引入一些模塊的 Spring 配置文件),所以 @Autowired(required = false) 會很少用到。
@Qualifier
使用@Autowired注釋進行byType注入,如果需要byName(byName就是通過id去標識)注入,增加@Qualifier注釋。一般在候選Bean數目不為1時應該加@Qualifier注釋。
在默認情況下使用 @Autowired 注釋進行自動注入時,Spring 容器中匹配的候選 Bean 數目必須有且僅有一個。當找不到一個匹配的 Bean 時,Spring 容器將拋出
BeanCreationException 異常,並指出必須至少擁有一個匹配的 Bean。
和找不到一個類型匹配 Bean 相反的一個錯誤是:如果 Spring 容器中擁有多個候選 Bean,Spring 容器在啟動時也會拋出 BeanCreationException 異常。
Spring 允許我們通過 @Qualifier 注釋指定注入 Bean 的名稱,這樣歧義就消除了,可以通過下面的方法解決異常:
- @Autowired
- public void setOffice(@Qualifier("office")Office office)
- {
- this.office =office;
- }
也可以直接注入到屬性:
- @Autowired
- @Qualifier("office")
- private Office office;
@Qualifier(“office”)中的office是Bean的名稱,所以@Autowired和@Qualifier結合使用時,自動注入的策略就從byType轉變成byName了。
@Autowired可以對成員變量、方法以及構造函數進行注釋,而@Qualifier的標注對象是成員變量、方法入參、構造函數入參。正是由於注釋對象的不同,所以Spring不將 @Autowired和@Qualifier統一成一個注釋類。
@Qualifier 只能和@Autowired 結合使用,是對@Autowired有益的補充。
一般來講,@Qualifier對方法簽名中入參進行注釋會降低代碼的可讀性,而對成員變量注釋則相對好一些。
@Resource
Spring不但支持自己定義的@Autowired注解,還支持幾個由JSR-250規范定義的注解,它們分別是@Resource、@PostConstruct以及@PreDestroy。
@Resource的作用相當於@Autowired,只不過@Autowired按byType自動注入,而@Resource默認按 byName自動注入罷了。@Resource有兩個屬性是比較重要的,分是name和type,Spring將@Resource注解的name屬性解析為bean的名字,而type屬性則解析為bean的類型。所以如果使用name屬性,則使用byName的自動注入策略,而使用type屬性時則使用byType自動注入策略。如果既不指定name也不指定type屬性,這時將通過反射機制使用byName自動注入策略。
@Resource裝配順序
1. 如果同時指定了name和type,則從Spring上下文中找到唯一匹配的bean進行裝配,找不到則拋出異常
2. 如果指定了name,則從上下文中查找名稱(id)匹配的bean進行裝配,找不到則拋出異常
3. 如果指定了type,則從上下文中找到類型匹配的唯一bean進行裝配,找不到或者找到多個,都會拋出異常
4. 如果既沒有指定name,又沒有指定type,則自動按照byName方式進行裝配;如果沒有匹配,則回退為一個原始類型進行匹配,如果匹配則自動裝配;
@Component、@Repository、@Service、@Controller
Spring 2.5 中除了提供 @Component 注釋外,還定義了幾個擁有特殊語義的注釋,它們分別是:@Repository、@Service 和 @Controller。
在目前的 Spring 版本中,這 3 個注釋和 @Component 是等效的,但是從注釋類的命名上,很容易看出這 3 個注釋分別和持久層、業務層和控制層(Web 層)相對應。
雖然目前這3 個注釋和 @Component 相比沒有什么新意,但 Spring 將在以后的版本中為它們添加特殊的功能。
所以,如果 Web 應用程序采用了經典的三層分層結構的話,最好在持久層、業務層和控制層分別采用上述注解對分層中的類進行注釋。
@Service用於標注業務層組件
@Controller用於標注控制層組件(如struts中的action)
@Repository用於標注數據訪問組件,即DAO組件
@Component泛指組件,當組件不好歸類的時候,我們可以使用這個注解進行標注。
- @Service
- public class VentorServiceImpl implements iVentorService {
- }
- @Repository
- public class VentorDaoImpl implements iVentorDao {
- }
在一個稍大的項目中,如果組件采用xml的bean定義來配置,顯然會增加配置文件的體積,查找以及維護起來也不太方便。
Spring2.5為我們引入了組件自動掃描機制,他在類路徑下尋找標注了上述注解的類,並把這些類納入進spring容器中管理。
它的作用和在xml文件中使用bean節點配置組件時一樣的。要使用自動掃描機制,我們需要打開以下配置信息:
- <?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 />
- <context:component-scan base-package=”com.iteedu.spring”>
- </beans>
annotation-config是對標記了@Required、@Autowired、@PostConstruct(實例化bean后執行的方法(init()))、@PreDestroy(關閉資源后執行的方法( destroy()))、@Resource、@WebServiceRef、@EJB、@PersistenceContext、@PersistenceUnit等注解的類進行對應的操作使注解生效。
base-package為需要掃描的包(含所有子包),負責掃描那些有@Component、@Repository、@Service 和 @Controller注解的類。
可以使用以下方式指定初始化方法和銷毀方法:
- @PostConstruct
- public void init() {
- }
- @PreDestroy
- public void destory() {
- }