AutowiredAnnotationBeanPostProcessor"/>
--将officeBean注释掉-->
--
-->
由于officeBean被注释掉了,所以Spring容器中将没有类型为Office的Bean了,而Boss的office属性标注了@Autowired,当启动Spring容器时,异常就产生了。
当不能确定Spring容器中一定拥有某个类的Bean时,可以在需要自动注入该类Bean的地方可以使用@Autowired(required=false),这等于告诉Spring:
在找不到匹配Bean时也不报错。
来看一下具体的例子:
清单11.使用@Autowired(required=false)
packagecom.baobaotao;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.beans.factory.annotation.Required;
publicclassBoss{
privateCarcar;
privateOfficeoffice;
@Autowired
publicvoidsetCar(Carcar){
this.car=car;
}
@Autowired(required=false)
publicvoidsetOffice(Officeoffice){
this.office=office;
}
…
}
当然,一般情况下,使用@Autowired的地方都是需要注入Bean的,使用了自动注入而又允许不注入的情况一般仅会在开发期或测试期碰到(如为了快速启动Spring容器,仅引入一些模块的Spring配置文件),所以@Autowired(required=false)会很少用到。
和找不到一个类型匹配Bean相反的一个错误是:
如果Spring容器中拥有多个候选Bean,Spring容器在启动时也会抛出BeanCreationException异常。
来看下面的例子:
清单12.在beans.xml中配置两个Office类型的Bean
…
…
我们在Spring容器中配置了两个类型为Office类型的Bean,当对Boss的office成员变量进行自动注入时,Spring容器将无法确定到底要用哪一个Bean,因此异常发生了。
Spring允许我们通过@Qualifier注释指定注入Bean的名称,这样歧义就消除了,可以通过下面的方法解决异常:
清单13.使用@Qualifier注释指定注入Bean的名称
@Autowired
publicvoidsetOffice(@Qualifier("office")Officeoffice){
this.office=office;
}
@Qualifier("office")中的office是Bean的名称,所以@Autowired和@Qualifier结合使用时,自动注入的策略就从byType转变成byName了。
@Autowired可以对成员变量、方法以及构造函数进行注释,而@Qualifier的标注对象是成员变量、方法入参、构造函数入参。
正是由于注释对象的不同,所以Spring不将@Autowired和@Qualifier统一成一个注释类。
下面是对成员变量和构造函数入参进行注释的代码:
对成员变量进行注释:
清单14.对成员变量使用@Qualifier注释
publicclassBoss{
@Autowired
privateCarcar;
@Autowired
@Qualifier("office")
privateOfficeoffice;
…
}
对构造函数入参进行注释:
清单15.对构造函数变量使用@Qualifier注释
publicclassBoss{
privateCarcar;
privateOfficeoffice;
@Autowired
publicBoss(Carcar,@Qualifier("office")Officeoffice){
this.car=car;
this.office=office;
}
}
@Qualifier只能和@Autowired结合使用,是对@Autowired有益的补充。
一般来讲,@Qualifier对方法签名中入参进行注释会降低代码的可读性,而对成员变量注释则相对好一些。
使用JSR-250的注释
Spring不但支持自己定义的@Autowired的注释,还支持几个由JSR-250规范定义的注释,它们分别是@Resource、@PostConstruct以及@PreDestroy。
@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的例子:
清单16.使用@Resource注释的Boss.java
packagecom.baobaotao;
importjavax.annotation.Resource;
publicclassBoss{
//自动注入类型为Car的Bean
@Resource
privateCarcar;
//自动注入bean名称为office的Bean
@Resource(name="office")
privateOfficeoffice;
}
一般情况下,我们无需使用类似于@Resource(type=Car.class)的注释方式,因为Bean的类型信息可以通过Java反射从代码中获取。
要让JSR-250的注释生效,除了在Bean类中标注这些注释外,还需要在Spring容器中注册一个负责处理这些注释的BeanPostProcessor:
class="org.springframework.context.annotation.CommonAnnotationBeanPostProc