使用Spring 2.5注解驱动的IOC功能
【摘要】
基于注释(Annotation)的配置有越来越流行的趋势,Spring 2.5 顺应这种趋势,提供了完全基于注释配置 Bean、装配 Bean 的功能,您可以使用基于注释的 Spring IoC 替换原来基于 XML 的配置。本文通过实例详细讲述了 Spring 2.5 基于注释 IoC 功能的使用。
【 概述】
概述
注释配置相对于 XML 配置具有很多的优势:
它可以充分利用 Java 的反射机制获取类结构信息,这些信息可以有效减少配置的工作。如使用 JPA 注释配置 ORM 映射时,我们就不需要指定 PO 的属性名、类型等信息,如果关系表字段和 PO 属性名、类型都一致,您甚至无需编写任务属性映射信息——因为这些信息都可以通过 Java 反射机制获取。
注释和 Java 代码位于一个文件中,而 XML 配置采用独立的配置文件,大多数配置信息在程序开发完成后都不会调整,如果配置信息和 Java 代码放在一起,有助于增强程序的内聚性。而采用独立的 XML 配置文件,程序员在编写一个功能时,往往需要在程序文件和配置文件中不停切换,这种思维上的不连贯会降低开发效率。
因此在很多情况下,注释配置比 XML 配置更受欢迎,注释配置有进一步流行的趋势。Spring 2.5 的一大增强就是引入了很多注释类,现在您已经可以使用注释配置完成大部分 XML 配置的功能。在这篇文章里,我们将向您讲述使用注释进行 Bean 定义和依赖注入的内容。
原来我们是怎么做的
在使用注释配置之前,先来回顾一下传统上是如何配置 Bean 并完成 Bean 之间依赖关系的建立。下面是 3 个类,它们分别是 Office、Car 和 Boss,这 3 个类需要在 Spring 容器中配置为 Bean:
Office 仅有一个属性:
清单 1. Office.java package com.baobaotao;public class Office { private String officeNo =”001”; //省略 get/setter @Override public String toString() { return "officeNo:" + officeNo; }}
清单 2. Car.java package com.baobaotao;public class Car { private String brand; private double price; // 省略 get/setter @Override public String toString() { return "brand:" + brand + "," + "price:" + price; }}
清单 3. Boss.java package com.baobaotao;public class Boss { private Car car; private Office office; // 省略 get/setter @Override public String toString() { return "car:" + car + "\n" + "office:" + office; }}
<?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" ref="car"/> <property name="office" ref="office" /> </bean> <bean id="office" value="002"/> </bean> <bean id="car" scope="singleton"> <property name="brand" value=" 红旗 CA72"/> <property name="price" value="2000"/> </bean></beans>
清单 5. 测试类:AnnoIoCTest.java import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class AnnoIoCTest { public static void main(String[] args) { String[] locations = {"beans.xml"}; ApplicationContext ctx = new ClassPathXmlApplicationContext(locations); Boss boss = (Boss) ctx.getBean("boss"); System.out.println(boss); }}
清单 6. 使用 @Autowired 注释的 Boss.java package com.baobaotao;import org.springframework.beans.factory.annotation.Autowired;public class Boss { @Autowired private Car car; @Autowired private Office office; …}
清单 7. 让 @Autowired 注释工作起来 <?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"> <!-- 该 BeanPostProcessor 将自动起作用,对标注 @Autowired 的 Bean 进行自动注入 --> <bean value="001"/> </bean> <bean id="car" scope="singleton"> <property name="brand" value=" 红旗 CA72"/> <property name="price" value="2000"/> </bean></beans>
清单 8. 将 @Autowired 注释标注在 Setter 方法上 package com.baobaotao;public class Boss { private Car car; private Office office; @Autowired public void setCar(Car car) { this.car = car; } @Autowired public void setOffice(Office office) { this.office = office; } …}
清单 9. 将 @Autowired 注释标注在构造函数上 package com.baobaotao;public class Boss { private Car car; private Office office; @Autowired public Boss(Car car ,Office office){ this.car = car; this.office = office ; } …}
清单 10. 候选 Bean 数目为 0 时 <?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 value="001"/> </bean>--> <bean id="car" scope="singleton"> <property name="brand" value=" 红旗 CA72"/> <property name="price" value="2000"/> </bean></beans>
清单 11. 使用 @Autowired(required = false) package com.baobaotao;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Required;public class Boss { private Car car; private Office office; @Autowired public void setCar(Car car) { this.car = car; } @Autowired(required = false) public void setOffice(Office office) { this.office = office; } …}
清单 12. 在 beans.xml 中配置两个 Office 类型的 Bean … <bean id="office" value="001"/></bean><bean id="office2" value="001"/></bean>…
@Autowiredpublic void setOffice(@Qualifier("office")Office office) { this.office = office;}
清单 14. 对成员变量使用 @Qualifier 注释 public class Boss { @Autowired private Car car; @Autowired @Qualifier("office") private Office office; …}
清单 15. 对构造函数变量使用 @Qualifier 注释 public class Boss { private Car car; private Office office; @Autowired public Boss(Car car , @Qualifier("office")Office office){ this.car = car; this.office = office ;}}
清单 16. 使用 @Resource 注释的 Boss.java package com.baobaotao;import javax.annotation.Resource;public class Boss { // 自动注入类型为 Car 的 Bean @Resource private Car car; // 自动注入 bean 名称为 office 的 Bean @Resource(name = "office") private Office office;}
<bean name="code">清单 17. 使用 @PostConstruct 和 @PreDestroy 注释的 Boss.java package com.baobaotao;import javax.annotation.Resource;import javax.annotation.PostConstruct;import javax.annotation.PreDestroy;public class Boss { @Resource private Car car; @Resource(name = "office") private Office office; @PostConstruct public void postConstruct1(){ System.out.println("postConstruct1"); } @PreDestroy public void preDestroy1(){ System.out.println("preDestroy1"); } …}
清单 18. 测试类代码 package com.baobaotao;import org.springframework.context.support.ClassPathXmlApplicationContext;public class AnnoIoCTest { public static void main(String[] args) { String[] locations = {"beans.xml"}; ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(locations); Boss boss = (Boss) ctx.getBean("boss"); System.out.println(boss); ctx.destroy();// 关闭 Spring 容器,以触发 Bean 销毁方法的执行 }}
清单 19. 调整 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" value="001"/> </bean> <bean id="car" scope="singleton"> <property name="brand" value=" 红旗 CA72"/> <property name="price" value="2000"/> </bean></beans>
清单 20. 使用 @Component 注释的 Car.java package com.baobaotao;import org.springframework.stereotype.Component;@Componentpublic class Car { …}
清单 21. 使用 @Component 注释的 Office.java package com.baobaotao;import org.springframework.stereotype.Component;@Componentpublic class Office { private String officeNo = "001"; …}
清单 22. 使用 @Component 注释的 Boss.java package com.baobaotao;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Required;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.stereotype.Component;@Component("boss")public class Boss { @Autowired private Car car; @Autowired private Office office; …}
清单 23. 简化版的 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>
<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>
package com.baobaotao;import org.springframework.context.annotation.Scope;…@Scope("prototype")@Component("boss")public class Boss { …}