Spring 2.5 Annotation

[b]Spring 2.5 Annotation[/b]

[b]Reference:[/b]
http://www.ibm.com/developerworks/cn/java/j-lo-spring25-ioc/
http://www.ibm.com/developerworks/cn/java/j-lo-spring25-mvc/
http://www.ibm.com/developerworks/cn/opensource/os-cn-spring-iocannt/
http://www.ibm.com/developerworks/cn/java/
《精通 Spring 2.x—企業應用開發精解》陳雄華 ([email protected]), 技術總監, 寶寶淘網絡科技有限公司
http://download.csdn.net/detail/zheng12tian/2584987

[b]Appicable scene:[/b]
Spring with Annotation:
1) Bean 的依賴關係是固定的,(如 Service 使用了哪幾個 DAO 類),這種配置信息不會在部署時發生調整。
2) 類是自己寫的,可以在源碼裏面加入 Annotation.

Spring with XML:
1) 部署時需要修改的,放在xml裏面修改後不需要編譯源碼,例如: 數據源、緩存池、持久層操作模板類、事務管理等內容的配置。
2) 引用第三方庫,則無法修改源代碼,例如:JdbcTemplate、SessionFactoryBean

[b]Spring with xml:[/b]
<?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">

<bean id="boss" class="com.baobaotao.Boss">
<property name="car" ref="car"/>
<property name="office" ref="office" />
</bean>

<bean id="office" class="com.baobaotao.Office">
<property name="officeNo" value="002"/>
</bean>

<bean id="car" class="com.baobaotao.Car" scope="singleton">
<property name="brand" value="Jaguar XJ"/>
<property name="price" value="89"/>
</bean>
</beans>

[b]注入屬性 @Autowired[/b]
//標註在字段上
public class Boss {
@Autowired
private Car car;

@Autowired
private Office office;
}

//標註在方法上
public class Boss {
private Car car;
private Office office;

@Autowired
public void setCar(Car car) {
this.car = car;
}
}

//標註在構造函數上
public class Boss {
private Car car;
private Office office;

@Autowired
public Boss(Car car ,Office office){
this.car = car;
this.office = office ;
}
}
//beans.xml
<?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">

<!-- Spring 通過一個 BeanPostProcessor 對 @Autowired 進行解析,所以要讓 @Autowired 起作用必須事先在 Spring 容器中聲明 AutowiredAnnotationBeanPostProcessor Bean。-->
<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>

<!-- 移除 boss Bean 的屬性注入配置的信息, 掃描 Autowired 標註,注入屬性, 默認按類型匹配 -->
<bean id="boss" class="com.baobaotao.Boss"/>

<bean id="office" class="com.baobaotao.Office">
<property name="officeNo" value="001"/>
</bean>

<bean id="car" class="com.baobaotao.Car" scope="singleton">
<property name="brand" value="Bugatti"/>
<property name="price" value="4200"/>
</bean>
</beans>

1) 當找不到一個匹配的 Bean 時,Spring 容器將拋出 BeanCreationException 異常,並指出必須至少擁有一個匹配的 Bean。可以使用 @Autowired(required = false)
2) 如果 Spring 容器中擁有多個候選 Bean,Spring 容器在啓動時也會拋出 BeanCreationException 異常。
public class Boss {
@Autowired
private Car car;

@Autowired
@Qualifier("office")
private Office office;
}

@Autowired
public void setOffice(@Qualifier("office") Office office) {
this.office = office;
}

@Autowired 可以對成員變量、方法以及構造函數
@Qualifier 的標註對象是成員變量、方法入參、構造函數入參。
//自動注入的策略就從 byType 轉變成 byName

[b]@Resource 注入屬性[/b]
@Autowired 是 Spring 提供的, 默認按 byType 自動注入
@Resource 是 JSR250 定義的, Spring 也支持,與 @Autowired 等效, (默認按 byName 自動注入)

讓 @Resource 生效,需要加 <bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"/>

