概要
关于 @Autowired, 实际上有一些内容可以聊一下。
首先是比较重要的一点, @Autowired一般来讲是用于单个bean的注入 。 不过他其实可以用于Array (数组),Collections(集合),甚至是 Map (散列表)的注入。
@Autowired
List<IService> serviceBeans;
@Autowired
Set<IService> serviceBeans;
@Autowired
Map<String,IService> serviceBeanMap;
第二点则是涉及相关的一个bug的查找,注入的bean是空的某种情形。
注入方式在设计中的用处
其中Map的key只能是String类型,用于放置对应bean的名字。
这些集合、数组或者map用法其实在做设计的时候很有用处。
比如我有一个服务,用于对订单的某个类型,进行不同的处理,这时,具体实现代码可以是:
//某个实现类
@Service
public class TypeAService implements IService {
@Override
@Transactional(rollbackFor = Exception.class)
public void execute(Order order) {
//do something
}
@Override
public boolean support(SomeTypeEnum type) {
return SomeTypeEnum .typeA.equals(type);
}
}
//另一个实现类
@Service
public class TypeBService implements IService {
@Override
@Transactional(rollbackFor = Exception.class)
public void execute(Order order) {
//do something
}
@Override
public boolean support(SomeTypeEnum type) {
return SomeTypeEnum .typeB.equals(type);
}
}
我们的主体代码则可以保持不变,在新增加类型时,进行增加对应的处理类即可。对了,依旧是之前的理念,对代码尽可能少的改动以实现功能的扩展。
主体代码:
@Autowired
private List<IService> services;
public void doAction(Order order){
for (IService service: services) {
if (service.support(order.getType())) {
recordActionService.execute(order);
}
}
}
注入bean为空的某种情形
在用到cola框架(一种领域模型的依赖框架)的时候,对多模块的处理,会出现这样一种场景,在A模块中定义了接口,但是未实现,之后再在B模块中进行实现,并注册为bean。(有点类似JNDI)
这个时候spring 实际上是会有2个bean在容器中,假设接口为IService,实现为ServiceA,如果用
@Autowired
IService service;
或者ApplicationContextAware组件的applicationContext获取service=applicationContext.getBean(IService .class),
之后调用IService 任何方法都会报错,原因就是注入了IService的空接口,而不是ServiceA这个具体实现类。解决的办法就是在实现ServiceA中加入@Primary的注解。
结尾
最后,spring不太推荐属性注入,所以在属性注入中会报warning,强迫症可以替换为set方法注入,或者构造器注入。
具体原因网上有很多,这里也就不再多赘述了。