# 【第十二章】零配置 之 12.3 注解實現Bean定義 ——跟我學spring3
## 12.3? 注解實現Bean定義
### 12.3.1? 概述
前邊介紹的Bean定義全是基于XML方式定義配置元數據,且在【12.2注解實現Bean依賴注入】一節中介紹了通過注解來減少配置數量,但并沒有完全消除在XML配置文件中的Bean定義,因此有沒有方式完全消除XML配置Bean定義呢?
Spring提供通過掃描類路徑中的特殊注解類來自動注冊Bean定義。同注解驅動事務一樣需要開啟自動掃描并注冊Bean定義支持,使用方式如下(resources/chapter12/ componentDefinitionWithAnnotation.xml):
```
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<aop:aspectj-autoproxy />
<context:component-scan base-package="cn.javass.spring.chapter12"/>
</beans>
```
使用<context:component-scan>標簽來表示需要要自動注冊Bean定義,而通過base-package屬性指定掃描的類路徑位置。
<context:component-scan>標簽將自動開啟“**注解實現Bean依賴注入**”支持。
此處我們還通過<aop:aspectj-autoproxy/>用于開啟Spring對@AspectJ風格切面的支持。
Spring基于注解實現Bean定義支持如下三種注解:
* **Spring自帶的@Component注解及擴展@Repository、@Service、@Controller**,如圖12-1所示;
* **JSR-250 1.1版本中中定義的@ManagedBean注解**,是Java EE 6標準規范之一,不包括在JDK中,需要在應用服務器環境使用(如Jboss),如圖12-2所示;
* **JSR-330的@Named注解**,如圖12-3所示。

圖12-1 Spring自帶的@Component注解及擴展

圖12-2 JSR-250中定義的@ManagedBean注解及自定義擴展

