使用 @Autowired
JSR 330 的 |
你可以将 @Autowired
注解应用于构造函数,如以下示例所示:
-
Java
-
Kotlin
public class MovieRecommender {
private final CustomerPreferenceDao customerPreferenceDao;
@Autowired
public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
this.customerPreferenceDao = customerPreferenceDao;
}
// ...
}
class MovieRecommender @Autowired constructor(
private val customerPreferenceDao: CustomerPreferenceDao)
从 Spring Framework 4.3 开始,如果目标 bean 只定义一个构造函数,那么在该构造函数上使用 |
你还可以将 @Autowired
注解应用于 传统 setter 方法,如以下示例所示:
-
Java
-
Kotlin
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Autowired
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
// ...
}
class SimpleMovieLister {
@set:Autowired
lateinit var movieFinder: MovieFinder
// ...
}
你还可以将注解应用于具有任意名称和多个参数的方法,如以下示例所示:
-
Java
-
Kotlin
public class MovieRecommender {
private MovieCatalog movieCatalog;
private CustomerPreferenceDao customerPreferenceDao;
@Autowired
public void prepare(MovieCatalog movieCatalog,
CustomerPreferenceDao customerPreferenceDao) {
this.movieCatalog = movieCatalog;
this.customerPreferenceDao = customerPreferenceDao;
}
// ...
}
class MovieRecommender {
private lateinit var movieCatalog: MovieCatalog
private lateinit var customerPreferenceDao: CustomerPreferenceDao
@Autowired
fun prepare(movieCatalog: MovieCatalog,
customerPreferenceDao: CustomerPreferenceDao) {
this.movieCatalog = movieCatalog
this.customerPreferenceDao = customerPreferenceDao
}
// ...
}
你还可以将 @Autowired
应用于字段,甚至可以将其与构造函数混合使用,如以下示例所示:
-
Java
-
Kotlin
public class MovieRecommender {
private final CustomerPreferenceDao customerPreferenceDao;
@Autowired
private MovieCatalog movieCatalog;
@Autowired
public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
this.customerPreferenceDao = customerPreferenceDao;
}
// ...
}
class MovieRecommender @Autowired constructor(
private val customerPreferenceDao: CustomerPreferenceDao) {
@Autowired
private lateinit var movieCatalog: MovieCatalog
// ...
}
请确保你的目标组件(例如, |
@Autowired
也考虑自引用进行注入(即,引用回当前正在注入的 bean)。
但请注意,自注入是一种回退机制。对其他组件的常规依赖始终具有优先权。从这个意义上讲,自引用不参与常规的自动装配候选选择,因此尤其永远不是主要的。相反,它们总是以最低优先级结束。
在实践中,自引用应仅作为最后的手段使用——例如,通过 bean 的事务代理调用同一实例上的其他方法。作为替代方案,在这种情况下,可以考虑将受影响的方法分解到一个单独的委托 bean 中。
另一种替代方法是使用 @Resource
,它可以通过其唯一名称获取指向当前 bean 的代理。
尝试在同一个 @Configuration
类中注入 @Bean
方法的结果也实际上是一种自引用场景。可以懒惰地在实际需要的方法签名中解析此类引用(而不是在配置类中的自动装配字段中),或者将受影响的 @Bean
方法声明为 static
,将它们与包含配置类实例及其生命周期解耦。
否则,此类 bean 仅在回退阶段考虑,而其他配置类上的匹配 bean 将被选为主要候选(如果可用)。
你还可以通过将 @Autowired
注解添加到期望该类型的数组的字段或方法中,指示 Spring 从 ApplicationContext
提供特定类型的所有 bean,如以下示例所示:
-
Java
-
Kotlin
public class MovieRecommender {
@Autowired
private MovieCatalog[] movieCatalogs;
// ...
}
class MovieRecommender {
@Autowired
private lateinit var movieCatalogs: Array<MovieCatalog>
// ...
}
对于类型化集合也是如此,如以下示例所示:
-
Java
-
Kotlin
public class MovieRecommender {
private Set<MovieCatalog> movieCatalogs;
@Autowired
public void setMovieCatalogs(Set<MovieCatalog> movieCatalogs) {
this.movieCatalogs = movieCatalogs;
}
// ...
}
class MovieRecommender {
@Autowired
lateinit var movieCatalogs: Set<MovieCatalog>
// ...
}
如果希望数组或列表中的项目按特定顺序排序,你的目标 bean 可以实现 |
即使是类型化的 Map
实例也可以自动装配,只要预期的键类型是 String
。map 值包含所有预期类型的 bean,键包含相应的 bean 名称,如以下示例所示:
-
Java
-
Kotlin
public class MovieRecommender {
private Map<String, MovieCatalog> movieCatalogs;
@Autowired
public void setMovieCatalogs(Map<String, MovieCatalog> movieCatalogs) {
this.movieCatalogs = movieCatalogs;
}
// ...
}
class MovieRecommender {
@Autowired
lateinit var movieCatalogs: Map<String, MovieCatalog>
// ...
}
默认情况下,当给定注入点没有匹配的候选 bean 可用时,自动装配会失败。在声明数组、集合或映射的情况下,至少需要一个匹配元素。
默认行为是将带注解的方法和字段视为指示必需的依赖项。你可以更改此行为,如以下示例所示,通过将其标记为非必需(即,通过将 @Autowired
中的 required
属性设置为 false
)来使框架跳过无法满足的注入点:
-
Java
-
Kotlin
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Autowired(required = false)
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
// ...
}
class SimpleMovieLister {
@Autowired(required = false)
var movieFinder: MovieFinder? = null
// ...
}
如果一个非必需方法的一个或多个依赖项(在多个参数的情况下)不可用,则该方法将完全不会被调用。在这种情况下,一个非必需字段将完全不会被填充,其默认值将保持不变。
换句话说,将 |
注入的构造函数和工厂方法参数是一种特殊情况,因为 @Autowired
中的 required
属性具有不同的含义,这是由于 Spring 的构造函数解析算法可能处理多个构造函数。构造函数和工厂方法参数默认是必需的,但在单构造函数场景中有一些特殊规则,例如多元素注入点(数组、集合、映射)在没有匹配 bean 可用时解析为空实例。这允许一种常见的实现模式,其中所有依赖项都可以在一个独特的、多参数的构造函数中声明——例如,声明为没有 @Autowired
注解的单个公共构造函数。
任何给定 bean 类中只有一个构造函数可以声明 |
或者,你可以通过 Java 8 的 java.util.Optional
来表达特定依赖项的非必需性质,如以下示例所示:
public class SimpleMovieLister {
@Autowired
public void setMovieFinder(Optional<MovieFinder> movieFinder) {
...
}
}
你还可以使用参数级别的 @Nullable
注解(任何包中的任何类型——例如,JSR-305 中的 javax.annotation.Nullable
)或直接利用 Kotlin 内置的 null 安全支持:
-
Java
-
Kotlin
public class SimpleMovieLister {
@Autowired
public void setMovieFinder(@Nullable MovieFinder movieFinder) {
...
}
class SimpleMovieLister {
@Autowired
var movieFinder: MovieFinder? = null
// ...
}
Spring Framework 6.2 尚不支持类型级别的 |
你还可以将 @Autowired
用于众所周知的可解析依赖项接口:BeanFactory
、ApplicationContext
、Environment
、ResourceLoader
、ApplicationEventPublisher
和 MessageSource
。这些接口及其扩展接口,例如 ConfigurableApplicationContext
或 ResourcePatternResolver
,会自动解析,无需特殊设置。以下示例自动装配一个 ApplicationContext
对象:
-
Java
-
Kotlin
public class MovieRecommender {
@Autowired
private ApplicationContext context;
public MovieRecommender() {
}
// ...
}
class MovieRecommender {
@Autowired
lateinit var context: ApplicationContext
// ...
}
|