Spring | 3.3 bean概述

3.3 bean概述

Spring IoC容器管理一个或多个bean。这些bean是使用您提供给容器的配置元数据创建的,例如,以XML 定义的形式 。
在容器本身内,这些bean定义表示为BeanDefinition 对象,其中包含(以及其他信息)以下元数据:

  • 包限定的类名:通常是正在定义的bean的实际实现类。
  • Bean行为配置元素,说明bean在容器中的行为方式(范围,生命周期回调等)。
  • 引用bean执行其工作所需的其他bean; 这些引用也称为协作者或依赖项。
  • 要在新创建的对象中设置的其他配置设置,例如,在管理连接池的Bean中使用的连接数,或池的大小限制。

此元数据转换为构成每个bean定义的一组属性。
表3.1 bean的定义

属性解释在…
第3.3.2节“实例化bean”
名称第3.3.1节“命名bean”
范围第3.5节“Bean范围”
构造函数参数第3.4.1节“依赖注入”
性能第3.4.1节“依赖注入”
自动装配模式第3.4.5节“自动装配协作者”
延迟初始化模式第3.4.4节“懒惰初始化的bean”
初始化方法称为“初始化回调”的部分
破坏方法“毁灭回调”一节

除了包含有关如何创建特定bean的信息的bean定义之外, ApplicationContext实现还允许用户注册在容器外部创建的现有对象。通过getBeanFactory()方法访问ApplicationContext的BeanFactory,该方法返回BeanFactory实现DefaultListableBeanFactory。DefaultListableBeanFactory通过registerSingleton(…)和registerBeanDefinition(…)方法支持这种注册。然而,典型的应用程序只使用通过元数据bean定义定义的bean。
注意:Bean元数据和手动提供的单例实例需要尽早注册,以便容器在自动装配和其他内省步骤中正确地推断它们。虽然在某种程度上支持覆盖现有的元数据和现有的单例实例,但是在运行时注册新bean(与对工厂的实时访问同时进行)并不是官方支持的,并且可能导致bean容器中的并发访问异常和(或)不一致状态。

3.3.1 bean的命名

