原来咱们是怎么作的java
在使用注释配置以前,先来回顾一下传统上是如何配置 Bean 并完成 Bean 之间依赖关系的创建。下面是 3 个类,它们分别是 Office、Car 和 Boss,这 3 个类须要在 Spring 容器中配置为 Bean:spring
Office 仅有一个属性:ide
package com.baobaotao; public class Office { private String officeNo =”001”; //省略 get/setter @Override public String toString() { return "officeNo:" + officeNo; } }
Car 拥有两个属性:函数
package com.baobaotao; public class Car { private String brand; private double price; // 省略 get/setter @Override public String toString() { return "brand:" + brand + "," + "price:" + price; } }
Boss 拥有 Office 和 Car 类型的两个属性:post
package com.baobaotao; public class Boss { private Car car; private Office office; // 省略 get/setter @Override public String toString() { return "car:" + car + "\n" + "office:" + office; } }
咱们在 Spring 容器中将 Office 和 Car 声明为 Bean,并注入到 Boss Bean 中:下面是使用传统 XML 完成这个工做的配置文件 beans.xml:this
<?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=" 红旗 CA72"/> <property name="price" value="2000"/> </bean> </beans>
使用 @Autowired 注释spa
Spring 2.5 引入了 @Autowired
注释,它能够对类成员变量、方法及构造函数进行标注,完成自动装配的工做。来看一下使用@Autowired
进行成员变量自动注入的代码:code
package com.baobaotao; import org.springframework.beans.factory.annotation.Autowired; public class Boss { @Autowired private Car car; @Autowired private Office office; … }
Spring 经过一个 BeanPostProcessor
对 @Autowired
进行解析,因此要让@Autowired
起做用必须事先在 Spring 容器中声明AutowiredAnnotationBeanPostProcessor
Bean。xml
让 @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 class="org.springframework.beans.factory.annotation. AutowiredAnnotationBeanPostProcessor"/> <!-- 移除 boss Bean 的属性注入配置的信息 --> <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>
这样,当 Spring 容器启动时,AutowiredAnnotationBeanPostProcessor
将扫描 Spring 容器中全部 Bean,当发现 Bean 中拥有@Autowired
注释时就找到和其匹配(默认按类型匹配)的 Bean,并注入到对应的地方中去。
按照上面的配置,Spring 将直接采用 Java 反射机制对 Boss 中的 car
和 office
这两个私有成员变量进行自动注入。因此对成员变量使用@Autowired
后,您大可将它们的 setter 方法(setCar()
和setOffice()
)从 Boss 中删除。
将 @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; } … }
这时,@Autowired
将查找被标注的方法的入参类型的 Bean,并调用方法自动注入这些 Bean。而下面的使用方法则对构造函数进行标注。
将 @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 ; } … }
因为 Boss()
构造函数有两个入参,分别是 car
和 office
,@Autowired
将分别寻找和它们类型匹配的 Bean,将它们做为Boss(Car car ,Office office)
的入参来建立Boss
Bean。
@Resource
@Resource
的做用至关于 @Autowired
,只不过 @Autowired
按 byType 自动注入,@Resource
默认按 byName 自动注入罢了。@Resource
有两个属性是比较重要的,分别是 name 和 type,Spring 将@Resource
注释的 name 属性解析为 Bean 的名字,而 type 属性则解析为 Bean 的类型。因此若是使用 name 属性,则使用 byName 的自动注入策略,而使用 type 属性时则使用 byType 自动注入策略。若是既不指定 name 也不指定 type 属性,这时将经过反射机制使用 byName 自动注入策略。
Resource 注释类位于 Spring 发布包的 lib/j2ee/common-annotations.jar 类包中,所以在使用以前必须将其加入到项目的类库中。来看一个使用@Resource
的例子:
通常状况下,咱们无需使用相似于 @Resource(type=Car.class)
的注释方式,由于 Bean 的类型信息能够经过 Java 反射从代码中获取。
要让 JSR-250 的注释生效,除了在 Bean 类中标注这些注释外,还须要在 Spring 容器中注册一个负责处理这些注释的 BeanPostProcessor
:
<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"/>
@PostConstruct 和 @PreDestroy
Spring 容器中的 Bean 是有生命周期的,Spring 容许在 Bean 在初始化完成后以及 Bean 销毁前执行特定的操做,您既能够经过实现 InitializingBean/DisposableBean 接口来定制初始化以后 / 销毁以前的操做方法,也能够经过 <bean> 元素的 init-method/destroy-method 属性指定初始化以后 / 销毁以前调用的操做方法。
JSR-250 为初始化以后/销毁以前方法的指定定义了两个注释类,分别是 @PostConstruct 和 @PreDestroy,这两个注释只能应用于方法上。标注了 @PostConstruct 注释的方法将在类实例化后调用,而标注了 @PreDestroy 的方法将在类销毁以前调用。
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"); } … }
您只须要在方法前标注 @PostConstruct
或 @PreDestroy
,这些方法就会在 Bean 初始化后或销毁以前被 Spring 容器执行了。
咱们知道,无论是经过实现 InitializingBean
/DisposableBean
接口,仍是经过 <bean> 元素的init-method/destroy-method
属性进行配置,都只能为 Bean 指定一个初始化 / 销毁的方法。可是使用@PostConstruct
和 @PreDestroy
注释却能够指定多个初始化 / 销毁方法,那些被标注 @PostConstruct
或 @PreDestroy
注释的方法都会在初始化 / 销毁时被执行。