使用IoC时,有时会碰到需要注入接口类型。看下面这个例子,判断是否能注入成功:
实现类
@Component
public class ITestImpl implements ITestInterface{
public ITestImpl(){
}
@Override
public void printfSomeThing() {
System.out.println("这是printfSomeThing();方法");
}
}
@Component
public class TestClass {
// @Qualifier(name = "ITestImpl")
@Autowired
private ITestInterface testInterface;
public ITestInterface getTestInterface() {
return testInterface;
}
public void setTestInterface(ITestInterface testInterface) {
this.testInterface = testInterface;
}
}
虽然beanPool中有该接口实现类,但是没有接口类,所以这个TestClass中的testInterface会注入失败。
注入实际上是接口的实现类
直接注入接口是没有什么意义的,应该注入的是该接口的实现类,比如上述例子,testInterface应该注入一个ITestImpl对象。
…那么怎么实现这个操作?
说明
使用到了@Qualifier注解。并且给@Qualifier(name = “ITestImpl”)添加name属性。
接口的实现类ITestImpl只能通过@Bean方法实现注入。而且Bean注解也需要完成name属性。
Bean的name是注入时,name作为键,bean作为值的。Qualifier注解的name是让知道需要从beanPool中取出的是哪一个bean。
简单的来说就是一个放入时name当记号,一个取出时根据记号和自己想要的匹配来取。俩个name必须要匹配。
另外,之前beanPool只能是一个类名为键,bean为值的map。现在的beanPool要根据输入来判断键是name还是类名。所以把beanPool作为一个新的类。
public class BeanPool {
private static final Map<String, BeanDefinition> classBeanPool
= new HashMap<>();
private static final Map<String, BeanDefinition> aliasBeanPool
= new HashMap<>();
static void put(String key, BeanDefinition bean) {
Class<?> beanClass = bean.getKlass();
String beanClassName = beanClass.getName();
//逻辑是:如果bean中的类名和key相同,则key提供的是类名,否则就是name属性的值
if (beanClassName.equals(key)) {
classBeanPool.put(key, bean);
} else {
aliasBeanPool.put(key, bean);
}
}
static BeanDefinition get(String key) {
BeanDefinition bean = classBeanPool.get(key);
if (bean == null) {
bean = aliasBeanPool.get(key);
}
return bean;
}
}
具体操作
- 先通过@Bean注解注入实现类。注入时,如果该bean有name属性,则放入的键应为name的值,否则就是类名。
//处理这个方法时,把这个bean加入到BeanPool中的aliasBeanPool
@Bean(name="ITestImpl"
public ITestImpl get(){ //对于TestClass对象注入时,根据别名从aliasBeanPool中获取
return new ITestImpl();
}
//放入时的操作
if(bean == null || bean.name() == ""){
BeanPool.put(returnType.getName(), beanDefinition);
}else{
String alias = bean.name();
BeanPool.put(alias, beanDefinition);
}
- 相关成员自动注入时的操作
if(field.isAnnotationPresent(Qualifier.class)){
Qualifier qua = field.getAnnotation(Qualifier.class);
value = getBean(qua.name());
}else{
value = getBean(fieldClass);
}