Spring 核心技术(2)
接上篇:Spring 核心技术(1)
version 5.1.8.RELEASE
1.3 Bean概述
Spring IoC 容器管理一个或多个bean,他们都是根据提供的配置元数据(例如 XML 中<bean/>定义)创建的。
在容器内部,这些 bean 定义以 BeanDefinition 对象进行表示,其中包含(以及其他信息)以下元数据:
- 包限定的类名:通常是 bean 的实际实现类
- Bean 行为配置元素,定义 bean 在容器中的行为方式(范围,生命周期回调等)
- 引用 bean 执行工作所需的其他 bean,这些引用也称为协作者或依赖项
- 要在新创建的对象中设置的其他配置。例如连接池中连接池的大小和连接数。
元数据可以转换为构成每个 bean 定义的一组属性。下表描述了这些属性:
| 属性 | 转换目标 |
|---|---|
| 类(Class) | 实例化 Bean |
| 名称(Name) | Bean 名称 |
| 范围(Scope) | Bean 作用范围 |
| 构造函数参数(Constructor arguments) | 依赖注入 |
| 属性(Properties) | 依赖注入 |
| 自动装配模式(Autowiring mode) | 自动装配协作者 |
| 延迟初始化模式(Lazy initialization mode) | 延迟初始化 Bean |
| 初始化方法(Initialization method) | 初始化回调 |
| 销毁方法(Destruction method) | 销毁回调 |
除了包含如何创建特定 bean 的 bean 定义之外,ApplicationContext 实现类还允许用户已经在容器外创建的对象进行注册。这些任务通过使用 getBeanFactory() 方法访问应用程序上下文的 Bean 工厂来完成,该方法返回 Bean 工厂的实现类 DefaultListableBeanFactory。DefaultListableBeanFactory 通过 registerSingleton(..) 和 registerBeanDefinition(..) 方法支持此注册过程。然而一般情况下应用程序仅使用通过常规 bean 定义元数据定义的 bean。
Bean 元数据和手动提供的单例实例需要尽可能早的注册,以便容器在自动装配和其他内省步骤期间正确的推理。虽然在某种程度上支持覆盖现有元数据和现有单例实例,但是在运行时(与对工厂的实时访问同时)注册新 bean 并未得到官方支持,并且可能导致并发访问异常或 bean 容器中的状态不一致。
1.3.1 Bean 命名
每个bean都有一个或多个标识符。这些标识符在托管 bean 的容器中必须是唯一的。一个 bean 通常只有一个标识符。如果它需要多个,则额外的可以被视为别名。
在基于 XML 的配置元数据中,您可以使用 id 属性、name 属性或者两者都用来指定 bean 标识符。id 属性允许您指定一个准确的 id。一般来说这些名称包含字母和数字('myBean','someService'等),但它们也可以包含特殊字符。如果你想要为 bean 引入其他别名,还可以在 name 属性中指定它们,使用逗号(,)、分号(;)或空格进行分隔。作为历史记录,在 Spring 3.1 之前的版本中,id 属性被定义为一种 xsd:ID 类型,它限制了可用的字符。从 3.1 开始,它被定义为一种 xsd:string 类型。请注意,bean id 在容器内必须唯一,但 XML 解析器不会进行限制。
bean 的 name 和 id 并不是必填的。如果你没有显式提供 name 或 id,则容器会为该 bean 生成唯一的名称。但是如果需要通过使用 ref 元素或 Service Locator 样式按名称引用该 bean 则必须提供名称。在使用内部 Bean 或自动装配协作者时可以不提供名称。
Bean命名约定
在命名 bean 时约定使用 Java 实例字段命名规范。也就是说,bean 名称以小写字母开头并遵循驼峰法。这样的名字的例子包括
accountManager、accountService、userDao、loginController等等。
命名 bean 始终使你的配置更易于阅读和理解。此外,如果使用 Spring AOP,那么在将切面织入使用 name 进行关联的一组 bean 时,它会有很大帮助。
通过类路径中的组件扫描,Spring 按照前面描述的规则为未命名的组件生成 bean 名称:实质上是简单的使用类名并将其初始字符转换为小写。但是,在特殊情况下,当类名中有多个字符且第一个和第二个字符都是大写字母时,原始格式将被保留。Spring 遵循
java.beans.Introspector.decapitalize定义的规则。
在 Bean 定义之外为其创建别名
在 bean 定义本身中,可以组合使用单个 id shuxing 和任意数量的 name 属性为 bean 提供多个名称。这些名称可以是同一个 bean 的等效别名,在某些情况下很有用,例如让应用程序中的每个组件通过使用特定于该组件本身的 bean 名称来引用公共依赖项。
但是,只在 Bean 定义时指定别名是不够的,有时需要为其他地方定义的 bean 引入别名。在大型系统中,每个子系统之间的配置通常是分离的,每个子系统都有自己的一组对象定义。在基于 XML 的配置元数据中,您可以使用<alias/>元素来完成此任务。以下示例显示了如何执行此操作:
<alias name="fromName" alias="toName"/>
在示例中,同一容器中名称为 fromName 的 Bean 在使用这种别名定义之后也可以叫做 toName。
例如,子系统 A 的配置元数据通过名称 subsystemA-dataSource 引用数据源。子系统 B 的配置元数据通过名称 subsystemB-dataSource 引用数据源。在编写同时使用这两个子系统的主应用程序时,主应用程序通过名称 myApp-dataSource 引用数据源。要使这三个名称引用同一对象,可以将以下别名定义添加到配置元数据中:
<alias name="myApp-dataSource" alias="subsystemA-dataSource"/>
<alias name="myApp-dataSource" alias="subsystemB-dataSource"/>
现在,每个组件和主应用程序都可以通过一个唯一的名称引用 dataSource,并保证不与任何其他定义冲突(实际上创建了一个命名空间),但它们引用相同的 bean。
基于 Java 的配置
如果使用 Javaconfiguration,则
@Bean注解可以提供别名。有关详细信息,请参阅使用 @Bean 注解 。
1.3.2 初始化 Bean
bean 定义本质上是创建一个或多个对象的方法。容器在被请求时查找已经命名的 bean 的方法,并使用由该 bean 定义封装的配置元数据来创建(或获取)实际对象。
如果使用基于 XML 的配置元数据,则需要在 <bean/> 元素的 class 属性指定对象类型。此 class 属性通常是必需的(对应 BeanDefinition 实例的 Class 属性)。(有关例外的情况,请参阅使用实例工厂方法进行实例化和 Bean定义继承)。你可以通过以下两种方式之一使用 Class 属性:
- 容器通过反射调用 Bean 的构造函数(类似于使用 new 运算符的 Java 代码)直接创建 Bean 的情况下指定要构造的 bean 类型。
- 调用指定包含静态工厂方法的实际类来创建对象,在不太常见的情况下,容器调用类中的静态工厂方法来创建 bean。通过调用静态工厂方法返回的对象类型可以完全是同一个类或另一个类。
内部类名
如果要为静态嵌套类配置 bean 定义则必须使用嵌套类的二进制名称。例如,如果在
com.example包中有一个类叫做SomeThing,并且SomeThing类有一个静态嵌套类叫做OtherThing,则 bean 定义中的class属性值将为com.example.SomeThing$OtherThing。请注意,类名中
$字符用于将嵌套类名与外部类名分开。
使用构造函数实例化
当您通过构造方法创建 bean 时,所有普通类都可以使用并与 Spring 兼容。也就是说,需要开发的类不需要实现任何特定接口或以某种特定方式进行编码。简单地指定 bean 的类就足够了。取决于指定 bean 使用的 IoC 类型,有时候你可能需要一个默认构造函数。
Spring IoC 容器几乎可以管理你希望它管理的任何类。它不仅限于管理真正的 JavaBean。大多数 Spring 用户更倾向于使用只有一个默认构造函数且在属性之后由合适的 setter 和 getter 的 JavaBean。你还可以在容器中包含一些外部的非 bean 样式类。例如,如果需要使用完全不符合 JavaBean 规范的传统连接池,Spring 也可以对其进行管理。
使用基于 XML 的配置元数据,你可以按如下方式指定 bean 类:
<bean id="exampleBean" class="examples.ExampleBean"/>
<bean name="anotherExample" class="examples.ExampleBeanTwo"/>
有关为构造函数提供参数的机制(如果需要)以及在构造对象后设置对象实例属性的详细信息,请参阅注入依赖项。
使用静态工厂方法实例化
定义使用静态工厂方法创建的 bean 时,请使用 class 属性指定包含静态工厂方法的类,并使用 factory-method 属性指定工厂方法本身的名称。你应该能够调用此方法(如后面示例所述,使用可选参数)并返回一个活动对象,随后将其视为通过构造函数创建的对象。这种 bean 定义的一个用途是在传统代码中调用静态工厂。
以下 bean 定义演示通过调用工厂方法来创建 bean。该定义未指定返回对象的类型(类),仅指定了包含工厂方法的类。在此示例中,createInstance()方法必须是静态方法。以下示例显示如何指定工厂方法:
<bean id="clientService" class="examples.ClientService" factory-method="createInstance"/>
以下示例显示了一个可以使用之前 bean 定义的类:
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 属性设置工厂方法本身的名称。以下示例显示如何配置此类 bean:
<!-- 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"/>
以下示例展示了相应的Java类:
public class DefaultServiceLocator {
private static ClientService clientService = new ClientServiceImpl();
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"/>
以下示例展示了相应的Java类:
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;
}
}
这种方法表明工厂 bean 本身可以通过依赖注入(DI)进行管理和配置。请参阅依赖关系和配置详情。
在 Spring 文档中,“工厂 bean”指的是在 Spring 容器中配置并通过实例或静态工厂方法创建对象的 bean。相比之下,
FactoryBean(注意大写)指的是特定于 Spring 的FactoryBean。
Spring 核心技术(2)的更多相关文章
- Spring核心技术(八)——Spring自动装载的注解
本文针对自动装载的一些注解进行描述. 基于注解的容器配置 @Required注解 @Required注解需要应用到Bean的属性的setter方法上面,如下面的例子: public class Sim ...
- Spring核心技术(六)——Spring中Bean的生命周期
前文已经描述了Bean的作用域,本文将描述Bean的一些生命周期作用,配置还有Bean的继承. 定制Bean 生命周期回调 开发者通过实现Spring的InitializeingBean和Dispos ...
- Spring核心技术(五)——Spring中Bean的作用域
前文概述了Spring的容器,Bean,以及依赖的一些信息,本文将描述一下Bean的作用域 Bean的作用域 当开发者定义Bean的时候,同时也会定义了该如何创建Bean实例.这些具体创建的过程是很重 ...
- Spring核心技术(四)——Spring的依赖及其注入(续二)
前面两篇文章描述了IoC容器中依赖的概念,包括依赖注入以及注入细节配置.本文将继续描述玩全部的依赖信息. 使用 depends-on 如果一个Bean是另一个Bean的依赖的话,通常来说这个Bean也 ...
- Spring 核心技术(3)
接上篇:Spring 核心技术(2) version 5.1.8.RELEASE 1.4 依赖 典型的企业应用程序不会只包含单个对象(或 Spring 术语中的 bean).即使是最简单的应用程序也是 ...
- Spring 核心技术(4)
接上篇:Spring 核心技术(3) version 5.1.8.RELEASE 1.4.2 依赖关系及配置详情 如上一节所述,你可以将 bean 属性和构造函数参数定义为对其他托管 bean(协作者 ...
- Spring 核心技术(5)
接上篇:Spring 核心技术(4) version 5.1.8.RELEASE 1.4.5 自动装配协作者 Spring 容器可以自动连接协作 bean 之间的关系.你可以让 Spring 通过检查 ...
- Spring 核心技术(6)
接上篇:Spring 核心技术(5) version 5.1.8.RELEASE 1.5 Bean 作用域 创建 bean 定义时,你创建了一种用于创建 bean 定义中定义的类实例的方法.bean定 ...
- Spring 核心技术(7)
接上篇:Spring 核心技术(6) version 5.1.8.RELEASE 1.6 定制 Bean 的特性 Spring Framework 提供了许多可用于自定义 bean 特性的接口.本节将 ...
随机推荐
- 【WPF】SnapsToDevicePixels与UseLayoutRounding二者到底有什么区别?供参考
原文:[WPF]SnapsToDevicePixels与UseLayoutRounding二者到底有什么区别?供参考 MSDN上解释了一大堆,二者对比来看,并不能发现什么明显的区别,微软爸爸也不知道多 ...
- 利用winIO3.0进行windows10 64bit端口读取
一.winIO介绍 WinIO程序库允许在32位的Windows应用程序中直接对I/O端口和物理内存进行存取操作.通过使用一种内核模式的设备驱动器和其它几种底层编程技巧,它绕过了Windows系统的保 ...
- 基于vue开发的多功能的时间选择器组件,开箱即用
好一段时间没有写过博客了,在国庆期间心血来潮优化了一个组件,在日常开发中时常会有需求用到时间选择器,不同的项目需求可能会不一样.近期开发的几个项目中就有需求用到这样的选择器,由于以前有用到相关的组件, ...
- windows下捕获dump之Google breakpad_client
breakpad是Google开源的一套跨平台工具,用于dump的处理.很全的一套东西,我这里只简单涉及breakpad客户端,不涉及纯文本符号生成,不涉及dump解析. 一.使用 最简单的是使用进程 ...
- GIS基础软件及操作(十)
原文 GIS基础软件及操作(十) 练习十.网络分析 (1) 加深对网络分析基本原理.方法的认识:(2) 熟练掌握ARCGIS下进行道路网络分析的技术方法:(3) 结合实际.掌握利用网络分析方法解决地学 ...
- Vm安装
说明:都是默认安装,并不需要繁琐设置,所以没有文字说明
- ASP.NET MVC5快速入门--MyFirstWeb并发布到Windows Azure上
博主刚刚学习ASP.NET MVC5,看着微软的文档一点点学,就把FirstWeb的建立展示一下下啦,本次建立一个带个人身份验证的例子(即有注册登录机制的动态网页),开始,啦啦啦~~ 新建一个项目,选 ...
- delphi Stomp客户端连接 RabbitMQ(1)
最近公司想上个消息推送系统,网上搜了很多,因公司主要产品是Delphi,我选择了开源的RabbitMQ,Erlang语言开发,天生并行. 代码下载地址:delphistomp下载地址 windows上 ...
- 如何配置一个绿色化的 Qt for Windows 开发环境(有.bat脚本,亲测好用) good
安装 QtCreator for Windows 其实是很简单的,不过,我一向讨厌什么软件都得弄个安装程序,我希望我所安装的这个 Qt 可以是绿色的.便携的,如果无法实现,至少让这个 Qt 可以在新系 ...
- Tencent://Message/协议的实现原理(Windows提供协议注册)
腾讯官方通过 Tencent://Message/协议可以让QQ用户显示QQ/TM的在线状态发布在互联网上:并且点击 XXX ,不用加好友也可以聊天 官方链接: http://is.qq.com/w ...