大家都知道,Spring使用最多的就是IOC(控制反转),我们通过将注册Bean,把Bean交由Spring的IOC容器管理,将对象的依赖关系由Spring控制,避免硬编码所造成的过度程序耦合。
其中注解方式的注入Bean,有三种方式:
- 使用字段Field注入(使用注解);
- 使用Setter方法注入(需要加注解@Autowired等,或者自己创建Bean,调用该Setter方法设进去);
- 构造器注入 (需要加注解@Autowired等,或自己创建Bean,放入构造器中创建);
其中Setter注入方式 是Spring 3.x推荐的,
而构造器注入方式是Spring 4.x及以上推荐的
。
不推荐是用字段(Field)注入方式,因为可能会产生NPE问题,还有在编译期无法检查出循环依赖。
而Setter注入方式,单例模式下可以解决循环依赖问题。
而最后的构造器注入,在Spring启动进行bean初始化时自动帮我们检查Null空值, 并且检查出循环依赖,会立马报错,防止在运行时出现错误。依赖关系在构造时由容器一次性设定,组件被创建之后一直处于相对“不变”的稳定状态。
如以下代码会在bean初始化时报错,并指出循环依赖异常:
AService类:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* Created by martin on 2018/6/24.
*/
@Service
public class AService {
private BService bService;
@Autowired
public AService(BService bService) {
this.bService = bService;
}
}
BService类:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* Created by martin on 2018/6/24.
*/
@Service
public class BService {
private AService aService;
@Autowired
public BService(AService aService) {
this.aService = aService;
}
}
报错信息:
***************************
APPLICATION FAILED TO START
***************************
Description:
The dependencies of some of the beans in the application context form a cycle:
┌─────┐
| AService defined in file [/Users/martin/Documents/****/****/target/classes/com/****/****/service/AService.class]
↑ ↓
| BService defined in file [/Users/martin/Documents/****/****/target/classes/com/****/****/service/BService.class]
└─────┘