Spring注解详解
基于注释(Annotation)的配置有越来越流行的趋势,Spring 2.5 顺应这种趋势,提供了完全基于注释配置 Bean、装配 Bean 的功能,您可以使用基于注释的 Spring IoC 替换原来基于 XML 的配置。本文通过实例详细讲述了 Spring 2.5 基于注释 IoC 功能的使用。
概述
注释配置相对于 XML 配置具有很多的优势:
1.它可以充分利用 Java 的反射机制获取类结构信息,这些信息可以有效减少配置的工作。如使用 JPA 注释配置 ORM 映射时,我们就不需要指定 PO 的属性名、类型等信息,如果关系表字段和 PO 属性名、类型都一致,您甚至无需编写任何属性映射信息——因为这些信息都可以通过 Java 反射机制获取。
2.注释和 Java 代码位于一个文件中,而 XML 配置采用独立的配置文件,大多数配置信息在程序开发完成后都不会调整,如果配置信息和 Java 代码放在一起,有助于增强程序的内聚性。而采用独立的 XML 配置文件,程序员在编写一个功能时,往往需要在程序文件和配置文件中不停切换,这种思维上的不连贯会降低开发效率。
因此在很多情况下,注释配置比 XML 配置更受欢迎,注释配置有进一步流行的趋势。Spring 2.5 的一大增强就是引入了很多注释类,现在您已经可以使用注释配置完成大部分 XML 配置的功能。在这篇文章里,我们将向您讲述使用注释进行 Bean 定义和依赖注入的内容。
Spring2.5的注释
Spring 2.5 提供了 AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor、 PersistenceAnnotationBeanPostProcessor 和 RequiredAnnotationBeanPostProcessor 这四个主要的关于 Annotation 的 BeanPostProcessor。
我们可以使用 <context:annotation-config /> 来方便地、一次性的声明者四个 BeanPostProcessor。
1.Autowired... 提供对 Spring 特有的 Autowired 和 Qualifier 注释。
2.CommonAnotation... 用于支持 JSR 250 的注释
3.Persistence... 用于 JPA 的 PersistenceUnit 和PersistenceContext 注释
4.Required... 用于检查被 Required 注释标记的属性是否被设定
原来我们是怎么做的
在使用注释配置之前,先来回顾一下传统上是如何配置 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; }}package com.baobaotao;public class Car { private String brand; private double price; // 省略 get/setter @Override public String toString() { return "brand:" + brand + "," + "price:" + price; }}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=" 奥迪A8"/> <property name="price" value="200000"/> </bean></beans>
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); }}这说明 Spring 容器已经正确完成了 Bean 创建和装配的工作。package com.baobaotao;import org.springframework.beans.factory.annotation.Autowired;public class Boss { @Autowired private Car car; @Autowired private 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"> <!-- 该 BeanPostProcessor 将自动起作用,对标注 @Autowired 的 Bean 进行自动注入 --> <bean value="001"/> </bean> <bean id="car" scope="singleton"> <property name="brand" value=" 红旗 CA72"/> <property name="price" value="2000"/> </bean></beans>
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; } …}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 ; } …}<?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="奥迪 A8"/> <property name="price" value="200000"/> </bean></beans>
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; } …}… <bean id="office" value="001"/></bean><bean id="office2" value="001"/></bean>…
@Autowiredpublic void setOffice(@Qualifier("office")Office office) { this.office = office;}public class Boss { @Autowired private Car car; @Autowired @Qualifier("office") private Office office; …}public class Boss { private Car car; private Office office; @Autowired public Boss(Car car , @Qualifier("office")Office office){ this.car = car; this.office = office ; }}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">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"); } …}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 销毁方法的执行 }}<?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=" 奥迪 A8"/> <property name="price" value="200000"/> </bean></beans>
package com.baobaotao;import org.springframework.stereotype.Component;@Componentpublic class Car { …}package com.baobaotao;import org.springframework.stereotype.Component;@Componentpublic class Office { private String officeNo = "001"; …}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; …}<?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>
package com.baobaotao;import org.springframework.context.annotation.Scope;…@Scope("prototype")@Component("boss")public class Boss { …}