Spring注入使用规范
首先本文将列出Spring中常见的依赖注入形式,并说明哪些注入形式推荐使用,哪些注入形式不推荐使用。并且会列出各种注入形式之间的差异。
私有字段上使用@Autowired注入(不推荐)
是否推荐:不推荐
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
}
这种注入形式违背了 SnoarLint
中的 java:S6813
规则:Field dependency injection should be avoided
代码检查中会提示:Remove this field injection and use constructor injection instead.(移除字段的形式的注入,使用构造函数注入代替)。
Field dependency injection should be avoided的详细描述
Dependency injection frameworks such as Spring support dependency injection by using annotations such as @Inject and @Autowired. These annotations can be used to inject beans via constructor, setter, and field injection.
Generally speaking, field injection is discouraged. It allows the creation of objects in an invalid state and makes testing more difficult. The dependencies are not explicit when instantiating a class that uses field injection.
In addition, field injection is not compatible with final fields. Keeping dependencies immutable where possible makes the code easier to understand, easing development and maintenance.
Finally, because values are injected into fields after the object has been constructed, they cannot be used to initialize other non-injected fields inline.
This rule raises an issue when the @Autowired or @Inject annotations are used on a field.
依赖注入框架(如 Spring)通过使用 @Inject 和 @Autowired 等注解来支持依赖注入。这些注解可用于通过构造器、设置器和字段 注入来注入 Bean。
一般来说,我们不鼓励字段注入。它允许在无效状态下创建对象,使测试变得更加困难。在实例化使用字段注入的类时,依赖关系是不明确的。
此外,字段注入与最终字段不兼容。在可能的情况下,保持依赖关系不可变会使代码更容易理解,从而简化开发和维护工作。
最后,由于值是在对象构造完成后注入字段的,因此不能用于内联初始化其他非注入字段。
当在字段上使用 @Autowired 或 @Inject 注解时,这条规则就会引起问题。
除了违背了 SnoarLint
中的 java:S6813
规则外,这种注入方式还有一个问题,就是它破坏了破坏类的封装性。使得私有字段被强行访问。
使用构造函数注入
是否推荐:推荐
@Service
public class UserServiceImpl implements UserService {
@Autowired
private final UserMapper userMapper;
public UserServiceImpl(UserMapper userMapper) {
this.userMapper = userMapper;
}
}
定义的字段上必须加上 final
关键字来修饰。推荐使用这种方式注入,这也是当前Spring推荐使用的注入方式。
这种注入形式会带来循环依赖无法解决的问题。但是如果出现循环依赖的问题,首先要考虑自己的程序设计是否合理。
在Setter上使用@Autowired来注入
是否推荐:推荐
@Service
public class UserServiceImpl implements UserService {
private UserMapper userMapper;
@Autowired
public void setUserMapper(UserMapper userMapper) {
this.userMapper = userMapper;
}
}
这种方式不仅可以解决循环依赖问题,而且不会出现在私有字段上使用@Autowired
注入的问题。
但是会增加一定的代码量。如果注入的Bean比较多,Setter方法会使整个类看起来很乱。
使用lombok优化Setter注入
@Service
public class UserServiceImpl implements UserService {
@Setter(onMethod_={@Autowired})
private UserMapper userMapper;
}