Using @Autowired

可以在本节中包含的示例中使用 JSR 330 的 @Inject 注解替代 Spring 的 @Autowired 注解。参阅 here 了解更多详情。

JSR 330’s @Inject annotation can be used in place of Spring’s @Autowired annotation in the examples included in this section. See here for more details.

可以将`@Autowired`注释应用于构造函数,如下例所示:

You can apply the @Autowired annotation to constructors, as the following example shows:

  • 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 本身仅定义了一个构造函数,就不再需要在该构造函数上使用 "@32" 注解。但是,如果有多个构造函数可用,并且没有主/默认构造函数,那么为了指示容器使用哪个构造函数,必须至少有一个构造函数用 "@33" 注解。请参阅 "@34" 上的讨论内容,了解详细信息。

As of Spring Framework 4.3, an @Autowired annotation on such a constructor is no longer necessary if the target bean defines only one constructor to begin with. However, if several constructors are available and there is no primary/default constructor, at least one of the constructors must be annotated with @Autowired in order to instruct the container which one to use. See the discussion on constructor resolution for details.

还可以将`@Autowired`注释应用于_传统_setter 方法,如下例所示:

You can also apply the @Autowired annotation to traditional setter methods, as the following example shows:

  • 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

	// ...

}

还可以将注释应用于名称任意且具有多个参数的方法,如下例所示:

