对于最新稳定版本,请使用 Spring Framework 7.0.6spring-doc.cadn.net.cn

使用 @Autowired

本节示例中,可以使用 JSR 330 的 @Inject 注解代替 Spring 的 @Autowired 注解。更多详细信息请参见此处spring-doc.cadn.net.cn

您可以将 @Autowired 注解应用于构造函数,如下例所示:spring-doc.cadn.net.cn

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 注解不再是必需的。然而,如果有多个构造函数可用,并且没有主构造函数(primary)或默认构造函数(default constructor),则必须至少在一个构造函数上添加 @Autowired 注解,以指示容器应使用哪一个构造函数。详情请参见关于构造函数解析的讨论。spring-doc.cadn.net.cn

您也可以将 @Autowired 注解应用于传统的 setter 方法,如下例所示:spring-doc.cadn.net.cn

public class SimpleMovieLister {

	private MovieFinder movieFinder;

	@Autowired
	public void setMovieFinder(MovieFinder movieFinder) {
		this.movieFinder = movieFinder;
	}

	// ...
}
class SimpleMovieLister {

	@set:Autowired
	lateinit var movieFinder: MovieFinder

	// ...

}

你也可以将该注解应用于具有任意名称和多个参数的方法上,如下例所示:spring-doc.cadn.net.cn

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 应用于字段,甚至可以将其与构造函数混合使用,如下例所示:spring-doc.cadn.net.cn

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 注解的注入点所使用的类型进行声明。否则,由于运行时出现“未找到匹配类型”的错误,注入可能会失败。spring-doc.cadn.net.cn

对于通过 XML 定义的 bean 或通过类路径扫描发现的组件类,容器通常能提前知道其具体类型。然而,对于 @Bean 工厂方法,你需要确保所声明的返回类型具有足够的表达能力。对于实现了多个接口的组件,或可能通过其实现类型被引用的组件,请考虑在你的工厂方法上声明最具体的返回类型(至少要与引用该 bean 的注入点所要求的具体程度一致)。spring-doc.cadn.net.cn

你还可以通过在期望接收该类型数组的字段或方法上添加 ApplicationContext 注解,指示 Spring 从 @Autowired 中提供所有特定类型的 bean,如下例所示:spring-doc.cadn.net.cn

public class MovieRecommender {

	@Autowired
	private MovieCatalog[] movieCatalogs;

	// ...
}
class MovieRecommender {

	@Autowired
	private lateinit var movieCatalogs: Array<MovieCatalog>

	// ...
}

对于类型化的集合也同样适用,如下例所示:spring-doc.cadn.net.cn

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 定义的注册顺序。spring-doc.cadn.net.cn

你可以在目标类级别以及 @Order 方法上声明 @Bean 注解, 可能用于单个 bean 定义(在多个定义使用相同 bean 类的情况下)。@Order 的值可能会影响注入点的优先级, 但请注意,它们不会影响单例 bean 的启动顺序,后者是一个正交的问题,由依赖关系和 @DependsOn 声明决定。spring-doc.cadn.net.cn

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

即使是有泛型类型的 Map 实例,只要其期望的键类型为 String,也可以被自动装配。 该 Map 的值包含所有符合期望类型的 Bean,而键则包含相应的 Bean 名称,如下例所示:spring-doc.cadn.net.cn

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 可用时,自动装配会失败。对于声明的数组、集合或映射,至少需要有一个匹配的元素。spring-doc.cadn.net.cn

默认行为是将带有注解的方法和字段视为表示必需的依赖项。你可以更改此行为,如以下示例所示,通过将注入点标记为非必需(即,将 required 注解中的 @Autowired 属性设置为 false),使框架跳过无法满足的注入点:spring-doc.cadn.net.cn

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

	// ...
}

如果某个非必需方法的依赖项(或在具有多个参数的情况下,其任一依赖项)不可用,则该方法根本不会被调用。在类似情况下,非必需字段也不会被填充,而是保留其默认值。spring-doc.cadn.net.cn

换句话说,将 required 属性设置为 false 表示该属性在自动装配时是可选的,如果无法完成自动装配,则会忽略该属性。这使得属性可以被赋予默认值,并可通过依赖注入选择性地覆盖这些默认值。spring-doc.cadn.net.cn

注入的构造函数和工厂方法参数属于一种特殊情况,因为 required 注解中的 @Autowired 属性在此处具有略微不同的含义,这是由于 Spring 的构造函数解析算法可能会处理多个构造函数。默认情况下,构造函数和工厂方法参数实际上是必需的,但在只有一个构造函数的场景下存在一些特殊规则,例如多元素注入点(数组、集合、映射)在没有匹配的 Bean 可用时会解析为空实例。这使得一种常见的实现模式成为可能:所有依赖项都可以在一个唯一的多参数构造函数中声明——例如,声明为一个不带 @Autowired 注解的单一公共构造函数。spring-doc.cadn.net.cn

任何给定 Bean 类的构造函数中,只能有一个构造函数将 required 属性声明为 @Autowired,并设置为 true,以指示在用作 Spring Bean 时要自动装配的那个构造函数。因此,如果required属性保持其默认值true, 只能使用一个构造函数进行注解。@Autowired如果多个构造函数声明了该注解,那么它们都必须声明required=false才能被视为自动注入的候选者(类似于XML中的autowire=constructor)。将选择具有最多依赖项的构造函数,前提是这些依赖项能够通过匹配 Spring 容器中的 bean 得到满足。如果所有候选者都无法满足要求, 则将使用主构造函数/默认构造函数(如果存在)。同样地,如果一个类声明了多个构造函数,但其中没有任何一个使用 @Autowired 进行注解,那么将使用主构造函数/默认构造函数(如果存在的话)。如果一个类最初只声明了一个构造函数,那么即使没有添加注解,也始终会使用该构造函数。请注意,带注解的构造函数不必是 public 的。spring-doc.cadn.net.cn

或者,您也可以通过 Java 8 的 java.util.Optional 来表达某个特定依赖项的非必需性,如下例所示:spring-doc.cadn.net.cn

public class SimpleMovieLister {

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

从 Spring Framework 5.0 开始,你还可以使用 @Nullable 注解(任意包中的任意类型的注解——例如来自 JSR-305 的 javax.annotation.Nullable),或者直接利用 Kotlin 内置的空安全支持:spring-doc.cadn.net.cn

public class SimpleMovieLister {

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

	@Autowired
	var movieFinder: MovieFinder? = null

	// ...
}

您也可以对众所周知的可解析依赖项使用 @AutowiredBeanFactoryApplicationContextEnvironmentResourceLoaderApplicationEventPublisherMessageSource。这些接口及其扩展接口(例如 ConfigurableApplicationContextResourcePatternResolver)会 自动解析,无需任何特殊配置。以下示例演示了如何自动装配一个 ApplicationContext 对象:spring-doc.cadn.net.cn

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 方法显式地进行装配。spring-doc.cadn.net.cn