0%

spring-bean-overview

Spring IoC 容器管理一个或多个 bean。这些 bean 是使用配置元数据创建的(例如,以 XML <bean/> 定义的形式)。在容器内,这些 bean 定义表示为 BeanDefinition 对象,其中包含以下元数据:

  • 一个包限定的类名:通常是被定义的 bean 的实际实现类。
  • Bean 行为配置元素,说明 bean 在容器中的行为(范围、生命周期回调等)。
  • 其他 bean 的引用。这些引用也称为协作者或依赖项。
  • 其他配置设置 — 例如,池的大小限制或在管理连接池的 bean 中使用的连接数。

此元数据转换为组成每个 bean 定义的一组属性。下表描述了这些属性:

Property Explained in…
Class 类名
Name 命名
Scope 作用域
Constructor arguments 构造器注入
Properties set 方法注入
Autowiring mode 自动装配
Lazy initialization mode 懒初始化模式
Initialization method 初始化
Destruction method 销毁

Bean 的单例实例需要尽早注册,以便容器在自动装配和步骤中正确推理它们。但官方不支持在运行时注册新 bean(与实时访问工厂同时),可能导致并发访问异常或bean 容器中的状态不一致。

命名

每个 bean 都有一个或多个标识符。这些标识符是唯一的,如果需要多个,可以将多余的视为别名。

基于 XML 的配置元数据中,使用 id 属性、name 属性或两者来指定 bean 标识符。 id 属性指定一个 id,通常,这些名称是字母数字(myBeansomeService等),也可以包含特殊字符。如果要为 bean 引入其他别名,可以在 name 属性中指定它们,用逗号 (,)、分号 (;) 或空格分隔。

命名约定

命名 bean 时使用标准 Java 约定—以小写字母开头,使用驼峰式大小写。比如 accountManager、accountService、userDao、loginController 等。这样做的ha呕出是使配置更易于阅读和理解。

别名

在 bean 定义中,使用name 属性中任意数量的其他名称,可以为 bean 提供多个名称。

在别处定义的 bean 别名,可以使用<alias/>元素来完成。以下示例显示了如何执行此操作:

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

如果使用 Javaconfiguration,则可以使用 @Bean 注解来提供别名。

实例化 bean

bean definition 本质上是创建一个或多个对象的配方。当被请求时,容器会查看该配方,并使用该 bean 定义封装的配置元数据来创建(或获取)实际对象。

基于 XML 的配置元数据,要指定在 <bean/> 元素的 class 属性中实例化的对象的类型(或类)。这个class属性(在内部,它是 BeanDefinition 实例上的 Class 属性)是强制性的。

可以通过以下两种方式之一使用 Class 属性:

  • 在容器本身通过反射调用其构造函数直接创建 bean ,等同于带有 new 运算符的 Java 代码。
  • 容器调用类上的静态工厂方法来创建 bean。调用静态工厂方法返回的对象类型可能是同一个类,也可能是另一类。

使用构造函数实例化

通过构造函数方法创建 bean ,所有普通类都可以被 Spring 使用并与 Spring 兼容。也就是说,正在开发的类不需要实现任何特定的接口或以特定的方式进行编码。只需指定 bean class就足够了。根据该 bean 使用的 IoC 类型,可能需要一个默认(空)构造函数。

基于 XML 的配置元数据,可以按如下方式:

1
2
<bean id="exampleBean" class="examples.ExampleBean"/>
<bean name="anotherExample" class="examples.ExampleBeanTwo"/>

使用静态工厂方法实例化

使用实例工厂方法实例化

确定 Bean 的运行时类型

bean 元数据定义中的指定类只是一个初始类引用,可能与声明的工厂方法结合或作为 FactoryBean 类,导致 bean 的不同运行时类型,或者在实例的情况下根本没有设置-level factory 方法(通过指定的 factory-bean 名称解析)。此外,AOP 代理可以使用基于接口的代理包装 bean 实例,并限制暴露目标 bean 的实际类型(仅其实现的接口)。

推荐方法是对指定 bean 名称的 BeanFactory.getType 调用。