每个bean都有一个或多个标识符。这些标识符在承载bean的容器中必须是惟一的。bean通常只有一个标识符,但如果它需要多个标识符,则可以将额外的标识符视为别名。
在基于xml的配置元数据中,使用id和(或)name属性指定bean标识符。id属性允许您精确地指定一个id。通常这些名称是字母数字(‘myBean’、'fooService’等),但也可能包含特殊字符。如果希望向bean引入其他别名,还可以在name属性中指定它们,以逗号(、)、分号(;)或空格分隔。作为历史记录,在Spring 3.1之前的版本中,id属性被定义为xsd: id类型,这限制了可能的字符。从3.1开始,它被定义为xsd:string类型。注意,bean id惟一性仍然由容器执行,但不再由XML解析器执行
你不需要为bean提供名称或id。如果没有显式提供名称或id,容器将为该bean生成唯一的名称。但是,如果你希望通过名称引用该bean,通过使用ref元素或服务定位器样式查找,你必须提供一个名称。不提供名称的动机与使用内部bean和自动装配协作者有关。

bean命名约定

约定是在为bean命名时使用标准Java约定作为实例字段名。也就是说,bean名称以小写字母开头,从那时起采用驼峰大小写。这样的名字的例子有(没有引号)‘accountManager’、‘accountService’、‘userDao’、'loginController’等等。
一致地命名bean可以使您的配置更容易阅读和理解,如果您正在使用Spring AOP,那么当您将建议应用到一组按名称关联的bean时,它会提供很大的帮助。

通过在类路径中扫描组件,Spring按照上面的规则为未命名的组件生成bean名称:本质上,使用简单的类名并将其初始字符转换为小写。但是,在(不寻常的)特殊情况下,如果有多个字符,并且第一个和第二个字符都是大写的,则保留原来的大小写。这些规则与java.beans.Introspector.decapitalize(这里使用的是Spring)定义的规则相同。

在bean定义之外别名化bean

在bean定义本身中,可以使用id属性指定的最多一个名称和name属性中任意数量的其他名称的组合,为bean提供多个名称。这些名称可以等效于同一个bean的别名,并且在某些情况下非常有用,例如允许应用程序中的每个组件通过使用特定于该组件本身的bean名称引用公共依赖项。
但是,指定实际定义bean的所有别名并不总是足够的。有时需要为在其他地方定义的bean引入别名。在大型系统中,配置通常在每个子系统之间进行划分,每个子系统都有自己的一组对象定义。在基于xml的配置元数据中,可以使用元素来完成此任务。

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

在本例中,在使用别名定义之后,同一容器中名为fromName的bean也可以称为toName。
例如,子系统A的配置元数据可以通过名称subsystem - DataSource引用数据源。子系统B的配置元数据可以通过名称subsystem - DataSource引用数据源。当组合使用这两个子系统的主应用程序时,主应用程序通过名称myApp-dataSource引用数据源。要让这三个名称都指向您添加到MyApp配置元数据的相同对象,请使用以下别名定义:

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

现在每个组件和主应用程序可以通过名称引用数据源是独一无二的,保证不与其他任何冲突定义(有效地创建一个名称空间),然而他们引用同一个bean。

java配置
如果您正在使用Java-configuration,可以使用@Bean注释来提供别名,详细信息请参见3.12.3节“使用@Bean注释”。

3.3.2 初始化beans

bean定义本质上是创建一个或多个对象的诀窍。当被询问时,容器会查看命名bean的配方,并使用该bean定义封装的配置元数据来创建(或获取)一个实际对象。
如果使用基于xml的配置元数据,则指定要在元素的class属性中实例化的对象的类型(或类)。这个类属性通常是强制性的,它在内部是BeanDefinition实例上的一个类属性。(有关例外,请参阅“使用实例工厂方法实例化”一节和“Bean定义继承”3.7节。)您可以通过以下两种方式之一使用Class属性:

  • 通常,指定容器本身通过反射调用其构造函数直接创建bean的情况下要构造的bean类,这与使用新操作符的Java代码有些类似。
  • 要指定包含将被调用来创建对象的静态工厂方法的实际类,在容器调用类上的静态工厂方法来创建bean的不太常见的情况下。从静态工厂方法调用返回的对象类型可以是同一个类,也可以完全是另一个类。

内部类的名字。如果要为静态嵌套类配置bean定义,必须使用嵌套类的二进制名称。
例如,如果com中有一个名为Foo的类。这个Foo类有一个叫做Bar的静态嵌套类,bean定义上class属性的值是…
注意,在名称中使用$字符将嵌套的类名与外部类名分隔开。

com.example.Foo$Bar
通过构造函数初始化

当您使用构造函数方法创建bean时,所有的普通类都可以被Spring使用并与Spring兼容。也就是说,正在开发的类不需要实现任何特定的接口或以特定的方式编码。只需指定bean类就足够了。但是,根据您为特定bean使用的IoC类型,您可能需要一个默认(空)构造函数。
Spring IoC容器几乎可以管理您希望它管理的任何类;它不仅限于管理真正的javabean。大多数Spring用户更喜欢实际的javabean,它只有一个默认(无参数)构造函数,以及根据容器中的属性构建适当的setter和getter。您还可以在容器中包含更多非bean样式的类。例如,如果您需要使用完全不符合JavaBean规范的遗留连接池,Spring也可以管理它。
使用基于xml的配置元数据,您可以指定您的bean类如下:

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

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

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

使用静态工厂方法实例化

定义使用静态工厂方法创建的bean时,使用class属性指定包含静态工厂方法的类,使用factory-method属性指定工厂方法本身的名称。您应该能够调用这个方法(带有后面描述的可选参数)并返回一个活动对象,该对象随后被视为通过构造函数创建的。这种bean定义的一个用途是在遗留代码中调用静态工厂。
下面的bean定义指定将通过调用factory-method创建bean。定义没有指定返回对象的类型(类),只指定包含工厂方法的类。在本例中,createInstance()方法必须是一个静态方法。

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

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

	public static ClientService createInstance() {
		return clientService;
	}
}

有关向工厂方法提供(可选)参数并在对象从工厂返回后设置对象实例属性的机制的详细信息,请参阅依赖项和配置。

使用实例工厂方法实例化

与通过静态工厂方法实例化类似,使用实例工厂方法实例化将从容器中调用现有bean的非静态方法来创建新bean。要使用这种机制,请保留class属性为空,在factory-bean属性中,在当前(或父/父)容器中指定bean的名称,该容器包含要调用来创建对象的实例方法。使用factory-method属性设置factory方法本身的名称。

<!-- the factory bean, which contains a method called createInstance() -->
<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"/>
public class DefaultServiceLocator {

	private static ClientService clientService = new ClientServiceImpl();
	private DefaultServiceLocator() {}

	public ClientService createClientServiceInstance() {
		return clientService;
	}
}

一个工厂类还可以容纳多个工厂方法,如下所示:

<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"/>
public class DefaultServiceLocator {

	private static ClientService clientService = new ClientServiceImpl();
	private static AccountService accountService = new AccountServiceImpl();

	private DefaultServiceLocator() {}

	public ClientService createClientServiceInstance() {
		return clientService;
	}

	public AccountService createAccountServiceInstance() {
		return accountService;
	}

}

这种方法表明,可以通过依赖项注入(dependency injection, DI)管理和配置工厂bean本身。请参阅有关依赖项和配置的详细信息。
注意:在Spring文档中,工厂bean指的是在Spring容器中配置的bean,该容器将通过实例或静态工厂方法创建对象。相反,FactoryBean(注意大小写)指的是特定于spring的FactoryBean。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值