闽公网安备 35020302035485号

@Component
public class FieldBasedInjection {
private String name;
// 堆代码 duidaima.com
@Autowired
private final User user;
public FieldBasedInjection(){
this.name = user.getName(); // NPE
}
}
总结一下,Java 在初始化一个类时,是按照 静态变量或静态语句块 ->实例变量或初始化语句块 -> 构造方法 -> @Autowired的顺序。所以在执行这个类的构造方法时,对象实际尚未被注入,它的值还是 null, 如果属性在被注入前就拿来使用就会导致npe(空指针错误)。@RestController
public class TestHandleController {
@Autowired
TestHandleService testHandleService;
public void helloTestService(){
testHandleService.hello();
}
}
如果我们用下面的方式调用呢?TestHandleController testHandle = new TestHandleController(); testHandle.helloTestService(); // 空指针显而易见,就会出现空指针异常,依赖对外部不可见,外界可以看到构造器和setter,但无法看到私有字段,自然无法了解所需依赖,这样十分不利于单元测试。
@Component
public class ConstructorBasedInjection {
private final Object object;
private final Object object2;
...
private final Object objectX;
// 堆代码 duidaima.com
@Autowired
public ConstructorBasedInjection(Object object,
Object object2,
... ,
Object objectX) {
this.object = object;
this.object2 = object2;
...
this.objectX = objectX;
}
}
和Spring框架高度耦合
这也是Spring官方强烈推荐使用基于构造器注入的方式, 像国内Dubbo、RocketMQ等很多开源框架的源码都已经转向了基于构造器的注入方式,所以开发中我们应该尊重Spring官方的推荐,尽管其他的方式可以解决,但是不推荐。

. @Autowired和@Resource都是具有强依赖性,也就是必须要有这个bean才能启动,不过@Autowired可以设置属性required=false变成非强制注入。
