Field injection is not recommended
意思就是不推荐使用字段注入的方式,不是不推荐@Autowired
注解,以前为了简便就直接使用
@Resource
代替,程序员都在不断追求完美。。。 接下来我们实实在在的分析一下为啥不推荐,以及到底推荐那种方式注入。
不推荐使用@Autowired进行字段注入的原因有以下几点:
紧耦合性(Tight Coupling):字段注入将依赖关系直接注入到类的字段上,导致类与依赖之间产生紧密的耦合。这使得代码难以修改和扩展,并且增加了对具体实现的依赖性。
隐藏依赖关系(Hidden Dependencies):字段注入隐藏了类的依赖关系,使代码不够透明和可读。读取代码时无法立即知道类所依赖的其他组件或服务。
单元测试困难(Difficult Unit Testing):由于字段注入需要依赖容器来自动注入依赖项,导致在编写单元测试时必须依赖完整的容器环境。这增加了测试的复杂性,并且可能会导致测试变慢或不稳定。
难以发现依赖问题(Dependency Issues):字段注入使得依赖可以在运行时更改,这增加了代码维护的复杂性。同时,如果依赖项没有正确配置或不存在,就会在运行时出现错误,而不是在编译时就能发现。
相比之下,构造器注入(Constructor Injection)或Setter方法注入(Setter Injection)提供了更好的可测试性、可维护性和代码清晰度。它们明确列出了类所需的依赖项,并使得依赖关系更加透明和易于理解。这些方法也更容易进行单元测试,且不需要依赖完整的容器环境。
通过构造函数将依赖项传递给目标类。这种方式明确声明了类所需的依赖项,并且使得类的实例在创建时就具备了必要的依赖关系。示例代码如下:
@Component
public class SLFBClient {
private final DataSourceFactory dataSourceFactory;
/**
* @Autowired 从spring4.3开始可以省略
*/
// @Autowired
public SLFBClient(DataSourceFactory dataSourceFactory) {
this.dataSourceFactory = dataSourceFactory;
}
}
通过Setter方法设置依赖项。这种方式允许使用默认构造函数创建类的实例,然后通过Setter方法来动态设置依赖项。示例代码如下:
@Component
public class SLFBClient {
private DataSourceFactory dataSourceFactory;
/**
* @Autowired 从spring4.3开始可以省略
*/
// @Autowired
public void setDataSourceFactory(DataSourceFactory dataSourceFactory) {
this.dataSourceFactory = dataSourceFactory;
}
}
通过直接将依赖项注入到类的字段上。这种方式最简洁,但也最不推荐使用(在之前的回答中已经详细解释了原因)。示例代码如下:
@Component
public class SLFBClient {
// @Autowired
// @Resource
@Inject
private DataSourceFactory dataSourceFactory;
}
@Autowired、@Resource和@Inject
是用于依赖注入的常见注解,它们在使用方式和一些细节上有一些区别。
@Autowired:
Spring
框架。byType
)进行依赖注入,会尝试将匹配的bean
自动注入到目标字段、构造函数或方法参数中。@Qualifier
一起使用,通过指定bean
的名称或限定符来进一步指定要注入的bean。@Autowired
是非强制性的,可以在某些情况下将依赖项标记为可选。@Resource:
Java EE
的标准注解,也可以被Spring
框架支持。byName
)进行依赖注入,通过指定bean
的名称来解析并注入匹配的bean
。name
属性指定要注入的bean
的名称。@Resource
是强制性的,要求找到匹配的bean
进行注入,否则会抛出异常。@Inject:
Java CDI(Contexts and Dependency Injection)
规范的一部分,可以由Java EE
和一些其他框架(如Spring
)支持。byType
)进行依赖注入,使用与@Autowired
类似的机制。required
属性,即所有注入都被视为必需的。@Qualifier
一起使用,通过指定bean
的名称或限定符来进一步指定要注入的bean
。总结:
@Autowired
是Spring
特有的注解,默认按类型进行依赖注入。@Resource
是Java EE
的标准注解,可被Spring
支持,默认按名称进行依赖注入。@Inject
是Java CDI
规范的注解,也可被Spring
等框架支持,默认按类型进行依赖注入。@Qualifier
一起使用来指定具体要注入的bean
。@Autowired
和@Inject
在功能上相似,而@Resource
功能稍有不同,但它们通常可以互相替代使用。需要注意的是,具体在Spring
中使用哪个注解,可以根据项目的需求、框架的支持以及个人偏好来决定。
使用构造器注入的好处:
推荐使用Lombok
中的@RequiredArgsConstructor
注解
@Component
@RequiredArgsConstructor
public class SLFBClient {
private final DataSourceFactory dataSourceFactory;
}
接下来我们探讨一下Lombok
的@NoArgsConstructor, @RequiredArgsConstructor, @AllArgsContructor
三个注解
@NoArgsConstructor:
import lombok.NoArgsConstructor;
@NoArgsConstructor
public class MyClass {
// Fields and methods
}
2. @RequiredArgsConstructor:
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
public class MyClass {
private final String name;
@NonNull
private final Integer age;
// Other fields and methods
}
@AllArgsConstructor:
import lombok.AllArgsConstructor;
@AllArgsConstructor
public class MyClass {
private String name;
private int age;
// Other fields and methods
}
Field Dependency Injection Considered Harmful
Field injection is not recommended(Spring团队不推荐使用Field注入)
【Spring】浅谈spring为什么推荐使用构造器注入