使用Spring注解來注入屬性
使用注解以前我們是怎樣注入屬性的
類的實現
Java代碼
public class UserManagerImpl implements UserManager {
private UserDao userDao;
public void setUserDao(UserDao userDao) {
thisuserDao = userDao;
}
}
配置文件
Java代碼
<bean id=userManagerImpl class=comkedacomspringannotationserviceUserManagerImpl>
<property name=userDao ref=userDao />
</bean>
<bean id=userDao class=comkedacomspringannotationpersistenceUserDaoImpl>
<property name=sessionFactory ref=mySessionFactory />
</bean>
引入@Autowired注解(不推薦使用建議使用@Resource)下面有對於他們兩個的介紹>
類的實現(對成員變量進行標注)
Java代碼
public class UserManagerImpl implements UserManager {
@Autowired
private UserDao userDao;
}
或者(對方法進行標注)
Java代碼
public class UserManagerImpl implements UserManager {
private UserDao userDao;
@Autowired
public void setUserDao(UserDao userDao) {
thisuserDao = userDao;
}
}
配置文件
Java代碼
<bean id=userManagerImpl class=comkedacomspringannotationserviceUserManagerImpl />
<bean id=userDao class=comkedacomspringannotationpersistenceUserDaoImpl>
<property name=sessionFactory ref=mySessionFactory />
</bean>
@Autowired可以對成員變量方法和構造函數進行標注來完成自動裝配的工作以上兩種不同實現方式中@Autowired的標注位置不同它們都會在Spring在初始化userManagerImpl這個bean時自動裝配userDao這個屬性區別是第一種實現中Spring會直接將UserDao類型的唯一一個bean賦值給userDao這個成員變量第二種實現中Spring會調用setUserDao方法來將UserDao類型的唯一一個bean裝配到userDao這個屬性
讓@Autowired工作起來
要使@Autowired能夠工作還需要在配置文件中加入以下代碼 (對於這個問題spring也為我們考慮到了在下面的這個配置中省去了我們 編寫bean的麻煩)
Java代碼
<bean class=orgspringframeworkbeansfactoryannotationAutowiredAnnotationBeanPostProcessor />
<<<<<<<<<<<<<
在基於主機方式配置Spring的配置文件中你可能會見到<context:annotationconfig/>這樣一條配置他的作用是式地向 Spring 容器注冊
AutowiredAnnotationBeanPostProcessorCommonAnnotationBeanPostProcessor
PersistenceAnnotationBeanPostProcessor 以及 RequiredAnnotationBeanPostProcessor 這 個BeanPostProcessor
注冊這個 BeanPostProcessor的作用就是為了你的系統能夠識別相應的注解
例如
如果你想使用@Autowired注解那麼就必須事先在 Spring 容器中聲明 AutowiredAnnotationBeanPostProcessor Bean傳統聲明方式如下
<bean class=orgspringframeworkbeansfactoryannotation AutowiredAnnotationBeanPostProcessor /> 如果想使用@ Resource @ PostConstruct@ PreDestroy等注解就必須聲明CommonAnnotationBeanPostProcessor
如果想使用@PersistenceContext注解就必須聲明PersistenceAnnotationBeanPostProcessor的Bean
如果想使用 @Required的注解就必須聲明RequiredAnnotationBeanPostProcessor的Bean同樣傳統的聲明方式如下
<bean class=orgspringframeworkbeansfactoryannotationRequiredAnnotationBeanPostProcessor/> 一般來說這些注解我們還是比較常用尤其是Antowired的注解在自動注入的時候更是經常使用所以如果總是需要按照傳統的方式一條一條配置顯得有些繁瑣和沒有必要於是spring給我們提供<context:annotationconfig/>的簡化配置方式自動幫你完成聲明
>>>>>>>>>>>>>>
@Qualifier (重點)
@Autowired是根據類型進行自動裝配的在上面的例子中如果當Spring上下文中存在不止一個UserDao類型的bean時就會拋出BeanCreationException異常如果Spring上下文中不存在UserDao類型的bean也會拋出BeanCreationException異常我們可以使用@Qualifier配合@Autowired來解決這些問題
可能存在多個UserDao實例
Java代碼
@Autowired
public void setUserDao(@Qualifier(userDao) UserDao userDao) {
thisuserDao = userDao;
}
這樣Spring會找到id為userDao的bean進行裝配
可能不存在UserDao實例
Java代碼
@Autowired(required = false)
public void setUserDao(UserDao userDao) {
thisuserDao = userDao;
}
@Resource 和 @Autowired的區別 (一定要看)
@Resource(JSR標准注解推薦使用它來代替Spring專有的@Autowired注解)
Spring 不但支持自己定義的@Autowired注解還支持幾個由JSR規范定義的注解它們分別是@Resource@PostConstruct以及@PreDestroy
@Resource的作用相當於@Autowired只不過@Autowired按byType自動注入而@Resource默認按byName自動注入罷了@Resource有兩個屬性是比較重要的分別是name和typeSpring將@Resource注解的name屬性解析為bean的名字而type屬性則解析為bean的類型所以如果使用name屬性則使用byName的自動注入策略而使用type屬性時則使用byType自動注入策略如果既不指定name也不指定type屬性這時將通過反射機制使用byName自動注入策略
@Resource裝配順序
如果同時指定了name和type則從Spring上下文中找到唯一匹配的bean進行裝配找不到則拋出異常
如果指定了name則從上下文中查找名稱(id)匹配的bean進行裝配找不到則拋出異常
如果指定了type則從上下文中找到類型匹配的唯一bean進行裝配找不到或者找到多個都會拋出異常
如果既沒有指定name又沒有指定type則自動按照byName方式進行裝配(見)如果沒有匹配則回退為一個原始類型(UserDao)進行匹配如果匹配則自動裝配
@PostConstruct(JSR)
在方法上加上注解@PostConstruct這個方法就會在Bean初始化之後被Spring容器執行(注Bean初始化包括實例化Bean並裝配Bean的屬性(依賴注入))
它的一個典型的應用場景是當你需要往Bean裡注入一個其父類中定義的屬性而你又無法復寫父類的屬性或屬性的setter方法時如
Java代碼
public class UserDaoImpl extends HibernateDaoSupport implements UserDao {
private SessionFactory mySessionFacotry;
@Resource
public void setMySessionFacotry(SessionFactory sessionFacotry) {
thismySessionFacotry = sessionFacotry;
}
@PostConstruct
public void injectSessionFactory() {
supersetSessionFactory(mySessionFacotry);
}
}
這裡通過@PostConstruct為UserDaoImpl的父類裡定義的一個sessionFactory私有屬性注入了我們自己定義的sessionFactory(父類的setSessionFactory方法為final不可復寫)之後我們就可以通過調用supergetSessionFactory()來訪問該屬性了
@PreDestroy(JSR)
在方法上加上注解@PreDestroy這個方法就會在Bean初始化之後被Spring容器執行由於我們當前還沒有需要用到它的場景這裡不不去演示其用法同@PostConstruct
使用<context:annotationconfig />簡化配置
Spring添加了一個新的context的Schema命名空間該命名空間對注釋驅動屬性文件引入加載期織入等功能提供了便捷的配置我們知道注釋本身是不會做任何事情的它僅提供元數據信息要使元數據信息真正起作用必須讓負責處理這些元數據的處理器工作起來
AutowiredAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor就是處理這些注釋元數據的處理器但是直接在Spring配置文件中定義這些Bean顯得比較笨拙Spring為我們提供了一種方便的注冊這些BeanPostProcessor的方式這就是<context:annotationconfig />
Java代碼
<beans xmlns=/schema/beans xmlns:xsi=//XMLSchemainstance xmlns:context=/schema/context
xsi:schemaLocation=/schema/beans
/schema/beans/springbeansxsd
/schema/context
/schema/context/springcontextxsd>
<context:annotationconfig />
</beans>
<context:annotationconfig />將隱式地向Spring容器注冊AutowiredAnnotationBeanPostProcessorCommonAnnotationBeanPostProcessor PersistenceAnnotationBeanPostProcessor以及RequiredAnnotationBeanPostProcessor這個BeanPostProcessor
使用Spring注解完成Bean的定義
以上我們介紹了通過@Autowired或@Resource來實現在Bean中自動注入的功能下面我們將介紹如何注解Bean從而從XML配置文件中完全移除Bean定義的配置
@Component(不推薦使用)@Repository@Service@Controller
只需要在對應的類上加上一個@Component注解就將該類定義為一個Bean了
Java代碼
@Component
public class UserDaoImpl extends HibernateDaoSupport implements UserDao {
}
使用@Component注解定義的Bean默認的名稱(id)是小寫開頭的非限定類名如這裡定義的Bean名稱就是userDaoImpl你也可以指定Bean的名稱
@Component(userDao)
@Component是所有受Spring管理組件的通用形式Spring還提供了更加細化的注解形式@Repository@Service@Controller它們分別對應存儲層Bean業務層Bean和展示層Bean目前版本()中這些注解與@Component的語義是一樣的完全通用在Spring以後的版本中可能會給它們追加更多的語義所以我們推薦使用@Repository@Service@Controller來替代@Component
使用<context:componentscan />讓Bean定義注解工作起來 指定掃描的范圍
Java代碼
<beans xmlns=/schema/beans xmlns:xsi=//XMLSchemainstance xmlns:context=/schema/context
xsi:schemaLocation=/schema/beans
/schema/beans/springbeansxsd
/schema/context
/schema/context/springcontextxsd>
<context:componentscan basepackage=comkedacomksoa />
</beans>
這裡所有通過<bean>元素定義Bean的配置內容已經被移除僅需要添加一行<context:componentscan />配置就解決所有問題了——Spring XML配置文件得到了極致的簡化(當然配置元數據還是需要的只不過以注釋形式存在罷了)<context:componentscan />的basepackage屬性指定了需要掃描的類包類包及其遞歸子包中所有的類都會被處理
<context:componentscan />還允許定義過濾器將基包下的某些類納入或排除Spring支持以下種類型的過濾方式
過濾器類型 表達式范例 說明
注解 orgexampleSomeAnnotation 將所有使用SomeAnnotation注解的類過濾出來
類名指定 orgexampleSomeClass 過濾指定的類
正則表達式 com\kedacom\spring\annotation\web\* 通過正則表達式過濾一些類
AspectJ表達式 orgexample*Service+ 通過AspectJ表達式過濾一些類
以正則表達式為例我列舉一個應用實例
Java代碼
<context:componentscan basepackage=comcasheenspringannotation>
<context:excludefilter type=regex expression=com\casheen\spring\annotation\web\* />
</context:componentscan>
值得注意的是<context:componentscan />配置項不但啟用了對類包進行掃描以實施注釋驅動Bean定義的功能同時還啟用了注釋驅動自動注入的功能(即還隱式地在內部注冊了AutowiredAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor)因此當使用<context:componentscan />後就可以將<context:annotationconfig />移除了
使用@Scope來定義Bean的作用范圍
在使用XML定義Bean時我們可能還需要通過bean的scope屬性來定義一個Bean的作用范圍我們同樣可以通過@Scope注解來完成這項工作
Java代碼
@Scope(session)
@Component()
public class UserSessionBean implements Serializable {
}
下面 是一些問答的可以看看
casheen 寫道
使用Spring注解來注入屬性
使用注解以前我們是怎樣注入屬性的
類的實現
Java代碼
public class UserManagerImpl implements UserManager {
private UserDao userDao;
public void setUserDao(UserDao userDao) {
thisuserDao = userDao;
}
}
配置文件
Java代碼
<bean id=userManagerImpl class=comkedacomspringannotationserviceUserManagerImpl>
<property name=userDao ref=userDao />
</bean>
<bean id=userDao class=comkedacomspringannotationpersistenceUserDaoImpl>
<property name=sessionFactory ref=mySessionFactory />
</bean>
引入@Autowired注解(不推薦使用建議使用@Resource)
類的實現(對成員變量進行標注)
Java代碼
public class UserManagerImpl implements UserManager {
@Autowired
private UserDao userDao;
}
或者(對方法進行標注)
Java代碼
public class UserManagerImpl implements UserManager {
private UserDao userDao;
@Autowired
public void setUserDao(UserDao userDao) {
thisuserDao = userDao;
}
}
配置文件
Java代碼
<bean id=userManagerImpl class=comkedacomspringannotationserviceUserManagerImpl />
<bean id=userDao class=comkedacomspringannotationpersistenceUserDaoImpl>
<property name=sessionFactory ref=mySessionFactory />
</bean>
@Autowired可以對成員變量方法和構造函數進行標注來完成自動裝配的工作以上兩種不同實現方式中@Autowired的標注位置不同它們都會在Spring在初始化userManagerImpl這個bean時自動裝配userDao這個屬性區別是第一種實現中Spring會直接將UserDao類型的唯一一個bean賦值給userDao這個成員變量第二種實現中Spring會調用setUserDao方法來將UserDao類型的唯一一個bean裝配到userDao這個屬性
讓@Autowired工作起來
要使@Autowired能夠工作還需要在配置文件中加入以下代碼
Java代碼
<bean class=orgspringframeworkbeansfactoryannotationAutowiredAnnotationBeanPostProcessor />
@Qualifier
@Autowired是根據類型進行自動裝配的在上面的例子中如果當Spring上下文中存在不止一個UserDao類型的bean時就會拋出BeanCreationException異常如果Spring上下文中不存在UserDao類型的bean也會拋出BeanCreationException異常我們可以使用@Qualifier配合@Autowired來解決這些問題
可能存在多個UserDao實例
Java代碼
@Autowired
public void setUserDao(@Qualifier(userDao) UserDao userDao) {
thisuserDao = userDao;
}
這樣Spring會找到id為userDao的bean進行裝配
可能不存在UserDao實例
Java代碼
@Autowired(required = false)
public void setUserDao(UserDao userDao) {
thisuserDao = userDao;
}
@Resource(JSR標准注解推薦使用它來代替Spring專有的@Autowired注解)
Spring 不但支持自己定義的@Autowired注解還支持幾個由JSR規范定義的注解它們分別是@Resource@PostConstruct以及@PreDestroy
@Resource的作用相當於@Autowired只不過@Autowired按byType自動注入而@Resource默認按byName自動注入罷了@Resource有兩個屬性是比較重要的分別是name和typeSpring將@Resource注解的name屬性解析為bean的名字而type屬性則解析為bean的類型所以如果使用name屬性則使用byName的自動注入策略而使用type屬性時則使用byType自動注入策略如果既不指定name也不指定type屬性這時將通過反射機制使用byName自動注入策略
@Resource裝配順序
如果同時指定了name和type則從Spring上下文中找到唯一匹配的bean進行裝配找不到則拋出異常
如果指定了name則從上下文中查找名稱(id)匹配的bean進行裝配找不到則拋出異常
如果指定了type則從上下文中找到類型匹配的唯一bean進行裝配找不到或者找到多個都會拋出異常
如果既沒有指定name又沒有指定type則自動按照byName方式進行裝配(見)如果沒有匹配則回退為一個原始類型(UserDao)進行匹配如果匹配則自動裝配
@PostConstruct(JSR)
在方法上加上注解@PostConstruct這個方法就會在Bean初始化之後被Spring容器執行(注Bean初始化包括實例化Bean並裝配Bean的屬性(依賴注入))
它的一個典型的應用場景是當你需要往Bean裡注入一個其父類中定義的屬性而你又無法復寫父類的屬性或屬性的setter方法時如
Java代碼
public class UserDaoImpl extends HibernateDaoSupport implements UserDao {
private SessionFactory mySessionFacotry;
@Resource
public void setMySessionFacotry(SessionFactory sessionFacotry) {
thismySessionFacotry = sessionFacotry;
}
@PostConstruct
public void injectSessionFactory() {
supersetSessionFactory(mySessionFacotry);
}
}
這裡通過@PostConstruct為UserDaoImpl的父類裡定義的一個sessionFactory私有屬性注入了我們自己定義的sessionFactory(父類的setSessionFactory方法為final不可復寫)之後我們就可以通過調用supergetSessionFactory()來訪問該屬性了
@PreDestroy(JSR)
在方法上加上注解@PreDestroy這個方法就會在Bean初始化之後被Spring容器執行由於我們當前還沒有需要用到它的場景這裡不不去演示其用法同@PostConstruct
使用<context:annotationconfig />簡化配置
Spring添加了一個新的context的Schema命名空間該命名空間對注釋驅動屬性文件引入加載期織入等功能提供了便捷的配置我們知道注釋本身是不會做任何事情的它僅提供元數據信息要使元數據信息真正起作用必須讓負責處理這些元數據的處理器工作起來
AutowiredAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor就是處理這些注釋元數據的處理器但是直接在Spring配置文件中定義這些Bean顯得比較笨拙Spring為我們提供了一種方便的注冊這些BeanPostProcessor的方式這就是<context:annotationconfig />
Java代碼
<beans xmlns=/schema/beans xmlns:xsi=//XMLSchemainstance xmlns:context=/schema/context
xsi:schemaLocation=/schema/beans
/schema/beans/springbeansxsd
/schema/context
/schema/context/springcontextxsd>
<context:annotationconfig />
</beans>
<context:annotationconfig />將隱式地向Spring容器注冊AutowiredAnnotationBeanPostProcessorCommonAnnotationBeanPostProcessor PersistenceAnnotationBeanPostProcessor以及RequiredAnnotationBeanPostProcessor這個BeanPostProcessor
使用Spring注解完成Bean的定義
以上我們介紹了通過@Autowired或@Resource來實現在Bean中自動注入的功能下面我們將介紹如何注解Bean從而從XML配置文件中完全移除Bean定義的配置
@Component(不推薦使用)@Repository@Service@Controller
只需要在對應的類上加上一個@Component注解就將該類定義為一個Bean了
Java代碼
@Component
public class UserDaoImpl extends HibernateDaoSupport implements UserDao {
}
使用@Component注解定義的Bean默認的名稱(id)是小寫開頭的非限定類名如這裡定義的Bean名稱就是userDaoImpl你也可以指定Bean的名稱
@Component(userDao)
@Component是所有受Spring管理組件的通用形式Spring還提供了更加細化的注解形式@Repository@Service@Controller它們分別對應存儲層Bean業務層Bean和展示層Bean目前版本()中這些注解與@Component的語義是一樣的完全通用在Spring以後的版本中可能會給它們追加更多的語義所以我們推薦使用@Repository@Service@Controller來替代@Component
使用<context:componentscan />讓Bean定義注解工作起來
Java代碼
<beans xmlns=/schema/beans xmlns:xsi=//XMLSchemainstance xmlns:context=/schema/context
xsi:schemaLocation=/schema/beans
/schema/beans/springbeansxsd
/schema/context
/schema/context/springcontextxsd>
<context:componentscan basepackage=comkedacomksoa />
</beans>
這裡所有通過<bean>元素定義Bean的配置內容已經被移除僅需要添加一行<context:componentscan />配置就解決所有問題了——Spring XML配置文件得到了極致的簡化(當然配置元數據還是需要的只不過以注釋形式存在罷了)<context:componentscan />的basepackage屬性指定了需要掃描的類包類包及其遞歸子包中所有的類都會被處理
<context:componentscan />還允許定義過濾器將基包下的某些類納入或排除Spring支持以下種類型的過濾方式
過濾器類型 表達式范例 說明
注解 orgexampleSomeAnnotation 將所有使用SomeAnnotation注解的類過濾出來
類名指定 orgexampleSomeClass 過濾指定的類
正則表達式 com\kedacom\spring\annotation\web\* 通過正則表達式過濾一些類
AspectJ表達式 orgexample*Service+ 通過AspectJ表達式過濾一些類
以正則表達式為例我列舉一個應用實例
Java代碼
<context:componentscan basepackage=comcasheenspringannotation>
<context:excludefilter type=regex expression=com\casheen\spring\annotation\web\* />
</context:componentscan>
值得注意的是<context:componentscan />配置項不但啟用了對類包進行掃描以實施注釋驅動Bean定義的功能同時還啟用了注釋驅動自動注入的功能(即還隱式地在內部注冊了AutowiredAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor)因此當使用<context:componentscan />後就可以將<context:annotationconfig />移除了
使用@Scope來定義Bean的作用范圍
在使用XML定義Bean時我們可能還需要通過bean的scope屬性來定義一個Bean的作用范圍我們同樣可以通過@Scope注解來完成這項工作
Java代碼
@Scope(session)
@Component()
public class UserSessionBean implements Serializable {
}
From:http://tw.wingwit.com/Article/program/Java/ky/201311/28094.html