博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring的@Autowired用法浅谈
阅读量:7117 次
发布时间:2019-06-28

本文共 2157 字,大约阅读时间需要 7 分钟。

hot3.png

先让我们来总结下,@Autowired的使用方式有哪些。根据文档上的说明,@Autowired注解有三种常用方式。一种是在构造器的前面使用,后续我们简称为“constructor方式”;一种是在setter方法前面使用,后续简称为“setter方式”;最后一种是直接在声明的类属性上使用,后续简称“field方式”

Spring依赖注入的@Autowired总结一些想法。最近笔者看到一则实践建言,建议Spring的依赖注入采用构造器的方式(下面会提到)。看到这条,不免心中会有疑惑,为什么?

相信看过Spring依赖注入示例代码、项目源码的人,对笔者上面提到的三种方式不会陌生,应该都有所见闻,而且应该知道@Autowired默认是依据类型来进行注入的。既然提供了三种方式,为什么那条建言推荐使用constructor方式呢?

各个方式的对比

constructor方式

@Controller
public class ItemStoreController{
    private final UserService userService;
 
    @Autowired
    public ItemStoreController (UserService userService){
        this.userService = userService;
    }
 
    //...省略
}
优势:

1.可以将依赖的属性设为final,避免了不期望的可变性。

2.在写测试用例时,这种方式的优势会更明显。写测试代码时,依赖的属性对象一般是通过mock实现的,但是脱离了Spring的依赖注入机制,如何将mock的对象进行赋值呢?通过构造器可以很好的完成这项任务。写过测试用例的人,应该对此非常赞同。但笔者对此不太苟同,假设采用了field方式,spring-test包现在提供了工具类可以实现将mock的对象赋值给测试对象的属性。

劣势:

1.     无法再次配置或再次注入,当期望再次注入bean时,则必须重新构造一个新的实例。这项跟上面的优势对比,自相矛盾了,具体还得看你的应用场景了。但笔者未想到需要再次注入的场景,在一篇博客中看到一句“Management through JMX MBeans is a compelling use case”,希望了解的朋友可以指点一二。

2.     如果当前类依赖的bean过多,那么构造器就会变得很笨拙了。从表象上看,这项说的确实在理,但从另一个角度来看,这项未必算是劣势。假如当前类依赖了过多的bean,这个类是否需要重新审视一下,是否需要重构呢?

3.     存在循环依赖的风险。这点说的应该算戳中痛点了,若采用constructor方式,切记避免循环依赖。

setter方式

@Controller
public class ItemStoreController{
    private UserService userService;
 
    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }
 
    //...省略
}

优势:

1.     对比constructor方式,很明显setter方式“重塑性”强。

2.     同样可以解决测试时绑定mock对象的问题。

3.     避免了依赖bean太多导致的构造器笨拙的现象。

劣势:

1.     假设代码的应用场景渴望不可变性的话,那么setter方式自然暴露了太多。有人可能会提出,把依赖注入的属性设为final如何?既然你的本意不变,又暴露了可变的方法,岂不是自己打脸么。

 

field方式

@Controller
public class ItemStoreController{
    @Autowired
    private UserService userService;
 
    //...省略
}

优势:

1.     咋一看,是不是“清爽”了许多?可以没有专门的构造器和setter方法,直接注解在属性上,简单明了。

2.     避免了依赖bean太多导致的构造器笨拙的现象。但往往容易忽视了过多依赖导致的类结构的合理性,所以此项是优是劣,不是绝对的。

劣势:

1.     写测试用例时无法直接绑定mock的依赖对象。但spring-test包中可以解决这个问题了。

2.     没有“重塑性”。

3.     综上所述,@Autowired的三种用法其实没有所谓的孰优孰劣,笔者也就不在此提倡哪种用法被喷了。使用者需要根据具体的应用场景,例如可变性的要求、“重塑性”的需要、测试时的方便、代码结构合理性等等因素吧,采用适合自己的方式。

4.     笔者在做上述内容的思考时,想到了另外一个“话题”,不在本篇中叙述了,不然有些跑题。可以先抛个引子,在后续博文中探讨。“假设采用field方式注入bean,又想保证不可变性的话,能否把属性设为final呢?”

 

转载于:https://my.oschina.net/u/1054538/blog/601717

你可能感兴趣的文章
ADempiere3.6.0LTS - 重新导入会计科目(基于Ubuntu Desktop 12.04 LTS)
查看>>
Project Euler Problem 48: Self powers
查看>>
python一个小程序:猜数字
查看>>
转:web.xml 配置中classpath: 与classpath*:的区别
查看>>
vue-自定义组件传
查看>>
由用户反映DroidPilot安装之后,License没有同步安装 - 解决办法
查看>>
java发展史与java的语言特性
查看>>
trunk端口配置错误导致环路
查看>>
《坟·题记》
查看>>
小女也爱c#(1)
查看>>
洛谷P4070 生成魔咒
查看>>
linux下挂载NTFS分区错误修复
查看>>
是C太傻逼?还是C++不够傻逼;
查看>>
Anaconda使用总结
查看>>
JAVA基础◆浅谈3DES加密解密
查看>>
mysql 优化
查看>>
POJ1065/HDOJ1051 Wooden Sticks
查看>>
bui前端框架+yii整理
查看>>
android之间传递list
查看>>
要注意一下xss攻击啊
查看>>