public class Boss {
// 自動注入類型爲 Car 的 Bean
@Resource
private Car car;

// 自動注入 bean 名稱爲 office 的 Bean
@Resource(name = "office")
private Office office;
}

[b]JSR 250[/b]
JSR250 定義了 @Resource, @PostConstruct 和 @PreDestroy
@PostConstruct / @PreDestroy 等效於 實現 InitializingBean/DisposableBean 接口進行初始化和銷燬。也可以通過 <bean> 元素的 init-method/destroy-method 屬性指定初始化之後 / 銷燬之前調用的操作方法。
@PostConstruct 可以定義在多個初始化方法上。而接口或者 init-method 只能一個。

讓 JSR250的 Annotations 生效, 需要在 xml 裏面加 BeanPostProcessor:
<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"/>

public static void main(String[] args) {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(new String[] {"beans.xml"};);
Boss boss = (Boss) ctx.getBean("boss");
System.out.println(boss);
ctx.destroy();// 關閉 Spring 容器,以觸發 Bean 銷燬方法的執行
}

[b]使用<context:annotation-config/> 簡化配置[/b]
<context:annotationconfig/> 將隱式地向 Spring 容器註冊 AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor、PersistenceAnnotationBeanPostProcessor、RequiredAnnotationBeanPostProcessor。

//beans.xml
<?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="boss" class="com.baobaotao.Boss"/>

<bean id="office" class="com.baobaotao.Office">
<property name="officeNo" value="001"/>
</bean>

<bean id="car" class="com.baobaotao.Car" scope="singleton">
<property name="brand" value=" 紅旗 CA72"/>
<property name="price" value="2000"/>
</bean>
</beans>

[b]使用 @Component[/b]
通過 @Autowired 或 @Resource 在 Bean 類中使用自動注入功能,
但是 Bean 還是在 XML 文件中通過 <bean> 進行定義 —— 也就是說,在 XML 配置文件中定義 Bean,通過 @Autowired 或 @Resource 爲 Bean 的成員變量、方法入參或構造函數入參提供自動注入的功能。
通過註釋定義 Bean,從 XML 配置文件中完全移除 Bean 定義的配置: @Component

//默認實例化爲 car,首字母小寫,也可以指定名稱。 @Component("myCar")
@Component
public class Car {

}

@Component("boss")
public class Boss {
@Autowired
private Car car;

@Autowired
private Office office;

}

//beans.xml
<?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.baobaotao"/>
</beans>

Filter:
<context:component-scan base-package="com.baobaotao">
<context:include-filter type="regex" expression="com\.baobaotao\.service\..*"/>
<context:exclude-filter type="aspectj" expression="com.baobaotao.util..*"/>
</context:component-scan>

<context:component-scan/>
不但啓用了對類包進行掃描以實施註釋驅動 Bean 定義的功能,
同時還啓用了註釋驅動自動注入的功能(即還隱式地在內部註冊了 AutowiredAnnotationBeanPostProcessor 和 CommonAnnotationBeanPostProcessor),
因此當使用 <context:component-scan/> 後,就可以將 <context:annotation-config/> 移除了。

Scope
默認情況下通過 @Component 定義的 Bean 都是 singleton 的,如果需要使用其它作用範圍的 Bean,可以通過 @Scope 註釋來達到目標

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

}

[b]採用具有特殊語義的註釋[/b]
@Repository, @Service, @Controller, @Component 是等效的
但是從註釋類的命名上,這 3 個註釋分別和持久層、業務層和控制層(Web 層)相對應。
雖然目前這 3 個註釋和 @Component 相比沒有什麼新意,但 Spring 將在以後的版本中爲它們添加特殊的功能。
所以,如果 Web 應用程序採用了經典的三層分層結構的話,最好在持久層、業務層和控制層分別採用 @Repository, @Service 和 @Controller 對分層中的類進行註釋,而用 @Component 對那些比較中立的類進行註釋。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章