Spring中@Autowired骚操作

Spring中@Autowired骚操作

十一月 02, 2018

昨天在Java交流群里看一位群友问了个问题,看了半天虽然知道是什么意思,但是又说不上来,很懵逼,特意Google了一下get到一个骚操作。

一般后台开发都会分层,并且基于接口进行调用,比如在Service中调用Dao或者Controller中调用Service,我们都会使用@Autowired或者@Resource进行注入,然后用注入的对象去操作,这位群友提出的问题是:

1
2
3
// 多个class实现了PService,然后都注入进来了,并且map的key被重写了
@Autowired
private Map<String, PService> map;

首先分析一下,问题拆分成两点:

  1. 使用map,为什么实现了PService接口的类都被注入进来了;
  2. 注入进来后map的key本来是什么,为什么可以重写。

第一个问题

对于Spring的注入还只是知道一些常规操作,其实有一种特殊注入,就是List,Set或者Map,对于一个多实现的接口进行注入的时候,如果采用我们常规的接口对象注入,在没有指定qualifier的情况下Spring会直接抛出错误,如果使用特殊注入,Spring会将所有实现全部注入进来(List和Set直接存放就可以,取得时候可以配合@Order进行使用,map在存放的时候key默认是实现类的首字母小写,value是实现对象,直接get(name)就可以使用)。

参考地址

第二个问题

注入的实现无非是构造注入或者set注入,那我们在注入的时候是不是可以做一点什么操作,去变相的修改map本身默认的key,或者以List或者Set进行注入,然后存放到一个map中,那么重写的key哪儿来,我们可以在接口中定义一个方法返回key,在多实现类中进行实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public interface MyInterface{
int getKey();
}

@Component
public ImplA implements MyInterface{
@Override
public int getKey(){
return 1;
}
}

@Component
public ImplB implements MyInterface{
@Override
public int getKey(){
return 2;
}
}

@Component
public MapHolder{
@Autowire
private List<MyInterface> myAutowireList;

private Map<Integer, MyInterface> myAutowireMap;

public mapHolder(){
}

@PostConstruct
public void init(){
for(MyInterface ob : myAutowireList){
myAutowireMap.put(ob.getKey(),ob);
}
}
}

参考地址

这么写感觉很炫,但仔细想想,这样做无非就类似spring的factory一样,把类放入工厂,重新包装了一遍,完全没有我们之前的实现类直接引入更让人理解,而且多实现的类注入到一个类里边,这个是不是设计上的问题?