圖12-3 JSR-330的@Named注解及自定義擴展
圖12-2和圖12-3中的自定義擴展部分是為了配合Spring自帶的模式注解擴展自定義的,并不包含在Java EE 6規范中,在Java EE 6中相應的服務層、DAO層功能由EJB來完成。
在Java EE中有些注解運行放置在多個地方,如@Named允許放置在類型、字段、方法參數上等,因此一般情況下放置在類型上表示定義,放置在參數、方法等上邊一般代表使用(如依賴注入等等)。
### 12.3.2? Spring自帶的@Component注解及擴展
**一、@Component:定義Spring管理Bean,**使用方式如下:
```
@Component("標識符")
POJO類
```
在類上使用@Component注解,表示該類定義為Spring管理Bean,使用默認value(可選)屬性表示Bean標識符。
1、定義測試Bean類:
```
package cn.javass.spring.chapter12;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
@Component("component")
public class TestCompoment {
@Autowired
private ApplicationContext ctx;
public ApplicationContext getCtx() {
return ctx;
}
}
```
2、Spring配置文件使用chapter12/ componentDefinitionWithAnnotation.xml即可且無需修改;
3、定義測試類和測試方法:
```
package cn.javass.spring.chapter12;
//省略import
public class ComponentDefinitionWithAnnotationTest {
private static String configLocation = "classpath:chapter12/componentDefinitionWithAnnotation.xml";
private static ApplicationContext ctx = new ClassPathXmlApplicationContext(configLocation);
@Test
public void testComponent() {
TestCompoment component = ctx.getBean("component", TestCompoment.class);
Assert.assertNotNull(component.getCtx());
}
}
```
測試成功說明被@Component注解的POJO類將自動被Spring識別并注冊到Spring容器中,且自動支持自動裝配。
**@AspectJ風格的切面可以通過@Compenent注解標識其為Spring管理Bean,而@Aspect注解不能被Spring自動識別并注冊為Bean,必須通過@Component注解來完成,示例如下:**
```
package cn.javass.spring.chapter12.aop;
//省略import
@Component
@Aspect
public class TestAspect {
@Pointcut(value="execution(* *(..))")
private void pointcut() {}
@Before(value="pointcut()")
public void before() {
System.out.println("=======before");
}
}
```
**通過@Component將切面定義為Spring管理Bean。**
**二、@Repository:@Component擴展,被@Repository注解的POJO類表示DAO層實現,從而見到該注解就想到DAO層實現,使用方式和@Component相同;**
1、定義測試Bean類:
```
package cn.javass.spring.chapter12.dao.hibernate;
import org.springframework.stereotype.Repository;
@Repository("testHibernateDao")
public class TestHibernateDaoImpl {
}
```
2、Spring配置文件使用chapter12/ componentDefinitionWithAnnotation.xml即可且無需修改;
3、定義測試方法:
```
@Test
public void testDao() {
TestHibernateDaoImpl dao =
ctx.getBean("testHibernateDao", TestHibernateDaoImpl.class);
Assert.assertNotNull(dao);
}
```
測試成功說明被@Repository注解的POJO類將自動被Spring識別并注冊到Spring容器中,且自動支持自動裝配,并且被@Repository注解的類表示DAO層實現。
**三、@Service:@Component擴展,被@Service注解的POJO類表示Service層實現,從而見到該注解就想到Service層實現,使用方式和@Component相同;**
1、定義測試Bean類:
```
package cn.javass.spring.chapter12.service.impl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import cn.javass.spring.chapter12.dao.hibernate.TestHibernateDaoImpl;
@Service("testService")
public class TestServiceImpl {
@Autowired
@Qualifier("testHibernateDao")
private TestHibernateDaoImpl dao;
public TestHibernateDaoImpl getDao() {
return dao;
}
}
```
2、Spring配置文件使用chapter12/ componentDefinitionWithAnnotation.xml即可且無需修改;
3、定義測試方法:
```
@Test
public void testService() {
TestServiceImpl service = ctx.getBean("testService", TestServiceImpl.class);
Assert.assertNotNull(service.getDao());
}
```
測試成功說明被@Service注解的POJO類將自動被Spring識別并注冊到Spring容器中,且自動支持自動裝配,并且被@Service注解的類表示Service層實現。
**四、@Controller:@Component擴展,被@Controller注解的類表示Web層實現,從而見到該注解就想到Web層實現,使用方式和@Component相同;**
1、定義測試Bean類:
```
package cn.javass.spring.chapter12.action;
//省略import
@Controller
public class TestAction {
@Autowired
private TestServiceImpl testService;
public void list() {
//調用業務邏輯層方法
}
}
```
2、Spring配置文件使用chapter12/ componentDefinitionWithAnnotation.xml即可且無需修改;
3、定義測試方法:
```
@Test
public void testWeb() {
TestAction action = ctx.getBean("testAction", TestAction.class);
Assert.assertNotNull(action);
}
```
測試成功說明被@Controller注解的類將自動被Spring識別并注冊到Spring容器中,且自動支持自動裝配,并且被@Controller注解的類表示Web層實現。
大家是否注意到@Controller中并沒有定義Bean的標識符,那么默認Bean的名字將是以小寫開頭的類名(不包括包名),即如“TestAction”類的Bean標識符為“testAction”。
**六、自定義擴展:Spring內置了三種通用的擴展注解@Repository、@Service、@Controller?,大多數情況下沒必要定義自己的擴展,在此我們演示下如何擴展@Component注解來滿足某些特殊規約的需要;**
在此我們可能需要一個緩存層用于定義緩存Bean,因此我們需要自定義一個@Cache的注解來表示緩存類。
1、擴展@Component:
```
package cn.javass.spring.chapter12.stereotype;
//省略import
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Cache{
String value() default "";
}
```
擴展十分簡單,只需要在擴展的注解上注解@Component即可,**@Repository、**@Service、@Controller也是通過該方式實現的,沒什么特別之處
2、定義測試Bean類:
```
package cn.javass.spring.chapter12.cache;
@Cache("cache")
public class TestCache {
}
```
2、Spring配置文件使用chapter12/ componentDefinitionWithAnnotation.xml即可且無需修改;
3、定義測試方法:
```
@Test
public void testCache() {
TestCache cache = ctx.getBean("cache", TestCache.class);
Assert.assertNotNull(cache);
}
```
測試成功說明自定義的@Cache注解也能很好的工作,而且實現了我們的目的,使用@Cache來表示被注解的類是Cache層Bean。
### 12.3.3? JSR-250中定義的@ManagedBean注解
@javax.annotation.ManagedBean需要在實現Java EE 6規范的應用服務器上使用,雖然Spring3實現了,但@javax.annotation.ManagedBean只有在Java EE 6環境中才有定義,因此測試前需要我們定義ManagedBean類。
1、定義javax.annotation.ManagedBean注解類:
```
package javax.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ManagedBean {
String value() default "";
}
```
其和@Component完全相同,唯一不同的就是名字和創建者(一個是Spring,一個是Java EE規范)。
2、定義測試Bean類:
```
package cn.javass.spring.chapter12;
import javax.annotation.Resource;
import org.springframework.context.ApplicationContext;
@javax.annotation.ManagedBean("managedBean")
public class TestManagedBean {
@Resource
private ApplicationContext ctx;
public ApplicationContext getCtx() {
return ctx;
}
}
```
2、Spring配置文件使用chapter12/ componentDefinitionWithAnnotation.xml即可且無需修改;
3、定義測試方法:
```
@Test
public void testManagedBean() {
TestManagedBean testManagedBean = ctx.getBean("managedBean", TestManagedBean.class);
Assert.assertNotNull(testManagedBean.getCtx());
}
```
測試成功說明被@ManagedBean注解類也能正常工作。
自定義擴展就不介紹了,大家可以參考@Component來完成如圖12-2所示的自定義擴展部分。
### 12.3.4? JSR-330的@Named注解
@Named不僅可以用于依賴注入來指定注入的Bean的標識符,還可以用于定義Bean。即注解在類型上表示定義Bean,注解在非類型上(如字段)表示指定依賴注入的Bean標識符。
1、定義測試Bean類:
```
package cn.javass.spring.chapter12;
//省略import
@Named("namedBean")
public class TestNamedBean {
@Inject
private ApplicationContext ctx;
public ApplicationContext getCtx() {
return ctx;
}
}
```
2、Spring配置文件使用chapter12/ componentDefinitionWithAnnotation.xml即可且無需修改;
3、定義測試方法:
```
@Test
public void testNamedBean() {
TestNamedBean testNamedBean =
ctx.getBean("namedBean", TestNamedBean.class);
Assert.assertNotNull(testNamedBean.getCtx());
}
```
測試成功說明被@Named注解類也能正常工作。
自定義擴展就不介紹了,大家可以參考@Component來完成如圖12-3所示的自定義擴展部分。
### 12.3.5? 細粒度控制Bean定義掃描
在XML配置中完全消除了Bean定義,而是只有一個<context:component-scan>標簽來支持注解Bean定義掃描。
前邊的示例完全采用默認掃描設置,如果我們有幾個組件不想被掃描并自動注冊、我們想更改默認的Bean標識符生成策略該如何做呢?接下來讓我們看一下如何細粒度的控制Bean定義掃描,具體定義如下:
```
<context:component-scan
base-package=""
resource-pattern="**/*.class"
name-generator="org.springframework.context.annotation.AnnotationBeanNameGenerator"
use-default-filters="true"
annotation-config="true">
<context:include-filter type="aspectj" expression=""/>
<context:exclude-filter type="regex" expression=""/>
</context:component-scan>
```
* **base-package:**表示掃描注解類的開始位置,即將在指定的包中掃描,其他包中的注解類將不被掃描,默認將掃描所有類路徑;
* **resource-pattern:**表示掃描注解類的后綴匹配模式,即“base-package+resource-pattern”將組成匹配模式用于匹配類路徑中的組件,默認后綴為“**/*.class”,即指定包下的所有以.class結尾的類文件;
* **name-generator:默認情況下的Bean標識符生成策略,默認是**AnnotationBeanNameGenerator,其將生成以小寫開頭的類名(不包括包名);可以自定義自己的標識符生成策略;
* **use-default-filters:**默認為true表示過濾@Component、@ManagedBean、@Named注解的類,如果改為false默認將不過濾這些默認的注解來定義Bean,即這些注解類不能被過濾到,即不能通過這些注解進行Bean定義;
* **annotation-config:**表示是否自動支持注解實現Bean依賴注入,默認支持,如果設置為false,將關閉支持注解的依賴注入,需要通過<context:annotation-config/>開啟。
默認情況下將自動過濾@Component、@ManagedBean、@Named注解的類并將其注冊為Spring管理Bean,可以通過在<context:component-scan>標簽中指定自定義過濾器將過濾到匹配條件的類注冊為Spring管理Bean,具體定義方式如下:
```
<context:include-filter type="aspectj" expression=""/>
<context:exclude-filter type="regex" expression=""/>
```
* **<context:include-filter>:**表示過濾到的類將被注冊為Spring管理Bean;
* **<context:exclude-filter>:**表示過濾到的類將不被注冊為Spring管理Bean,它比<context:include-filter>具有更高優先級;
* **type:**表示過濾器類型,目前支持注解類型、類類型、正則表達式、aspectj表達式過濾器,當然也可以自定義自己的過濾器,實現org.springframework.core.type.filter.TypeFilter即可;
* **expression:**表示過濾器表達式。
一般情況下沒必要進行自定義過濾,如果需要請參考如下示例:
1、cn.javass.spring.chapter12.TestBean14自動注冊為Spring管理Bean:
```
<context:include-filter type="assignable" expression="cn.javass.spring.chapter12.TestBean14"/>
```
2、把所有注解為org.aspectj.lang.annotation.Aspect自動注冊為Spring管理Bean:
```
<context:include-filter type="annotation"
expression="org.aspectj.lang.annotation.Aspect"/>
```
3、將把匹配到正則表達式“cn\.javass\.spring\.chapter12\.TestBean2*”排除,不注冊為Spring管理Bean:
```
<context:exclude-filter type="regex" expression="cn\.javass\.spring\.chapter12\.TestBean2*"/>
```
4、將把匹配到aspectj表達式“cn.javass.spring.chapter12.TestBean3*”排除,不注冊為Spring管理Bean:
```
<context:exclude-filter type="aspectj" expression="cn.javass.spring.chapter12.TestBean3*"/>
```
具體使用就要看項目需要了,如果以上都不滿足需要請考慮使用自定義過濾器。
### 12.3.6? 提供更多的配置元數據
**1、@Lazy:**定義Bean將延遲初始化,使用方式如下:
```
@Component("component")
@Lazy(true)
public class TestCompoment {
……
}
```
使用@Lazy注解指定Bean需要延遲初始化。
2、**@DependsOn:**定義Bean初始化及銷毀時的順序,使用方式如下:
```
@Component("component")
@DependsOn({"managedBean"})
public class TestCompoment {
……
}
```
**3、@Scope**:定義Bean作用域,默認單例,使用方式如下:
```
@Component("component")
@Scope("singleton")
public class TestCompoment {
……
}
```
**4、@Qualifier:**指定限定描述符,對應于基于XML配置中的<qualifier>標簽,使用方式如下:
```
@Component("component")
@Qualifier("component")
public class TestCompoment {
……
}
```
可以使用復雜的擴展,如@Mysql等等。
**5、@Primary:**自動裝配時當出現多個Bean候選者時,被注解為@Primary的Bean將作為首選者,否則將拋出異常,使用方式如下:
```
@Component("component")
@Primary
public class TestCompoment {
……
}
```
原創內容,轉載請注明私塾在線【http://sishuok.com/forum/blogPost/list/2547.html】
- 跟我學 Spring3
- 【第二章】 IoC 之 2.1 IoC基礎 ——跟我學Spring3
- 【第二章】 IoC 之 2.2 IoC 容器基本原理 ——跟我學Spring3
- 【第二章】 IoC 之 2.3 IoC的配置使用——跟我學Spring3
- 【第三章】 DI 之 3.1 DI的配置使用 ——跟我學spring3
- 【第三章】 DI 之 3.2 循環依賴 ——跟我學spring3
- 【第三章】 DI 之 3.3 更多DI的知識 ——跟我學spring3
- 【第三章】 DI 之 3.4 Bean的作用域 ——跟我學spring3
- 【第四章】 資源 之 4.1 基礎知識 ——跟我學spring3
- 【第四章】 資源 之 4.2 內置Resource實現 ——跟我學spring3
- 【第四章】 資源 之 4.3 訪問Resource ——跟我學spring3
- 【第四章】 資源 之 4.4 Resource通配符路徑 ——跟我學spring3
- 【第五章】Spring表達式語言 之 5.1 概述 5.2 SpEL基礎 ——跟我學spring3
- 【第五章】Spring表達式語言 之 5.3 SpEL語法 ——跟我學spring3
- 【第五章】Spring表達式語言 之 5.4在Bean定義中使用EL—跟我學spring3
- 【第六章】 AOP 之 6.1 AOP基礎 ——跟我學spring3
- 【第六章】 AOP 之 6.2 AOP的HelloWorld ——跟我學spring3
- 【第六章】 AOP 之 6.3 基于Schema的AOP ——跟我學spring3
- 【第六章】 AOP 之 6.4 基于@AspectJ的AOP ——跟我學spring3
- 【第六章】 AOP 之 6.5 AspectJ切入點語法詳解 ——跟我學spring3
- 【第六章】 AOP 之 6.6 通知參數 ——跟我學spring3
- 【第六章】 AOP 之 6.7 通知順序 ——跟我學spring3
- 【第六章】 AOP 之 6.8 切面實例化模型 ——跟我學spring3
- 【第六章】 AOP 之 6.9 代理機制 ——跟我學spring3
- 【第七章】 對JDBC的支持 之 7.1 概述 ——跟我學spring3
- 【第七章】 對JDBC的支持 之 7.2 JDBC模板類 ——跟我學spring3
- 【第七章】 對JDBC的支持 之 7.3 關系數據庫操作對象化 ——跟我學spring3
- 【第七章】 對JDBC的支持 之 7.4 Spring提供的其它幫助 ——跟我學spring3【私塾在線原創】
- 【第七章】 對JDBC的支持 之 7.5 集成Spring JDBC及最佳實踐 ——跟我學spring3
- 【第八章】 對ORM的支持 之 8.1 概述 ——跟我學spring3
- 【第八章】 對ORM的支持 之 8.2 集成Hibernate3 ——跟我學spring3
- 【第八章】 對ORM的支持 之 8.3 集成iBATIS ——跟我學spring3
- 【第八章】 對ORM的支持 之 8.4 集成JPA ——跟我學spring3
- 【第九章】 Spring的事務 之 9.1 數據庫事務概述 ——跟我學spring3
- 【第九章】 Spring的事務 之 9.2 事務管理器 ——跟我學spring3
- 【第九章】 Spring的事務 之 9.3 編程式事務 ——跟我學spring3
- 【第九章】 Spring的事務 之 9.4 聲明式事務 ——跟我學spring3
- 【第十章】集成其它Web框架 之 10.1 概述 ——跟我學spring3
- 【第十章】集成其它Web框架 之 10.2 集成Struts1.x ——跟我學spring3
- 【第十章】集成其它Web框架 之 10.3 集成Struts2.x ——跟我學spring3
- 【第十章】集成其它Web框架 之 10.4 集成JSF ——跟我學spring3
- 【第十一章】 SSH集成開發積分商城 之 11.1 概述 ——跟我學spring3
- 【第十一章】 SSH集成開發積分商城 之 11.2 實現通用層 ——跟我學spring3
- 【第十一章】 SSH集成開發積分商城 之 11.3 實現積分商城層 ——跟我學spring3
- 【第十二章】零配置 之 12.1 概述 ——跟我學spring3
- 【第十二章】零配置 之 12.2 注解實現Bean依賴注入 ——跟我學spring3
- 【第十二章】零配置 之 12.3 注解實現Bean定義 ——跟我學spring3
- 【第十二章】零配置 之 12.4 基于Java類定義Bean配置元數據 ——跟我學spring3
- 【第十二章】零配置 之 12.5 綜合示例-積分商城 ——跟我學spring3
- 【第十三章】 測試 之 13.1 概述 13.2 單元測試 ——跟我學spring3
- 【第十三章】 測試 之 13.3 集成測試 ——跟我學spring3
- 跟我學 Spring MVC
- SpringMVC + spring3.1.1 + hibernate4.1.0 集成及常見問題總結
- Spring Web MVC中的頁面緩存支持 ——跟我學SpringMVC系列
- Spring3 Web MVC下的數據類型轉換(第一篇)——《跟我學Spring3 Web MVC》搶先看
- Spring3 Web MVC下的數據格式化(第二篇)——《跟我學Spring3 Web MVC》搶先看
- 第一章 Web MVC簡介 —— 跟開濤學SpringMVC
- 第二章 Spring MVC入門 —— 跟開濤學SpringMVC
- 第三章 DispatcherServlet詳解 ——跟開濤學SpringMVC
- 第四章 Controller接口控制器詳解(1)——跟著開濤學SpringMVC
- 第四章 Controller接口控制器詳解(2)——跟著開濤學SpringMVC
- 第四章 Controller接口控制器詳解(3)——跟著開濤學SpringMVC
- 第四章 Controller接口控制器詳解 (4)——跟著開濤學SpringMVC
- 第四章 Controller接口控制器詳解(5)——跟著開濤學SpringMVC
- 跟著開濤學SpringMVC 第一章源代碼下載
- 第二章 Spring MVC入門 源代碼下載
- 第四章 Controller接口控制器詳解 源代碼下載
- 第四章 Controller接口控制器詳解(6)——跟著開濤學SpringMVC
- 第四章 Controller接口控制器詳解(7 完)——跟著開濤學SpringMVC
- 第五章 處理器攔截器詳解——跟著開濤學SpringMVC
- 源代碼下載 第五章 處理器攔截器詳解——跟著開濤學SpringMVC
- 注解式控制器運行流程及處理器定義 第六章 注解式控制器詳解——跟著開濤學SpringMVC
- 源代碼下載 第六章 注解式控制器詳解
- SpringMVC3強大的請求映射規則詳解 第六章 注解式控制器詳解——跟著開濤學SpringMVC
- Spring MVC 3.1新特性 生產者、消費者請求限定 —— 第六章 注解式控制器詳解——跟著開濤學SpringMVC
- SpringMVC強大的數據綁定(1)——第六章 注解式控制器詳解——跟著開濤學SpringMVC
- SpringMVC強大的數據綁定(2)——第六章 注解式控制器詳解——跟著開濤學SpringMVC
- SpringMVC數據類型轉換——第七章 注解式控制器的數據驗證、類型轉換及格式化——跟著開濤學SpringMVC
- SpringMVC數據格式化——第七章 注解式控制器的數據驗證、類型轉換及格式化——跟著開濤學SpringMVC
- SpringMVC數據驗證——第七章 注解式控制器的數據驗證、類型轉換及格式化——跟著開濤學SpringMVC