與大家共同成長
基于注釋(Annotation)的配置有越來越流行的趨勢,Spring 2.5 順應這種趨勢,提供了完全基于注釋配置 Bean、裝配 Bean 的功能,您可以使用基于注釋的 Spring IoC 替換原來基于 XML 的配置。
它可以充分利用 Java 的反射機制獲取類結構信息,這些信息可以有效減少配置的工作。如使用 JPA 注釋配置 ORM 映射時,我們就不需要指定 PO 的屬性名、類型等信息,如果關系表字段和 PO 屬性名、類型都一致,您甚至無需編寫任務屬性映射信息——因為這些信息都可以通過 Java 反射機制獲取。 注釋和 Java 代碼位于一個文件中,而 XML 配置采用獨立的配置文件,大多數配置信息在程序開發完成后都不會調整,如果配置信息和 Java 代碼放在一起,有助于增強程序的內聚性。而采用獨立的 XML 配置文件,程序員在編寫一個功能時,往往需要在程序文件和配置文件中不停切換,這種思維上的不連貫會降低開發效率。
因此在很多情況下,注釋配置比 XML 配置更受歡迎,注釋配置有進一步流行的趨勢。Spring 2.5 的一大增強就是引入了很多注釋類,現在您已經可以使用注釋配置完成大部分XML 配置的功能。在這篇文章里,我們將向您講述使用注釋進行 Bean 定義和依賴注入的內容。
UserDAO.java:
package com.tanlan.springdemo; /** * UserDAO接口 * * @author tanlan tl_smile@163.com * * @date 2009-8-3 */ public interface UserDAO { public void addUser(); }
UserJDBCDAO.java:
package com.tanlan.springdemo; /** * UserDAO的JDBC實現 * * @author tanlan tl_smile@163.com * * @date 2009-8-3 */ public class UserJDBCDAO implements UserDAO { public void addUser() { System.out.println("使用JDBC增加用戶信息!"); } }
UserService.java:
package com.tanlan.springdemo; /** * User業務邏輯處理類 * * @author tanlan tl_smile@163.com * * @date 2009-8-3 */ public class UserService { private UserDAO userDAO; public void addUser() { userDAO.addUser(); } public UserDAO getUserDAO() { return userDAO; } public void setUserDAO(UserDAO userDAO) { this.userDAO = userDAO; } }
配置文件 spring.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 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"> <bean id="userJdbcDAO" class="com.tanlan.springdemo.UserJDBCDAO"></bean> <bean id="userService" class="com.tanlan.springdemo.UserService"> <property name="userDAO" ref="userJdbcDAO"></property> </bean> </beans>
測試類Test.java:
package com.tanlan.springdemo; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Test { public static void main(String[] args) { String[] files = { "spring.xml" }; ApplicationContext context = new ClassPathXmlApplicationContext(files); UserService userService = (UserService) context.getBean("userService"); userService.addUser(); } }
Spring 2.5 引入了 @Autowired 注釋,它可以對類成員變量、方法及構造函數進行標注,完成自動裝配的工作。
對UserService.java的改進:
package com.tanlan.springdemo; import org.springframework.beans.factory.annotation.Autowired; /** * User業務邏輯處理類 * * @author tanlan tl_smile@163.com * * @date 2009-8-3 */ public class UserService { @Autowired private UserDAO userDAO; public void addUser() { userDAO.addUser(); } }
這個類甚至可以省略getter/setter.
配置文件spring.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 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"> <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"></bean> <bean id="userJdbcDAO" class="com.tanlan.springdemo.UserJDBCDAO"></bean> <bean id="userService" class="com.tanlan.springdemo.UserService"></bean> </beans>
Spring 通過一個 BeanPostProcessor 對 @Autowired 進行解析,所以要讓 @Autowired 起作用必須事先在 Spring 容器中聲明 AutowiredAnnotationBeanPostProcessor Bean。
UserService類的屬性不需要配置了。
在默認情況下使用 @Autowired 注釋進行自動注入時,Spring 容器中匹配的候選 Bean 數目必須有且僅有一個。當找不到一個匹配的 Bean 時,Spring 容器將拋出BeanCreationException 異常,并指出必須至少擁有一個匹配的 Bean。 和找不到一個類型匹配 Bean 相反的一個錯誤是:如果 Spring 容器中擁有多個候選Bean,Spring 容器在啟動時也會拋出 BeanCreationException 異常。 Spring 允許我們通過 @Qualifier 注釋指定注入 Bean 的名稱
加入現在多了一個UserDAO的實現類
UserHibernateDAO.java:
package com.tanlan.springdemo; /** * UserDAO的Hibernate實現 * * @author tanlan tl_smile@163.com * * @date 2009-8-3 */ public class UserHibernateDAO implements UserDAO { public void addUser() { System.out.println("使用Hibernate增加用戶信息!"); } }
更新spring.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 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"> <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"></bean> <bean id="userJdbcDAO" class="com.tanlan.springdemo.UserJDBCDAO"></bean> <bean id="userHibernateDAO" class="com.tanlan.springdemo.UserHibernateDAO"></bean> <bean id="userService" class="com.tanlan.springdemo.UserService"></bean> </beans>
當Spring自動找尋UserDAO類型的類時,會找到兩個符合要求的類:
No unique bean of type [com.tanlan.springdemo.UserDAO] is defined: expected single matching bean but found 2: [userJdbcDAO, userHibernateDAO]
需要改進UserService.java:
package com.tanlan.springdemo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; /** * User業務邏輯處理類 * * @author tanlan tl_smile@163.com * * @date 2009-8-3 */ public class UserService { @Autowired @Qualifier("userJdbcDAO") private UserDAO userDAO; public void addUser() { userDAO.addUser(); } }
Spring 2.1 添加了一個新的 context 的 Schema 命名空間,該命名空間對注釋驅動、屬性文件引入、加載期織入等功能提供了便捷的配置.
改進spring.xml:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" 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 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"> <context:annotation-config></context:annotation-config> <bean id="userJdbcDAO" class="com.tanlan.springdemo.UserJDBCDAO"></bean> <bean id="userHibernateDAO" class="com.tanlan.springdemo.UserHibernateDAO"></bean> <bean id="userService" class="com.tanlan.springdemo.UserService"></bean> </beans>
注意命名空間:xmlns:context=http://www.springframework.org/schema/context的添加。
以及<context:annotation-config/>的使用。
Spring 2.5 提供的 @Component 注釋可以定義 Bean,從 XML 配置文件中完全移除 Bean 定義的配置。
改進UserJDBCDAO.java:
package com.tanlan.springdemo; import org.springframework.stereotype.Component; /** * UserDAO的JDBC實現 * * @author tanlan tl_smile@163.com * * @date 2009-8-3 */ @Component("userJdbcDAO") public class UserJDBCDAO implements UserDAO { public void addUser() { System.out.println("使用JDBC增加用戶信息!"); } }
改進UserHibernateDAO.java:
package com.tanlan.springdemo; import org.springframework.stereotype.Component; /** * UserDAO的Hibernate實現 * * @author tanlan tl_smile@163.com * * @date 2009-8-3 */ @Component("userHibernateDAO") public class UserHibernateDAO implements UserDAO { public void addUser() { System.out.println("使用Hibernate增加用戶信息!"); } }
改進UserService.java:
package com.tanlan.springdemo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; /** * User業務邏輯處理類 * * @author tanlan tl_smile@163.com * * @date 2009-8-3 */ @Component public class UserService { @Autowired @Qualifier("userJdbcDAO") private UserDAO userDAO; public void addUser() { userDAO.addUser(); } }
改進spring.xml:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" 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 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"> <context:component-scan base-package="com.tanlan.springdemo"></context:component-scan> </beans>
在使用 @Component 注釋后,Spring 容器必須啟用類掃描機制以啟用注釋驅動 Bean 定義和注釋驅動 Bean 自動注入的策略. <context:component-scan/> 的 base-package 屬性指定了需要掃描的類包,類包及其遞歸子包中所有的類都會被處理.
是否有了這些 IOC 注釋,我們就可以完全摒除原來 XML 配置的方式呢?答案是否定的。有以下幾點原因: 注釋配置不一定在先天上優于 XML 配置。如果 Bean 的依賴關系是固定的,(如Service 使用了哪幾個 DAO 類),這種配置信息不會在部署時發生調整,那么注釋配置優于 XML 配置;反之如果這種依賴關系會在部署時發生調整,XML 配置顯然又優于注釋配置,因為注釋是對 Java 源代碼的調整,您需要重新改寫源代碼并重新編譯才可以實施調整。 如果 Bean 不是自己編寫的類(如 JdbcTemplate、SessionFactoryBean 等),注釋配置將無法實施,此時 XML 配置是唯一可用的方式。 注釋配置往往是類級別的,而 XML 配置則可以表現得更加靈活。比如相比于@Transaction 事務注釋,使用 aop/tx 命名空間的事務配置更加靈活和簡單。
所以在實現應用中,我們往往需要同時使用注釋配置和 XML 配置,對于類級別且不會發生變動的配置可以優先考慮注釋配置;而對于那些第三方類以及容易發生調整的配置則應優先考慮使用 XML 配置。Spring 會在具體實施 Bean 創建和 Bean 注入之前將這兩種配置方式的元信息融合在一起。
Copyright @ 小菜毛毛 Powered by: .Text and ASP.NET Theme by: .NET Monster