Spring IoC 容器管理一个或多个 bean。这些 bean 是使用 您提供给容器的配置元数据(例如,以 XML 定义的形式)。<bean/>spring-doc.cn

在容器本身中,这些 bean 定义表示为对象,其中包含(除其他信息外)以下元数据:BeanDefinitionspring-doc.cn

  • 包限定的类名:通常是 bean 被定义。spring-doc.cn

  • Bean 行为配置元素,这些元素表示 Bean 在 容器(范围、生命周期回调等)。spring-doc.cn

  • 对 Bean 执行其工作所需的其他 Bean 的引用。这些 引用也称为协作者或依赖项。spring-doc.cn

  • 要在新创建的对象中设置的其他配置设置 — 例如,大小 pool 的限制或要在管理 连接池。spring-doc.cn

此元数据转换为构成每个 Bean 定义的一组属性。 下表描述了这些属性:spring-doc.cn

表 1.bean 定义
财产 解释于...

spring-doc.cn

实例化 Beanspring-doc.cn

名字spring-doc.cn

命名 Beanspring-doc.cn

范围spring-doc.cn

Bean 作用域spring-doc.cn

构造函数参数spring-doc.cn

依赖关系注入spring-doc.cn

性能spring-doc.cn

依赖关系注入spring-doc.cn

自动装配模式spring-doc.cn

自动装配协作者spring-doc.cn

延迟初始化模式spring-doc.cn

延迟初始化的 Beanspring-doc.cn

初始化方法spring-doc.cn

初始化回调spring-doc.cn

销毁方法spring-doc.cn

销毁回调spring-doc.cn

除了包含有关如何创建特定 bean,则实现还允许注册现有的 在容器外部创建的对象(由用户创建)。这是通过访问 ApplicationContext 的 实现。 支持 此注册通过 和 方法。但是,典型的应用程序仅使用通过常规定义的 bean Bean 定义元数据。ApplicationContextBeanFactorygetBeanFactory()DefaultListableBeanFactoryDefaultListableBeanFactoryregisterSingleton(..)registerBeanDefinition(..)spring-doc.cn

Bean 元数据和手动提供的单例实例需要注册为 early 为了让容器在自动装配期间正确地推断它们 和其他内省步骤。在覆盖现有元数据和现有 在某种程度上支持单例实例,在 运行时(与工厂的实时访问同时)不受官方支持,可能会 导致并发访问异常、Bean 容器中的状态不一致,或两者兼而有之。spring-doc.cn

表 1.bean 定义
财产 解释于...

spring-doc.cn

实例化 Beanspring-doc.cn

名字spring-doc.cn

命名 Beanspring-doc.cn

范围spring-doc.cn

Bean 作用域spring-doc.cn

构造函数参数spring-doc.cn

依赖关系注入spring-doc.cn

性能spring-doc.cn

依赖关系注入spring-doc.cn

自动装配模式spring-doc.cn

自动装配协作者spring-doc.cn

延迟初始化模式spring-doc.cn

延迟初始化的 Beanspring-doc.cn

初始化方法spring-doc.cn

初始化回调spring-doc.cn

销毁方法spring-doc.cn

销毁回调spring-doc.cn

Bean 元数据和手动提供的单例实例需要注册为 early 为了让容器在自动装配期间正确地推断它们 和其他内省步骤。在覆盖现有元数据和现有 在某种程度上支持单例实例,在 运行时(与工厂的实时访问同时)不受官方支持,可能会 导致并发访问异常、Bean 容器中的状态不一致,或两者兼而有之。spring-doc.cn

覆盖 Bean

当使用标识符注册 Bean 时,会发生 Bean 覆盖 已分配。虽然 Bean 覆盖是可能的,但它会使配置更加困难 读取,此功能将在将来的发行版中弃用。spring-doc.cn

要完全禁用 bean 覆盖,可以在刷新之前将标志设置为 on。在这种设置中, 如果使用 Bean 覆盖,则引发 Exception。allowBeanDefinitionOverridingfalseApplicationContextspring-doc.cn

默认情况下,容器会在级别记录每个 bean 覆盖,以便您可以 相应地调整您的配置。虽然不建议这样做,但您可以将这些日志静音 通过将标志设置为 .INFOallowBeanDefinitionOverridingtruespring-doc.cn

Java 配置

如果使用 Java Configuration,则相应的方法始终以静默方式覆盖 具有相同组件名称的扫描 Bean 类,只要该方法的返回类型与该 Bean 类匹配即可。这只是意味着容器将调用 Factory 方法优先使用 Bean 类上任何预先声明的构造函数。@Bean@Bean@Beanspring-doc.cn

