spring依赖注入的三种方式以及优缺点

spring依赖注入的三种方式以及优缺点

一.依赖注入的三种方式

1.通过构造器注入。(spring4.3之后,推荐使用)

2.通过setter注入。(spring4.3之前,推荐使用)

3通过filed注入。

二.三种方式的代码示例:

Constructor注入

    private AlarmContactService alarmContactService;

	private final AlarmService alarmService;

	private final SysUserService sysUserService;

    @Autowired
	public AlarmContactController(AlarmContactService alarmContactService, AlarmService alarmService,
			SysUserService sysUserService) {
		this.alarmContactService = alarmContactService;
		this.alarmService = alarmService;
		this.sysUserService = sysUserService;
	}

Setter注入

private AlarmContactService alarmContactService;

	private AlarmService alarmService;

	private SysUserService sysUserService;

	@Autowired
	public void setAlarmContactService(AlarmContactService alarmContactService) {
		this.alarmContactService = alarmContactService;
	}

	@Autowired
	public void setAlarmService(AlarmService alarmService) {
		this.alarmService = alarmService;
	}

	@Autowired
	public void setSysUserService(SysUserService sysUserService) {
		this.sysUserService = sysUserService;
	}

Field注入

    @Autowired
	private AlarmContactService alarmContactService;

	@Autowired
	private AlarmService alarmService;

	@Autowired
	private SysUserService sysUserService;

三.3种方式的各优点和缺点

三种方式的优点分析

1.基于构造器注入,会固定依赖注入的顺序,不允许我们创建的bean对象之间存在循环依赖关系,这样Spring能解决循环依赖的问题。

2.基于setter注入,只有对象是需要被注入的时候,才会注入依赖,而不是在初始化的时候就注入。

3.在成员变量上写上注解来注入,这种方式,精短,可读性高,不需要多余的代码,也方便维护。

三种方式的缺点分析

1.使用构造器注入的缺点是,当我们构造器需要注入的对象比较多时,会显得我们的构造器,冗余,不美观,可读性差,也不易维护。

2.当我们选择setter方法来注入的时候,我们不能将对象设为final的;

3.当我们在field变量上来实现注入的时候

    a.这样不符合JavaBean的规范,而且很有可能引起空指针;

    b.同时也不能将对象标为final的;

  c.类与DI容器高度耦合,我们不能在外部使用它;

    d.类不通过反射不能被实例化(例如单元测试中),你需要用DI容器去实例化它,这更像集成测试;

 

来自Spring官方文档的建议:  
在Spring 3.x 中,Spring团队建议我们使用setter来注入:

而在Spring 4.x 中,Spring团队不再建议我们使用setter来注入,改为了constructor:

Spring团队通常建议使用构造器来注入,因为它允许一个应用程序组件实现为不可变对象,并确保所需的依赖项不是空。此外构造器注入组件总是返回一个完全初始化状态的client客户端(调用)。附注,大量的构造函数参数是一个糟糕的代码习惯,看起来也很坏,这意味着类可能有太多的责任,应该被重构,以更好地解决适当的关注点分离。

 

三.解释下什么是循环依赖:

1. 循环依赖是什么?

Bean A 依赖 B,Bean B 依赖 A这种情况下出现循环依赖。

Bean A → Bean B → Bean A     或者 Bean A → Bean B → BeanC → Bean A

2. 循环依赖会产生什么结果?

当Spring正在加载所有Bean时,Spring尝试以能正常创建Bean的顺序去创建Bean。

例如,有如下依赖:

Bean A → Bean B → Bean C

Spring先创建beanC,接着创建bean B(将C注入B中),最后创建bean A(将B注入A中)。

假如,有如下循环依赖:

Bean A → Bean B → Bean C → BeanD → Bean A  

 

但当存在循环依赖时,Spring将无法决定先创建哪个bean。这种情况下,Spring将产生异常BeanCurrentlyInCreationException。

 

一条Spring 4.3 的新特征:

在Spring 4.3 以后,如果我们的类中只有单个构造函数,那么Spring就会实现一个隐式的自动注入:

就是我去掉了构造器上的@Autowired注解,经测试后发现,程序能正常运行。alarmContactService,alarmService,sysUserService的依赖也被成功注入了。

    private AlarmContactService alarmContactService;

	private final AlarmService alarmService;

	private final SysUserService sysUserService;

	public AlarmContactController(AlarmContactService alarmContactService, AlarmService alarmService,
			SysUserService sysUserService) {
		this.alarmContactService = alarmContactService;
		this.alarmService = alarmService;
		this.sysUserService = sysUserService;
	}

使用构造注入允许加入final,这也表示以后不能再被更改了。

 

 

  • 6
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值