You can also apply the annotation to methods with arbitrary names and multiple arguments, as the following example shows:

  • 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`应用于字段,甚至可以将它与构造函数混合使用,如下例所示:

You can apply @Autowired to fields as well and even mix it with constructors, as the following example shows:

  • 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

	// ...
}

确保目标组件(例如 MovieCatalogCustomerPreferenceDao)是由用于 @Autowired 注解注入点的类型一致声明的。否则,注入可能会在运行时失败,出现“未找到类型匹配项”错误。

Make sure that your target components (for example, MovieCatalog or CustomerPreferenceDao) are consistently declared by the type that you use for your @Autowired-annotated injection points. Otherwise, injection may fail due to a "no type match found" error at runtime.

对于通过类路径扫描找到的 XML 定义的 Bean 或组件类,容器在前面通常已知具体类型。然而,对于 @Bean 工厂方法,你需要确保已充分明确声明的返回类型。对于实现多个接口的组件或可能被其实现类型引用的组件,考虑在你的工厂方法中声明最具体返回类型(至少像引用 Bean 的注入点所要求的那样具体)。

For XML-defined beans or component classes found via classpath scanning, the container usually knows the concrete type up front. However, for @Bean factory methods, you need to make sure that the declared return type is sufficiently expressive. For components that implement several interfaces or for components potentially referred to by their implementation type, consider declaring the most specific return type on your factory method (at least as specific as required by the injection points referring to your bean).

自 4.3 起,@Autowired 还会考虑注入的自引用(即,引用当前正在注入的 Bean)。请注意,自注入属于备用方案。实际上,你应仅在最后选择时使用自引用(例如,通过 Bean 的事务代理调用同一实例上的其他方法)。在此类场景中,考虑将受影响的方法通过单一委托 Bean 分解出来。

As of 4.3, @Autowired also considers self references for injection (that is, references back to the bean that is currently injected). Note that self injection is a fallback. In practice, you should use self references as a last resort only (for example, for calling other methods on the same instance through the bean’s transactional proxy). Consider factoring out the affected methods to a separate delegate bean in such a scenario.

你还可以指示 Spring 从 ApplicationContext 提供特定类型的全部 Bean,方法是将 @Autowired 注解添加到期待该类型数组的字段或方法,如下例所示:

You can also instruct Spring to provide all beans of a particular type from the ApplicationContext by adding the @Autowired annotation to a field or method that expects an array of that type, as the following example shows:

  • Java

  • Kotlin

public class MovieRecommender {

	@Autowired
	private MovieCatalog[] movieCatalogs;

	// ...
}
class MovieRecommender {

	@Autowired
	private lateinit var movieCatalogs: Array<MovieCatalog>

	// ...
}

对于类型化的集合,遵循同样原则,如下例所示:

The same applies for typed collections, as the following example shows:

  • 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 可以实现 org.springframework.core.Ordered 接口或使用 @Order 或标准 @Priority 注解。否则,它们的顺序遵循容器中相应目标 Bean 定义的注册顺序。

Your target beans can implement the org.springframework.core.Ordered interface or use the @Order or standard @Priority annotation if you want items in the array or list to be sorted in a specific order. Otherwise, their order follows the registration order of the corresponding target bean definitions in the container.

你可以在目标类级别和 @Bean 方法上声明 @Order 注解,可能用于单个 Bean 定义(在使用相同 Bean 类时有多个定义的情况下)。@Order 值可能影响注入点处的优先级,但要注意它们不影响单例启动顺序,这是一个因依赖关系和 @DependsOn 声明所确定的正交考虑因素。

You can declare the @Order annotation at the target class level and on @Bean methods, potentially for individual bean definitions (in case of multiple definitions that use the same bean class). @Order values may influence priorities at injection points, but be aware that they do not influence singleton startup order, which is an orthogonal concern determined by dependency relationships and @DependsOn declarations.

请注意,配置类上的 @Order 注解仅影响启动时配置类整体中的求值顺序。此类配置级别顺序值根本不会影响所包含的 @Bean 方法。对于 Bean 级排序,每个 @Bean 方法都需要有自己的 @Order 注解,该注解将在特定 Bean 类型的一组多个命中项内应用(由工厂方法返回)。

Note that @Order annotations on configuration classes just influence the evaluation order within the overall set of configuration classes on startup. Such configuration-level order values do not affect the contained @Bean methods at all. For bean-level ordering, each @Bean method needs to have its own @Order annotation which applies within a set of multiple matches for the specific bean type (as returned by the factory method).

请注意,标准 jakarta.annotation.Priority 注解在 @Bean 级别不可用,因为它不能被声明在方法上。可以通过每个类型中的单个 Bean 上的 @Order 值与 @Primary 相结合来模拟其语义。

Note that the standard jakarta.annotation.Priority annotation is not available at the @Bean level, since it cannot be declared on methods. Its semantics can be modeled through @Order values in combination with @Primary on a single bean for each type.

只要期望的键类型为 String,那么即使是类型化的 Map 实例也可以自动注入。地图值包含所有期望类型的 Bean,而键包含对应的 Bean 名称,如下例所示:

Even typed Map instances can be autowired as long as the expected key type is String. The map values contain all beans of the expected type, and the keys contain the corresponding bean names, as the following example shows:

  • 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 可用时,自动注入会失败。如果声明了数组、集合或地图,则至少应有一个匹配元素。

By default, autowiring fails when no matching candidate beans are available for a given injection point. In the case of a declared array, collection, or map, at least one matching element is expected.

默认行为是将带注释的方法和字段视为指示必需的依赖。你可以更改此行为,如下例所示,允许框架通过将其标记为非必需(即,将 @Autowired 中的 required 属性设置为 false)来跳过一个无法满足的注入点:

The default behavior is to treat annotated methods and fields as indicating required dependencies. You can change this behavior as demonstrated in the following example, enabling the framework to skip a non-satisfiable injection point through marking it as non-required (i.e., by setting the required attribute in @Autowired to 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

	// ...
}

如果其依赖(或多个参数的情况中的其一个依赖)不可用,那么一个非必需方法根本不会被调用。在此类情况下,一个非必需字段根本不会被填充,从而让其默认值保留在原位。

A non-required method will not be called at all if its dependency (or one of its dependencies, in case of multiple arguments) is not available. A non-required field will not get populated at all in such cases, leaving its default value in place.

换句话说,将 required 属性设置为 false 表明相应的属性对于自动注入而言是 可选的,并且如果不能自动注入,该属性将被忽略。这允许属性被分配可通过依赖注入选择性覆盖的默认值。

In other words, setting the required attribute to false indicates that the corresponding property is optional for autowiring purposes, and the property will be ignored if it cannot be autowired. This allows properties to be assigned default values that can be optionally overridden via dependency injection.

注入的构造函数和工厂方法参数是一种特殊情况,因为 @Autowired 中的 required 属性具有稍有不同的含义,这是由于 Spring 的可能处理多个构造函数的构造函数解决算法。在单构造函数场景中,构造函数和工厂方法参数实际上默认必需,但有几个特殊规则,例如如果没有可匹配 Bean,那么多元素注入点(数组、集合、地图)解析为空实例。这允许通用实现模式,在该模式中,所有依赖都可以声明在唯一的带多个参数的构造函数中——例如,声明为未带 @Autowired 注解的单个公共构造函数。

Injected constructor and factory method arguments are a special case since the required attribute in @Autowired has a somewhat different meaning due to Spring’s constructor resolution algorithm that may potentially deal with multiple constructors. Constructor and factory method arguments are effectively required by default but with a few special rules in a single-constructor scenario, such as multi-element injection points (arrays, collections, maps) resolving to empty instances if no matching beans are available. This allows for a common implementation pattern where all dependencies can be declared in a unique multi-argument constructor — for example, declared as a single public constructor without an @Autowired annotation.

只能在一个给定 Bean 类的构造函数中使用 @Autowiredrequired 属性设置为 true,从而指示当用作 Spring Bean 时要自动注入的 the 构造函数。因此,如果将 required 属性保留为其默认值 true,那么只能一个构造函数可以带 @Autowired 注解。如果多个构造函数声明该注解,那么它们都必须声明 required=false,才能被视为自动注入的候选项(类似于 XML 中的 autowire=constructor)。将选择可以在 Spring 容器中与匹配 Bean 匹配满足最多依赖的构造函数。如果不能满足任何候选项,则将使用主要/默认构造函数(如存在)。类似地,如果一个类声明了多个构造函数,但没有一个构造函数带 @Autowired 注解,则将使用主要/默认构造函数(如存在)。如果一个类从一开始就只声明了一个构造函数,那么即使没有添加注解,也会一直使用该构造函数。请注意,带注解的构造函数不必是公共的。

Only one constructor of any given bean class may declare @Autowired with the required attribute set to true, indicating the constructor to autowire when used as a Spring bean. As a consequence, if the required attribute is left at its default value true, only a single constructor may be annotated with @Autowired. If multiple constructors declare the annotation, they will all have to declare required=false in order to be considered as candidates for autowiring (analogous to autowire=constructor in XML). The constructor with the greatest number of dependencies that can be satisfied by matching beans in the Spring container will be chosen. If none of the candidates can be satisfied, then a primary/default constructor (if present) will be used. Similarly, if a class declares multiple constructors but none of them is annotated with @Autowired, then a primary/default constructor (if present) will be used. If a class only declares a single constructor to begin with, it will always be used, even if not annotated. Note that an annotated constructor does not have to be public.

或者,你可以通过 Java 8 的 java.util.Optional 表达特定依赖的非必需性质,如下例所示:

Alternatively, you can express the non-required nature of a particular dependency through Java 8’s java.util.Optional, as the following example shows:

public class SimpleMovieLister {

	@Autowired
	public void setMovieFinder(Optional<MovieFinder> movieFinder) {
		...
	}
}

从 Spring Framework 5.0 起,你还可以使用 @Nullable 注解(任何包中的任何种类的注解——例如 JSR-305 中的 javax.annotation.Nullable)或只是利用 Kotlin 内置的空安全性支持:

As of Spring Framework 5.0, you can also use a @Nullable annotation (of any kind in any package — for example, javax.annotation.Nullable from JSR-305) or just leverage Kotlin built-in null-safety support:

  • Java

  • Kotlin

public class SimpleMovieLister {

	@Autowired
	public void setMovieFinder(@Nullable MovieFinder movieFinder) {
		...
	}
}
class SimpleMovieLister {

	@Autowired
	var movieFinder: MovieFinder? = null

	// ...
}

你还可以将 @Autowired 用于众所周知并且可以解析的依赖:BeanFactoryApplicationContextEnvironmentResourceLoaderApplicationEventPublisherMessageSource。这些接口及其扩展接口(例如 ConfigurableApplicationContextResourcePatternResolver)会被自动解析,而不需要任何特殊设置。以下示例自动注入 ApplicationContext 对象:

You can also use @Autowired for interfaces that are well-known resolvable dependencies: BeanFactory, ApplicationContext, Environment, ResourceLoader, ApplicationEventPublisher, and MessageSource. These interfaces and their extended interfaces, such as ConfigurableApplicationContext or ResourcePatternResolver, are automatically resolved, with no special setup necessary. The following example autowires an ApplicationContext object:

  • Java

  • Kotlin

public class MovieRecommender {

	@Autowired
	private ApplicationContext context;

	public MovieRecommender() {
	}

	// ...
}
class MovieRecommender {

	@Autowired
	lateinit var context: ApplicationContext

	// ...
}

@Autowired, @Inject, @Value@Resource 注解由 Spring BeanPostProcessor 实现处理。这意味着您无法将这些注解应用到您自己的 BeanPostProcessorBeanFactoryPostProcessor 类型(如果有)。这些类型必须通过 XML 或 Spring @Bean 方法显式“连接”。

The @Autowired, @Inject, @Value, and @Resource annotations are handled by Spring BeanPostProcessor implementations. This means that you cannot apply these annotations within your own BeanPostProcessor or BeanFactoryPostProcessor types (if any). These types must be 'wired up' explicitly by using XML or a Spring @Bean method.