命名 Bean

每个 bean 都有一个或多个标识符。这些标识符在 托管 Bean 的容器。一个 bean 通常只有一个标识符。但是,如果它 需要多个,额外的可以被视为别名。spring-doc.cn

在基于 XML 的配置元数据中,您可以使用 attribute、 attribute 或 两者都用于指定 Bean 标识符。该属性允许您指定一个 。 通常,这些名称是字母数字('myBean'、'someService' 等),但它们 也可以包含特殊字符。如果要为 bean,你也可以在属性中指定它们,用逗号 () 分隔, 分号 () 或空格。尽管该属性被定义为类型,但 Bean 唯一性是由容器强制执行的,而不是由 XML 强制执行的 解析 器。idnameididname,;idxsd:stringidspring-doc.cn

您不需要为 bean 提供 a 或 an。如果未显式提供 or,则容器将为该 bean 生成唯一名称。然而 如果要按名称引用该 bean,请使用元素或 Service Locator 样式查找,您必须提供名称。 不提供名称的动机与使用内部 bean自动装配协作者有关。nameidnameidrefspring-doc.cn

Bean 命名约定

约定是在以下情况下对实例字段名称使用标准 Java 约定 命名 bean。也就是说,Bean 名称以小写字母开头,并且是驼峰式大小写的 从那里开始。此类名称的示例包括 、 等。accountManageraccountServiceuserDaologinControllerspring-doc.cn

一致地命名 bean 使您的配置更易于阅读和理解。 此外,如果你使用 Spring AOP,那么在将 advice 应用于一组 bean 时,它会有很大帮助 按名称相关。spring-doc.cn

通过在 Classpath 中进行组件扫描, Spring 会为 unnamed 生成 bean 名称 组件,遵循前面描述的规则:本质上,采用简单的类名 并将其初始字符转换为小写。然而,在(不寻常的)特别 当有多个字符并且同时具有第一个和第二个字符时 为大写,则保留原始大小写。这些规则与 定义者(Spring 在此处使用)。java.beans.Introspector.decapitalize

在 Bean 定义之外为 Bean 设置别名

在 bean 定义本身中,您可以通过使用 属性指定的最多一个名称与任意数量的其他名称的组合 names 在属性中。这些名称可以是同一 bean 的等效别名 ,并且在某些情况下很有用,例如让应用程序中的每个组件 使用特定于该组件的 Bean 名称来引用公共依赖项 本身。idnamespring-doc.cn

指定实际定义 bean 的所有别名并不总是足够的, 然而。有时需要为定义的 bean 引入别名 别处。在配置拆分的大型系统中,通常会出现这种情况 在每个子系统中,每个子系统都有自己的一组对象定义。 在基于 XML 的配置元数据中,您可以使用 Element 来完成 这。以下示例显示了如何执行此操作:<alias/>spring-doc.cn

<alias name="fromName" alias="toName"/>

在这种情况下,名为 使用此别名定义后,称为 。fromNametoNamespring-doc.cn

例如,子系统 A 的配置元数据可以通过 的名称。子系统 B 的配置元数据可以引用 名称为 .编写主应用程序时 使用这两个子系统,则主应用程序通过 的名称。要让所有三个名称都引用同一个对象,您可以 将以下别名定义添加到配置元数据中:subsystemA-dataSourcesubsystemB-dataSourcemyApp-dataSourcespring-doc.cn

<alias name="myApp-dataSource" alias="subsystemA-dataSource"/>
<alias name="myApp-dataSource" alias="subsystemB-dataSource"/>

现在每个组件和主应用程序都可以通过名称来引用 dataSource 这是唯一的,并且保证不会与任何其他定义冲突(有效地 创建命名空间),但它们引用同一个 bean。spring-doc.cn

Java 配置

如果使用 Java 配置,则注释可用于提供别名。 有关详细信息,请参阅使用 @Bean 注释@Beanspring-doc.cn

通过在 Classpath 中进行组件扫描, Spring 会为 unnamed 生成 bean 名称 组件,遵循前面描述的规则:本质上,采用简单的类名 并将其初始字符转换为小写。然而,在(不寻常的)特别 当有多个字符并且同时具有第一个和第二个字符时 为大写,则保留原始大小写。这些规则与 定义者(Spring 在此处使用)。java.beans.Introspector.decapitalize

实例化 Bean

bean 定义本质上是创建一个或多个对象的配方。这 容器在询问时查看命名 bean 的配方,并使用配置 元数据来创建(或获取)实际对象。spring-doc.cn

