Spring为什么不推荐你使用@Autowired ?
我们总能发现当使用IDEA写代码的时候,@Autowired注解会报黄,我们把鼠标悬停在上面,可以看到这个如下图所示的警告信息:
当我们按住alt+回车键,idea就会帮我们修改成这样:
我向来都是使用@Autowired来完成依赖注入的,但是我在公司的代码中发现大多都是下边的那种写法,这让我开始有些困惑,直接一个注解就可以完成的事,为啥要写构造函数呢?在网上也看了几篇文章,同时也去阅读官方文档(全英看不懂,有道立功),接下来就一起回顾一下spring中三种依赖注入的方式。
Spring中的三种依赖注入方式
依赖属性注入
这种注入方式就是在bean的变量上使用注解进行依赖注入。本质上是通过反射的方式直接注入到field。这是我平常开发中看的最多也是最熟悉的一种方式。用法也很简单,就直接使用@Autowired来完成依赖注入
@Autowired
private UserMapper userMapper;
这种注入方式通过Java的反射机制实现,所以private的成员也可以被注入具体的对象。
Spring Team recommends “Always use constructor based dependency injection in your beans. Always use assertions for mandatory dependencies”.
翻译:Spring建议”老是在您的bean中使用构造函数创建依赖注入。老是使用断言强制依赖”。
属性注入的缺点:
依赖属性注入有几个很明显的缺点
● 不能像构造器那样注入不可变的对象
● 依赖对外部不可见,外界可以看到构造器和setter,但无法看到私有字段,自然无法了解所需依赖
● 会导致组件与IoC容器紧耦合
● 依赖过多时是不太明显,容易忽略是否违背了单一职责
Java变量的初始化顺序为:静态变量或静态语句块–>实例变量或初始化语句块–>构造方法–>@Autowired
Field注入虽然有很多缺点,但它的好处也不可忽略:那就是太方便了。使用构造器或者setter注入需要写更多业务无关的代码,十分麻烦,而字段注入大幅简化了它们。
使用@Resouce代替@Autowired
@Resouce和@Autowired他们的基本功能都是通过注解实现依赖注入,只不过@Autowired是Spring定义的,而@Resource是Java自带的注解。
● @Resource有2个属性name和type。它默认按照byName方式进行装配;如果没有匹配,按照byType进行装配。
● @Autowired只根据type进行注入,不会去匹配name。如果涉及到type无法辨别注入对象时,那需要依赖@Qualifier注解一起来修饰。
依赖构造方法注入
依赖构造方法注入就是如图所示这种,
这种注入方式很直接,通过对象构建的时候建立关系,所以这种方式对对象创建的顺序会有要求,当然Spring会为你搞定这样的先后顺序,除非你出现循环依赖,然后就会抛出异常。
依赖set方法注入
set方法注入也会用到@Autowired注解,但使用方式与Field注入有所不同,Field注入是用在成员变量上,而set方法注入的时候,是用在成员变量的Setter函数上。就是通过调用成员变量的set方法来注入想要使用的依赖对象。
可以看到@Autowired注解没有出现黄色警告。
三种注入方式对比
注入方式 | 可靠性 | 可维护性 | 灵活性 | 循环关系的检测 | 性能影响 |
Field注入 | 不可靠 | 低 | 灵活 | 不检测 | 启动快 |
构造方法注入 | 可靠 | 高 | 不灵活 | 检测 | 启动慢 |
Set方法注入 | 不可靠 | 低 | 灵活 | 不检测 | 启动快 |
依赖构造方法注入在很多方面都是优于其他两种方式的,但是为了是代码更加简洁,大多数程序员依旧会选择使用Field注入。如果不想看到@Autowired注解的黄色警告,那不妨试试@Resource。