你的@Autowired被警告了吗

一个警告

近期团队里来了新同学,依赖注入的时候习惯使用@Autowired,发现被idea黄色警告,跑过来问我。借着这个机会,我给大家同步一些心得。

首先看下问题的现象,使用@Autowired被idea警告,而使用@Resource则不会:

你的@Autowired被警告了吗_第1张图片

@Autowired被idea警告

你的@Autowired被警告了吗_第2张图片

@Resource

@Autowired和@Resource的差异

来源

  • @Resource是JSR 250中的内容,发布时间是2006年

  • @Autowired是Spring2.5中的内容,发布时间是2007年

@Resource是JSR的标准,Spring框架也提供了实现。既然@Autowired是在@Resource之后发布的,应该就有@Resource不能表达的含义或者不能实现的功能。

用法

注入方式

虽然我们开发中使用最多的方式是属性注入,但其实存在构造函数注意、set方法注入等方式。相比于@Resource支持的属性注入和set方法注入,@Autowired还能支持构造方法注入的形式,@Resource是不行的。

你的@Autowired被警告了吗_第3张图片

你的@Autowired被警告了吗_第4张图片

可指定属性

@Autowired支持required属性

你的@Autowired被警告了吗_第5张图片

@Resource支持7个其它属性

你的@Autowired被警告了吗_第6张图片

bean查找策略

  • @Autowired是类型优先,如果这个类型的bean有多个,再根据名称定位

  • @Resource是名称优先,如果不存在这个名称的bean,再去根据类型查找

查找过程

@Autowired

你的@Autowired被警告了吗_第7张图片

@Resource

你的@Autowired被警告了吗_第8张图片

思考

对于大多数开发同学来说,@Autowired 和 @Resource 差异是很小的,虽然 @Autowired 多支持构造器注入的形式,但是直接属性注入真的太灵活太香了。而@Autowired晚生于@Resource,既然已经有JSR标准的@Resource,还要增加1个特有Autowired,必然有Spring的考虑。

个人认为,构造器注入和支持属性不同这个理由是很弱的,这些特性完全可以在@Resource上实现,也不违反JSR的约束。比较可能的原因是,含义的不同,而最大的不同体现在bean查找策略上,@Autowired默认byType,@Resource默认byName,这个不同其实隐含了,@Resource注入的bean,更加有确定性,你都已经确定了这个bean的名称了,而类型在Java中编译过程本身是个强依赖,其实这里相当于指定了类型和名称,注入的是一个非常确定的资源。而@Autowired是类型优先,根据类型去查找,相比于@Resource,确定性更弱,我知道这里要注入bean的类型,但是我不确定这个bean的名称,也隐含体现了java多态的思想。

总结

回到开篇的idea的警告,网上有很多人都赞同的一种说法是,@Resource是JSR规范,@Autowired是Spring提供,不推荐使用绑定了Spring的@Autowired,因为@Resource在更换了框架后,依然可以使用。我不太赞同这种说法,因为idea的错误提示很明确,「Field injection is not recommended」 ,不推荐使用属性注入的方式,那换成@Resource,我理解并没有解决这个问题,虽然idea确实不警告了,可能有点掩耳盗铃的意思。比较推荐的做法是,使用构造方法注入,虽然很多时候会有点麻烦,特别是增加依赖的时候,但是正是这种麻烦,会让你不再那么随意做属性注入,更能保持类的职责单一。然后配合lombok,也可以让你省去这种麻烦,不过希望还是能通过这个警告时刻提醒自己保持类的职责单一。

你的@Autowired被警告了吗_第9张图片

你可能感兴趣的:(java,java,开发语言)