1.通过构造器注入。(spring4.3之后,推荐使用)
2.通过setter注入。(spring4.3之前,推荐使用)
3通过filed注入。
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;
}
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;
}
@Autowired
private AlarmContactService alarmContactService;
@Autowired
private AlarmService alarmService;
@Autowired
private SysUserService sysUserService;
1.基于构造器注入,会固定依赖注入的顺序,不允许我们创建的bean对象之间存在循环依赖关系,这样Spring能解决循环依赖的问题。
2.基于setter注入,只有对象是需要被注入的时候,才会注入依赖,而不是在初始化的时候就注入。
3.在成员变量上写上注解来注入,这种方式,精短,可读性高,不需要多余的代码,也方便维护。
1.使用构造器注入的缺点是,当我们构造器需要注入的对象比较多时,会显得我们的构造器,冗余,不美观,可读性差,也不易维护。
2.当我们选择setter方法来注入的时候,我们不能将对象设为final的;
3.当我们在field变量上来实现注入的时候
a.这样不符合JavaBean的规范,而且很有可能引起空指针;
b.同时也不能将对象标为final的;
c.类与DI容器高度耦合,我们不能在外部使用它;
d.类不通过反射不能被实例化(例如单元测试中),你需要用DI容器去实例化它,这更像集成测试;
而在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,这也表示以后不能再被更改了。