扩展Spring——使用 Annotation将配置资源注入到Bean中
来源于http://www.blogjava.net/max/archive/2009/11/20/303112.html扩展Spring——使用 Annotation将配置资源注入到Bean中
好久没有更新BLOG了,这几天经常有朋友留言或EMAIL关心或鼓励我。其实这篇文章我大约两星期前就写好了,本来想投稿IBM的 developerWork中国。算啦,还是不等IBM的回复啦,发到我的自己的博客吧。
使用XML还是Annotation定义Bean
自从Spring 2.5开始引入使用Annotation定义Bean的方式之后,业界时常会有一些关于“到底是应该使用XML还是Annotation定义Bean呢?”的讨论。笔者本人就比较中庸,喜欢两者结合使用——对于一些框架性的基础型的Bean使用XML,对于业务性的Bean则使用Annotation。
然而,什么是“框架性的基础型的Bean”呢?这些Bean可以理解为由第三方开源组件提供的基础Java类的、又或者开发者在其基础上扩展而来的Bean,如数据源org.apache.commons.dbcp.BasicDataSource、事务管理器org.springframework.orm.hibernate3.HibernateTransactionManager等。这些Bean一般在应用程序中数量较少,却起着框架性和全局性的作用,对于此类Bean使用XML的好处是必要时可以通过修改一个或几个XML文件即可改变应用程序行为满足实际的项目需求,如下清单1所示。
1 <bean id="dataSource"
2 destroy-method="close">
3 <property name="driverClassName" value="${jdbc.driverClassName}" />
4 <property name="url" value="${jdbc.url}" />
5 <property name="username" value="${jdbc.username}" />
6 <property name="password" value="${jdbc.password}" />
7 </bean>
8 <bean id="transactionManager"
9 ref="sessionFactory" />
11 </bean>
清单 1. 使用XML定义框架性的Bean
此外,我们再来解释一下什么是“业务性的Bean”。这些Bean相对比较容易理解,也就是开发者根据业务需求编写的XxxDao、XxxManager或XxxService等。它们的特点是为数众多,定义起来比较麻烦。Annotation方式的简洁性可以最大程度地减少这方便的繁锁,而且可以避免诸如打错类型名称等常见的小错误。对比清单2、3和4的代码大家应该会有更为深刻的理解。
1 <bean id="myService" ref="myDao1" />
3 <!-- 其它DAO引用 -->
4 <property name="myDaoN" ref="myDaoN" />
5 </bean>
清单 2. 使用XML定义业务性的Bean
1 public class MyServiceImpl implements MyService {
2 private MyDao1 myDao1;
3 // 其它DAO
4 private MyDaoN myDaoN;
5
6 public void setMyDao1(MyDao1 myDao1) {
7 this.myDao1 = myDao1;
8 }
9
10 public void setMyDaoN(MyDaoN myDaoN) {
11 this.myDaoN = myDaoN;
12 }
13 // 其它业务代码
14 }清单 3. 使用XML方式时Bean的代码
1 @Service("myService")
2 public class MyServiceImpl implements MyService {
3 @Resource
4 private MyDao1 myDao1;
5 // 其它DAO
6 @Resource
7 private MyDaoN myDaoN;
8
9 // 其它业务代码
10 }清单 4. 使用Annotation方式的Bean代码
清单2、3实现的功能与清单4一样,都是在Spring容器中定义一个MyServiceImpl类型的Bean。孰优孰劣?一目了然!
在Spring中配置应用程序
大家可以从清单1看到有${xxx.xxx}的写法,有Spring开发经验的朋友可能已经知道这是使用Spring框架时配置应用程序的方式之一。为了方便一些不甚了解的朋友,笔者在此也大概讲述一下这种配置方式的步骤。
首先,在工程中新建一个资源(Property)文件(笔者建议放在源代码目录下),通过“名称=取值”的方式定义应用的配置,如下清单5所示。
1 jdbc.driverClassName=oracle.jdbc.driver.OracleDriver
2 jdbc.url=jdbc\:oracle\:thin\:@localhost\:1521\:ORCL
3 jdbc.username=max
4 jdbc.password=secret清单 5. 配置代码片段
然后,定义一个 org.springframework.beans.factory.config.PropertyPlaceholderConfigurer类型的Bean,id可以为propertyConfigurer。通常我们需要通过设定它的locations属性指明应用程序配置文件的路径。例如,以下清单6的代码就是指明配置在构建路径(Build Path)的根目录下的config.properties文件里。
1 <bean id="propertyConfigurer"
2 + config1 + ", config2 = " + config2
29 + "}");
30 }
31
32 public void printConfigXML() {
33 System.out.println("{ config3 = " + config3 + ", config4 = " + config4
34 + "}");
35 }
36
37 public static void main(String[] args) {
38 ApplicationContext appCtx = new ClassPathXmlApplicationContext(
39 "applicationContext.xml");
40
41 Demo demoAnn = (Demo) appCtx.getBean("demoAnn");
42 demoAnn.printConfigAnn();
43
44 Demo demoXML = (Demo) appCtx.getBean("demoXML");
45 demoXML.printConfigXML();
46 }
47 }清单 11. Demo.java
由于本示例的目的是演示@Config的使用,所以采取了最简单编码风格,而并非大家使用Spring时常用的基于接口的编码风格。另外,本示例同时通过XML和Annotation的方式在Spring中定义Demo类型的Bean,前者通过类中的XML和两个Setter注入配置资源,后者则是通过Annotation和两个私有域变量。
最后,编写Spring的XML配置文件,如清单12所示。
1 <?xml version="1.0" encoding="UTF-8"?>
2
3 <beans xmlns=http://www.springframework.org/schema/beans
4 xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance
5 xmlns:context=http://www.springframework.org/schema/context
6 xsi:schemaLocation="http://www.springframework.org/schema/beans
7 http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
8 http://www.springframework.org/schema/context
9 http://www.springframework.org/schema/context/spring-context-2.5.xsd">
10
11 <!-- 指明需要进行Annotation扫描的包 -->
12 <context:component-scan base-package="net.blogjava.max" />
13
14 <!-- 读入配置文件 -->
15 <bean id="propertyConfigurer"
16 value="${demo.config1}" />
27 <property name="config4" value="${config2}" />
28 </bean>
29
30 </beans>清单 12. src/applicationContext.xml
完成了配置之后,大家可以运行Demo类的main方法,控制台会有如清单13的输出。这就证明了通过XML或Annotation可以注入相同配置资源,而且对比两者的代码,Annotation比XML更为简便和快捷。
1 { config1 = Demo Config #1, config2 = 314159}
2 { config3 = Demo Config #1, config4 = 314159}清单 13. 示例控制台输出
结束语
本文再三强调定义Bean时Annotation对比XML的优越性,尤其是针对业务性的对象;而配置又是每个应用程序必不可少的一部分,通过扩展Spring框架,开发者可以轻松地使用Annotation的方式实现应用程序配置。同时,笔者也希望Spring社区能够意识到这方面的需求,将其整合在以后发行的Spring版本之中。在此之前,大家可以通过文章后面的下载链接获得本文Eclipse工程的压缩包文件,运行示例或者将代码应用到您的工程之中。该代码不受任何版权保护,可以随便修改或发布。