背景:自己最近在看《升入浅出springBoot2.X》,里面提到getBean方法,刚好联想到Autowired和Resouce两个注解。(如果想要这本书的pdf,可以在下面留下邮箱)
这篇文章会分为下面三个部分。1,2部分在网上很多,但是鉴于文章的完整性,这里还是写一下,之所以要写这篇文章主要是因为网上很少有分析原因的,大多都是用法和区别。我就在这里抛钻引钰,如果有不正确的地方还望各位大佬多多指出。
1.Autowired和Resouce的用法。
@Autowired
本着代码是程序员最直接的交流语言,我这里直接上代码。
@Service
public class BussionPerssion implements Perssion {
@Autowired
Animal animal;
@Override
public void service() {
animal.use();
}
}
BussionPerssion里面有animal属性,然后借助animal的use方法对外提供服务。
@Service("dog")
public class Dog implements Animal {
@Override
public void use() {
System.out.println("dog is a dog!");
}
}
Dog实现Animal接口,并由@service修饰。这样我们就可以在BussionPerssion中调用Dog的方法了。
这个时候问题来了,如果说现在我们现在想新加一个类Cat也实现Animal接口,然后我们调用Cat的方法。代码和Cat类似,区别只是use方法的实现不同,在这里我就不贴了。
可以看到代码直接报错提示不能注入animal,因为有多个Animal type的bean在spring中。为什么会出现这个错误呢,其实就是Autowired是按照by type进行注入的,现在spring要生成一个animal对象,但是在spring容器中存在两个类型的Animal对象,Cat和Dog,这个时候spring就不知道到底该生成哪个对象了。那我们怎么解决这一问题呢,spring给出了两种解决方案。@Primary和@Qualifier。
1.@Primary修饰Dog类,那么这个时候spring就会优先生成Dog对象赋值给BussionPerssion的animal。@primary我理解就是优先级最高的。但是这个还是存在一个问题,假如Cat类也被@Primary修饰怎么办。为了解决这一问题spring提出了@Qualifier。
2.@Qualifier代码如下。这两个注解代表什么意思呢?首先@Autowired指定赋值给animal的bean,类型必须是Animal;其次@Qualifier指定该bean的name必须是dog。现在我们通过type,name就可以在spring中唯一确定一个bean赋值给animal了。这个过程可以理解为依赖注入。
@Service
public class BussionPerssion implements Perssion {
@Autowired
@Qualifier(value = "dog")
Animal animal;
@Override
public void service() {
animal.use();
}
}
@Resouce
@Resouce和@Autowired的用法相似,这里只说明注入发现多个bean这种情况,代码如下。@Resource只有一个参数name,在这里显示指定需要name为dog的bean注入。这也就是为什么大家说Resouce是by name注入的。
@Service
public class BussionPerssion implements Perssion {
@Resource(name = "dog")
Animal animal;
@Override
public void service() {
animal.use();
}
}
这里大家可能会想,如果说Resource是by name的,那么我稍微修改一下Dog代码,让其不在实现Animal,那BussionPerssion 中的animal还会被正常注入吗?答案明显是否定的。
2.Autowired和Resouce的区别。
在上面的例子中我其实已经提到了两者的区别,在这里总结下。
@Autowired是按照by type注入,可以配合@Qulifier注解使用,那此时就是by type by name了。
@Resouce是按照by name注入,如果没有指定name,那么会取属性名称进行注入,如果此时没有找到对应的bean,那么会按照by type注入。如果指定了name那么只会 by name注入。
3.Autowired和Resouce的区别的原因。
这两个注解的作用都是注入,那么为什么会有这种区别呢?其实我们可以想一下注入的过程其实就是getBean的过程。我们可以看一下源头BeanFactory的getBean方法。
Object getBean(String name) throws BeansException;
<T> T getBean(Class<T> requiredType) throws BeansException;
<T> T getBean(String name, @Nullable Class<T> requiredType) throws BeansException;
Object getBean(String name, Object... args) throws BeansException;
<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
@Autowired修饰属性时,底层会调用第二个getBean方法,在配合@Qulifier时会调用第三个getBean方法。
@Resouce修饰属性时,会调用第一个getBean方法,在获取失败时,会调第三个getBean方法。