如果使用基于 XML 的配置元数据,请指定对象的类型(或类) 即在 Element 的属性中实例化。此属性(在内部是实例上的属性)通常是必需的。(有关异常,请参见使用实例工厂方法实例化Bean 定义继承。 您可以通过以下两种方式之一使用该属性:class<bean/>classClassBeanDefinitionClassspring-doc.cn

  • 通常,在容器 它本身通过反射性地调用其构造函数来直接创建 Bean 等效于带有运算符的 Java 代码。newspring-doc.cn

  • 要指定包含工厂方法的实际类,即 invoked 来创建对象,在不太常见的情况下,容器在类上调用工厂方法来创建 Bean。返回的对象类型 从工厂方法的调用可以是同一个类,也可以是另一个类 类。staticstaticstaticspring-doc.cn

嵌套类名

如果要为嵌套类配置 bean 定义,可以使用 binary name 或嵌套类的源名称。spring-doc.cn

例如,如果您在包中有一个名为 class 的 set,并且 此类有一个名为 的嵌套类,它们可以是 用美元符号 () 或点 () 分隔。因此,在 Bean 定义将是 或 。SomeThingcom.exampleSomeThingstaticOtherThing$.classcom.example.SomeThing$OtherThingcom.example.SomeThing.OtherThingspring-doc.cn

使用 Constructor 进行实例化

当你通过构造函数方法创建一个 bean 时,所有普通类都可以被 和 与 Spring 兼容。也就是说,正在开发的类不需要实现 任何特定接口或以特定方式编码。只需指定 bean 类应该就足够了。但是,具体取决于您为该特定 bean,则可能需要一个默认的(空的)构造函数。spring-doc.cn

Spring IoC 容器几乎可以管理您希望它管理的任何类。是的 不限于管理真正的 JavaBeans。大多数 Spring 用户更喜欢带有 仅对默认 (无参数) 构造函数和适当的 setter 和 getter 进行建模 在容器中的属性之后。你也可以有更多异国情调的非 bean 样式 类。例如,如果您需要使用遗留连接池 绝对不遵守 JavaBean 规范,Spring 可以将其管理为 井。spring-doc.cn

使用基于 XML 的配置元数据,您可以按如下方式指定 Bean 类:spring-doc.cn

<bean id="exampleBean" class="examples.ExampleBean"/>

<bean name="anotherExample" class="examples.ExampleBeanTwo"/>

有关向构造函数提供参数的机制的详细信息(如果需要) 以及在构造对象后设置对象实例属性,请参阅注入依赖项spring-doc.cn

对于构造函数参数,容器可以选择相应的 constructor 在多个重载构造函数中。也就是说,为避免歧义, 建议使构造函数签名尽可能简单明了。

使用 Static Factory Method 进行实例化

定义使用静态工厂方法创建的 Bean 时,使用该属性指定包含该工厂方法的类和一个属性 named 来指定工厂方法本身的名称。您应该 能够调用此方法(使用可选参数,如下所述)并返回一个实时的 object,该对象随后被视为通过构造函数创建的。 这种 bean 定义的一个用途是在遗留代码中调用工厂。classstaticfactory-methodstaticspring-doc.cn

以下 Bean 定义指定将通过调用 Factory 方法。定义没有指定返回对象的类型(类), 而是包含 Factory 方法的类。在此示例中,method 必须是 method。以下示例说明如何 指定 Factory 方法:createInstance()staticspring-doc.cn

<bean id="clientService"
	class="examples.ClientService"
	factory-method="createInstance"/>

下面的示例展示了一个将与前面的 bean 定义一起使用的类:spring-doc.cn

public class ClientService {
	private static ClientService clientService = new ClientService();
	private ClientService() {}

	public static ClientService createInstance() {
		return clientService;
	}
}
class ClientService private constructor() {
	companion object {
		private val clientService = ClientService()
		@JvmStatic
		fun createInstance() = clientService
	}
}

有关向工厂方法提供(可选)参数的机制的详细信息 以及在从工厂返回对象后设置对象实例属性, 详见 依赖关系和配置spring-doc.cn

在工厂方法参数的情况下,容器可以选择相应的 method 的 method。也就是说,为避免歧义, 建议使工厂方法签名尽可能简单明了。

工厂方法重载的一个典型问题情况是 Mockito,它有许多 方法的重载。选择最具体的 可能 变体:mockmockspring-doc.cn

<bean id="clientService" class="org.mockito.Mockito" factory-method="mock">
	<constructor-arg type="java.lang.Class" value="examples.ClientService"/>
	<constructor-arg type="java.lang.String" value="clientService"/>
</bean>

使用实例工厂方法进行实例化

与通过 static factory method 进行实例化类似,使用实例工厂方法进行实例化会调用非 static 方法创建一个新的 bean。要使用此功能 机制中,将属性留空,并在属性 在当前 (或 parent) 容器中指定 bean 的名称,其中包含 要调用以创建对象的 instance 方法。设置 factory 方法本身具有 attribute。以下示例显示了 如何配置这样的 bean:classfactory-beanfactory-methodspring-doc.cn

<!-- the factory bean, which contains a method called createClientServiceInstance() -->
<bean id="serviceLocator" class="examples.DefaultServiceLocator">
	<!-- inject any dependencies required by this locator bean -->
</bean>

<!-- the bean to be created via the factory bean -->
<bean id="clientService"
	factory-bean="serviceLocator"
	factory-method="createClientServiceInstance"/>

以下示例显示了相应的类:spring-doc.cn

public class DefaultServiceLocator {

	private static ClientService clientService = new ClientServiceImpl();

	public ClientService createClientServiceInstance() {
		return clientService;
	}
}
class DefaultServiceLocator {
	companion object {
		private val clientService = ClientServiceImpl()
	}
	fun createClientServiceInstance(): ClientService {
		return clientService
	}
}

一个工厂类还可以包含多个工厂方法,如下例所示:spring-doc.cn

<bean id="serviceLocator" class="examples.DefaultServiceLocator">
	<!-- inject any dependencies required by this locator bean -->
</bean>

<bean id="clientService"
	factory-bean="serviceLocator"
	factory-method="createClientServiceInstance"/>

<bean id="accountService"
	factory-bean="serviceLocator"
	factory-method="createAccountServiceInstance"/>

以下示例显示了相应的类:spring-doc.cn

public class DefaultServiceLocator {

	private static ClientService clientService = new ClientServiceImpl();

	private static AccountService accountService = new AccountServiceImpl();

	public ClientService createClientServiceInstance() {
		return clientService;
	}

	public AccountService createAccountServiceInstance() {
		return accountService;
	}
}
class DefaultServiceLocator {
	companion object {
		private val clientService = ClientServiceImpl()
		private val accountService = AccountServiceImpl()
	}

	fun createClientServiceInstance(): ClientService {
		return clientService
	}

	fun createAccountServiceInstance(): AccountService {
		return accountService
	}
}

这种方法表明,工厂 Bean 本身可以通过 依赖注入 (DI)。 详见 依赖关系和配置spring-doc.cn

在 Spring 文档中,“工厂 Bean”是指在 Spring 容器,它通过实例静态工厂方法创建对象。相比之下,(注意大写)指的是特定于 Spring 的 FactoryBean 实现类。FactoryBean

确定 Bean 的运行时类型

确定特定 bean 的运行时类型并非易事。中指定的类 Bean 元数据定义只是一个初始类引用,可能会组合在一起 替换为声明的工厂方法,或者是一个可能导致 bean 的运行时类型不同,或者在实例级别的情况下根本不设置 Factory 方法(通过指定名称解析)。 此外,AOP 代理可以使用基于接口的代理包装 bean 实例,其中 目标 Bean 的实际类型(仅其实现的接口)的有限公开。FactoryBeanfactory-beanspring-doc.cn

了解特定 Bean 的实际运行时类型的推荐方法是 对指定 Bean 名称的调用。这需要以上所有 cases 中,并返回调用的对象类型 将返回相同的 bean 名称。BeanFactory.getTypeBeanFactory.getBeanspring-doc.cn

对于构造函数参数,容器可以选择相应的 constructor 在多个重载构造函数中。也就是说,为避免歧义, 建议使构造函数签名尽可能简单明了。
在工厂方法参数的情况下,容器可以选择相应的 method 的 method。也就是说,为避免歧义, 建议使工厂方法签名尽可能简单明了。

工厂方法重载的一个典型问题情况是 Mockito,它有许多 方法的重载。选择最具体的 可能 变体:mockmockspring-doc.cn

<bean id="clientService" class="org.mockito.Mockito" factory-method="mock">
	<constructor-arg type="java.lang.Class" value="examples.ClientService"/>
	<constructor-arg type="java.lang.String" value="clientService"/>
</bean>
在 Spring 文档中,“工厂 Bean”是指在 Spring 容器,它通过实例静态工厂方法创建对象。相比之下,(注意大写)指的是特定于 Spring 的 FactoryBean 实现类。FactoryBean