本文是笔者阅读Spring源码的记录文章,由于本人技术水平有限,在文章中难免出现错误,如有发现,感谢各位指正。很多内容来自别人博客
简介
现如今,我们一般获取对象的方式有两种,一种是手动直接 new;另一种是交给 Spring 管理,Spring 将管理的对象称之为 Bean,容器会先实例化 Bean,然后自动注入,实例化的过程就需要依赖 BeanDefinition。
对于基于Spring框架开发的一个应用系统,其中每一个bean都来自于一个bean定义:开发人员的某个bean定义,框架自身的某个bean定义,三方库的某个bean定义。
这些概念上的bean定义,通过Spring接口BeanDefinition被建模,并且在应用运行时都会以一个BeanDefinition对象的形式被注册到Spring IoC容器中。所以说,bean定义,或者说,BeanDefinition接口,是整个Spring容器的根本概念之一。
BeanDefinition 用于保存 Bean 的相关信息,包括属性、构造方法参数、依赖的 Bean 名称及是否单例、延迟加载等,它是实例化 Bean 的原材料,Spring 就是根据 BeanDefinition 中的信息实例化 Bean。
接口BeanDefinition
简介
Spring
框架中的接口BeanDefinition
顾名思义,就是"bean定义"的意思,它定义了创建相应的bean
使用如下属性 :
dd
属性名称 | 介绍 |
---|---|
parentName |
双亲bean 定义(parent bean definition )的名称.如果没有双亲bean定义,这里为空 |
beanClassName |
bean 的类名,在bean factory 的post process 阶段可能会被修改。注意该属性并不总是运行时被对应bean 真正使用的类的名称:比如,bean 是通过某个类的静态工厂方法生成的,这里是该类的类名,再比如,bean 是通过一个工厂bean 生成的,那这里为空。 |
scope |
作用域, singleton 或者prototype 。在bean 的作用域尚未决定之前,该属性为null
|
lazyInit |
是否懒加载,仅适用于singleton bean 。当一个singleton bean 被指定lazyInit 为false 时,它会在bean factory 启动时执行singleton bean 初始化的阶段被实例化。 |
dependsOn |
所依赖的bean 的名称,如果有多个依赖的bean ,这里需要都列出来。容器会保证这些被依赖的bean 先被初始化。 |
autowireCandidate |
该bean 是否作为自动绑定的候选,仅适用于基于类型的自动绑定。基于名称的绑定不受此属性影响。 |
primary |
当前bean 定义是否主bean 。当某个自动绑定遇到多个候选bean 时,primary 属性为true 的会被使用。 |
factoryBeanName |
如果要使用factory bean 来创建bean ,这里指定了相应的工厂bean 的类名称 |
factoryMethodName | 工厂方法名称。基于类静态工厂方法的情况下,结合beanClassName 使用;基于工厂bean 的情况下,结合factoryBeanName 使用。如果bean 定义的constructorArgumentValues 有内容,工厂方法被调用时会使用该属性。 |
constructorArgumentValues |
bean 创建时的构造函数参数 |
propertyValues |
新建的bean 需要设置的属性值 |
initMethodName |
bean 的初始化方法 |
destroyMethodName |
bean 的析构方法 |
role |
bean 的角色:APPLICATION ,SUPPORT ,INFRASTRUCTURE 。提示框架该bean 的角色和重要程度。 |
description |
bean 的描述,human readable
|
singleton |
作用域断言,是否singleton
|
prototype |
作用域断言,是否prototype
|
abstract |
是否抽象bean 定义,抽象bean 定义的目的不是用于实例化bean ,而是有其他目的。 |
resourceDescription |
资源描述文本,告知当前bean 定义的来源,一般用于错误时显示上下文。 |
originatingBeanDefinition | 返回来源bean定义(如果有的话)。通过该属性,可以获取被修饰的bean定义。需要注意的是该属性仅仅返回直接来源bean定义而不是返回最深处的来源bean定义。一个bean定义的originatingBeanDefinition属性隐含了一个来源bean定义链,通过迭代访问该链,可以最终找到最终来自用户的bean定义。 |
上表中提到的bean的角色,分别是:
- APPLICATION – 指出该bean是应用程序的主要部分,通常对应用户定义的bean。
- SUPPORT – 应用支持性质的bean,在某些地方比较重要,但从整个应用的返回来看,还没那么重要。
- INFRASTRUCTURE – 基础设施bean,仅仅用于框架内部工作,跟终端用户无关。
接口BeanDefinition
实现类简介
BeanDefinition 接口有一些实现类,并且这些实现类有一些共同的基础逻辑。这些实现类主要是 : RootBeanDefinition,ChildBeanDefinition和GenericBeanDefinition。它们共同的基础逻辑实现在抽象类AbstractBeanDefinition。这些类之间的层级关系如下:
根据类图看到BeanDefinition有GenericBeanDefinition
、ChildBeanDefinition
、RootBeanDefinition
三个实现类;
BeanDefinition是配置文件<bean>元素标签在容器中内部表示形式。
-
RootBeanDefinition
可以单独作为一个BeanDefinition
,也可以作为其他BeanDefinition
的父类。但是他不能作为其他BeanDefinition的子类 -
ChildBeanDefinition
相当于一个子类,不可以单独存在,必须要依赖一个父BeanDetintion
。 -
GenericBeanDefinition
可以替代RootBeanDefinition
和ChildBeanDefinition
-
AnnotatedGenericBeanDefinition
处理@
Configuration
注解 -
ConfigurationClassBeanDefinition
处理@Bean
注解 -
ScannedGenericBeanDefinition
处理@Component
注解
一般情况下,建议使用
GenericBeanDefinition
用于定义用户可见的bean
定义。而对于一些父子关系已经确定的情况,使用RootBeanDefinition
/ChildBeanDefinition
。
各个实现类的区别/特点
- RootBeanDefinition– 不能设置parent bean定义
由此可见,RootBeanDefinition不能用于用于父子bean定义关系中的"子bean定义"
- ChildBeanDefinition – 必须设置parent bean定义,而且必须是通过构造函数指定
ChildBeanDefinition很适合父子bean定义关系明确的情况下基于双亲bean定义和自身少量设置一些个性化属性从而进行子bean定义。
实际上,真正在创建子bean定义规定的bean对象时,Spring框架内部是将双亲bean定义和孩子bean定义合并形成一个最终使用的RootBeanDefinition,这里孩子bean定义中设置的属性会被优先使用,没有指定的都会继承使用双亲bean定义中的设置。
-
GenericBeanDefinition
– 可以动态设置parent bean
定义,也可以不设置parent bean
定义
由此可见,
GenericBeanDefinition
既可以替代RootBeanDefinition
,也可以替代ChildBeanDefinition
,所以GenericBeanDefinition
更一般化(generic
)
AnnotatedBeanDefinition
AnnotatedBeanDefinition 是 BeanDefinition 子接口之一,该接口扩展了 BeanDefinition 的功能,其用来操作注解元数据。一般情况下,通过注解方式得到的 Bean(@Component、@Bean),其 BeanDefinition 类型都是该接口的实现类。
public interface AnnotatedBeanDefinition extends BeanDefinition {
// 获得当前 Bean 的注解元数据
AnnotationMetadata getMetadata();
// 获得当前 Bean 的工厂方法上的元数据
MethodMetadata getFactoryMethodMetadata();
}
该接口可以返回两个元数据的类:
-
AnnotationMetadata:主要对 Bean 的注解信息进行操作,如:获取当前 Bean 标注的所有注解、判断是否包含指定注解。
-
MethodMetadata:方法的元数据类。提供获取方法名称、此方法所属类的全类名、是否是抽象方法、判断是否是静态方法、判断是否是final方法等。
AbstractBeanDefinition
AbstractBeanDefinition是最终全功能BeanDefinition实现类的基类,也就是这些类的共同属性和公共逻辑实现。
AbstractBeanDefinition中并没有太复杂的实现逻辑,而是主要是用于:
- 定义共用的构造函数。
- 定义共用BeanDefinition属性以及提供它们的getter/setter方法。
- 其他一些共用工具方法 : 从另外一个bean定义覆盖当前bean定义,应用初始值等等。
另外AbstractBeanDefinition继承自BeanMetadataAttributeAccessor。BeanMetadataAttributeAccessor为AbstractBeanDefinition提供了接口AttributeAccessor定义的属性访问能力以及BeanMetadataElement定义的源配置对象设置/获取能力。
继承自AbstractBeanDefinition的全功能BeanDefinition实现类有 :
- GenericBeanDefinition
- RootBeanDefinition
- ChildBeanDefinition
源代码如下:
public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor
implements BeanDefinition, Cloneable {
// 默认的 SCOPE,默认是单例
public static final String SCOPE_DEFAULT = "";
// 不进行自动装配
public static final int AUTOWIRE_NO = AutowireCapableBeanFactory.AUTOWIRE_NO;
// 根据 Bean 的名字进行自动装配,byName
public static final int AUTOWIRE_BY_NAME = AutowireCapableBeanFactory.AUTOWIRE_BY_NAME;
// 根据 Bean 的类型进行自动装配,byType
public static final int AUTOWIRE_BY_TYPE = AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE;
// 根据构造器进行自动装配
public static final int AUTOWIRE_CONSTRUCTOR = AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR;
// 首先尝试按构造器自动装配。如果失败,再尝试使用 byType 进行自动装配。(Spring 3.0 之后已废除)
public static final int AUTOWIRE_AUTODETECT = AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT;
// 通过依赖检查来查看 Bean 的每个属性是否都设置完成
// 以下常量分别对应:不检查、对依赖对象检查、对基本类型,字符串和集合进行检查、对全部属性进行检查
public static final int DEPENDENCY_CHECK_NONE = 0;
public static final int DEPENDENCY_CHECK_OBJECTS = 1;
public static final int DEPENDENCY_CHECK_SIMPLE = 2;
public static final int DEPENDENCY_CHECK_ALL = 3;
// 关闭应用上下文时需调用的方法名称
public static final String INFER_METHOD = "(inferred)";
// 存放 Bean 的 Class 对象
private volatile Object beanClass;
// Bean 的作用范围
private String scope = SCOPE_DEFAULT;
// 非抽象
private boolean abstractFlag = false;
// 非延迟加载
private boolean lazyInit = false;
// 默认不自动装配
private int autowireMode = AUTOWIRE_NO;
// 默认不依赖检查
private int dependencyCheck = DEPENDENCY_CHECK_NONE;
// 依赖的 Bean 列表
private String[] dependsOn;
// 可以作为自动装配的候选者,意味着可以自动装配到其他 Bean 的某个属性中
private boolean autowireCandidate = true;
// 创建当前 Bean 实例工厂类名称
private String factoryBeanName;
// 创建当前 Bean 实例工厂类中方法名称
private String factoryMethodName;
// 存储构造方法的参数
private ConstructorArgumentValues constructorArgumentValues;
// 存储 Bean 属性名称以及对应的值
private MutablePropertyValues propertyValues;
// 存储被覆盖的方法信息
private MethodOverrides methodOverrides;
// init、destroy 方法名称
private String initMethodName;
private String destroyMethodName;
// 是否执行 init 和 destroy 方法
private boolean enforceInitMethod = true;
private boolean enforceDestroyMethod = true;
// Bean 是否是用户定义的而不是应用程序本身定义的
private boolean synthetic = false;
// Bean 的身份类别,默认是用户定义的 Bean
private int role = BeanDefinition.ROLE_APPLICATION;
// Bean 的描述信息
private String description;
// Bean 定义的资源
private Resource resource;
...
}
AbstractBeanDefinition 直接实现类:RootBeanDefinition、GenericBeanDefinition、ChildBeanDefinition。
最后三个 BeanDefinition 既实现了 AnnotatedBeanDefinition 接口,又间接继承 AbstractBeanDefinition 抽象类,这些 BeanDefinition 描述的都是注解形式的 Bean。
ConfigurationClassBeanDefinition
该类继承自 RootBeanDefinition ,并实现了 AnnotatedBeanDefinition 接口。这个 BeanDefinition 用来描述在标注 @Configuration 注解的类中,通过 @Bean 注解实例化的 Bean。
其功能特点如下:
1、如果 @Bean 注解没有指定 Bean 的名字,默认会用方法的名字命名 Bean。
2、标注 @Configuration 注解的类会成为一个工厂类,而标注 @Bean 注解的方法会成为工厂方法,通过工厂方法实例化 Bean,而不是直接通过构造方法初始化。
3、标注 @Bean 注解的类会使用构造方法自动装配
AnnotatedGenericBeanDefinition
该类继承自 GenericBeanDefinition ,并实现了 AnnotatedBeanDefinition 接口。这个 BeanDefinition 用来描述标注 @Configuration 注解的 Bean。
ScannedGenericBeanDefinition
该类继承自 GenericBeanDefinition ,并实现了 AnnotatedBeanDefinition 接口。这个 BeanDefinition 用来描述标注 @Component 注解的 Bean,其派生注解如 @Service、@Controller 也同理。
合并了的bean定义--MergedBeanDefinition
在Spring中,关于bean定义,其Java建模模型是接口BeanDefinition, 其变种有RootBeanDefinition,ChildBeanDefinition,还有GenericBeanDefinition,AnnotatedGenericBeanDefinition,ScannedGenericBeanDefinition等等。这些概念模型抽象了不同的关注点。关于这些概念模型,除了有概念,也有相应的Java建模模型,甚至还有通用的实现部分AbstractBeanDefinition。但事实上,关于BeanDefinition,还有一个概念也很重要,这就是MergedBeanDefinition(中文也许应该翻译成"合并了的bean定义"?),但这个概念并没有相应的Java模型对应。但是它确实存在,并且Spring专门为它提供了一个生命周期回调定义接口MergedBeanDefinitionPostProcessor用于扩展。
MergedBeanDefinition
的生成
我们先从代码看一个MergedBeanDefinition
是怎么生成的 ? 下面是类AbstractBeanFactory
中bean
获取方法doGetBean()
的伪代码 :
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
// ...
// 这里根据bean名称获取MergedBeanDefinition,结果类型是RootBeanDefinition
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// ...
createBean(beanName, mbd, args);
// ...
}
从上面代码可见,通过方法getMergedLocalBeanDefinition()
,一个RootBeanDefinition mbd
根据bean
名称生成了。我们进而跟踪getMergedLocalBeanDefinition
的实现。如下 :
protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName)
throws BeansException {
// Quick check on the concurrent map first, with minimal locking.
RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
if (mbd != null) {
return mbd;
}
return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}
protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd)
throws BeanDefinitionStoreException {
return getMergedBeanDefinition(beanName, bd, null);
}
protected RootBeanDefinition getMergedBeanDefinition(
String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
throws BeanDefinitionStoreException {
synchronized (this.mergedBeanDefinitions) {
// 准备一个RootBeanDefinition变量引用,用于记录要构建和最终要返回的BeanDefinition,
// 这里根据上下文不难猜测 mbd 应该就是 mergedBeanDefinition 的缩写。
RootBeanDefinition mbd = null;
// Check with full lock now in order to enforce the same merged instance.
if (containingBd == null) {
mbd = this.mergedBeanDefinitions.get(beanName);
}
if (mbd == null) {
if (bd.getParentName() == null) {
// bd不是一个ChildBeanDefinition的情况,换句话讲,这 bd应该是 :
// 1. 一个独立的 GenericBeanDefinition 实例,parentName 属性为null
// 2. 或者是一个 RootBeanDefinition 实例,parentName 属性为null
// 此时mbd直接使用一个bd的复制品
// Use copy of given root bean definition.
if (bd instanceof RootBeanDefinition) {
mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
}
else {
mbd = new RootBeanDefinition(bd);
}
}
else {
// bd是一个ChildBeanDefinition的情况,
// 这种情况下,需要将bd和其parent bean definition 合并到一起,
// 形成最终的 mbd
// 下面是获取bd的 parent bean definition 的过程,最终结果记录到 pbd,
// 并且可以看到该过程中递归使用了getMergedBeanDefinition(), 为什么呢?
// 因为 bd 的 parent bd 可能也是个ChildBeanDefinition,所以该过程
// 需要递归处理
// Child bean definition: needs to be merged with parent.
BeanDefinition pbd;
try {
String parentBeanName = transformedBeanName(bd.getParentName());
if (!beanName.equals(parentBeanName)) {
pbd = getMergedBeanDefinition(parentBeanName);
}
else {
BeanFactory parent = getParentBeanFactory();
if (parent instanceof ConfigurableBeanFactory) {
pbd = ((ConfigurableBeanFactory)
parent).getMergedBeanDefinition(parentBeanName);
}
else {
throw new NoSuchBeanDefinitionException(parentBeanName,
"Parent name '" + parentBeanName +
"' is equal to bean name '" + beanName +
"': cannot be resolved without an AbstractBeanFactory parent");
}
}
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanDefinitionStoreException(
bd.getResourceDescription(), beanName,
"Could not resolve parent bean definition '" +
bd.getParentName() + "'", ex);
}
// Deep copy with overridden values.
// 现在已经获取 bd 的parent bd到pbd,从上面的过程可以看出,这个pbd
// 也是已经"合并"过的。
// 这里根据pbd创建最终的mbd,然后再使用bd覆盖一次,
// 这样就相当于mbd来自两个BeanDefinition:
// 当前 BeanDefinition 及其合并的("Merged")双亲 BeanDefinition,
// 然后mbd就是针对当前bd的一个MergedBeanDefinition(合并的BeanDefinition)了。
mbd = new RootBeanDefinition(pbd);
mbd.overrideFrom(bd);
}
// Set default singleton scope, if not configured before.
if (!StringUtils.hasLength(mbd.getScope())) {
mbd.setScope(RootBeanDefinition.SCOPE_SINGLETON);
}
// A bean contained in a non-singleton bean cannot be a singleton itself.
// Let's correct this on the fly here, since this might be the result of
// parent-child merging for the outer bean, in which case the original
// inner bean
// definition will not have inherited the merged outer bean's singleton status.
if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
mbd.setScope(containingBd.getScope());
}
// Cache the merged bean definition for the time being
// (it might still get re-merged later on in order to pick up metadata changes)
if (containingBd == null && isCacheBeanMetadata()) {
this.mergedBeanDefinitions.put(beanName, mbd);
}
}
return mbd;
}
}
从上面的MergedBeanDefinition的获取过程可以看出,一个MergedBeanDefinition其实就是一个"合并了的BeanDefinition",最终以RootBeanDefinition的类型存在。
看完MergedBeanDefinition的生成,我们接下来看它的作用。从上面的代码中,我们也可以看到一个MergedBeanDefinition被根据bean名称获取之后,传递到了方法createBean()用于创建bean
MergedBeanDefinition
的应用
下面是类AbstractAutowireCapableBeanFactory中bean创建方法createBean()的实现,可以看到,针对传入的参数RootBeanDefinition mbd,也就是上面生成的MergedBeanDefinition,专门有一个applyMergedBeanDefinitionPostProcessors()调用,这里就是容器中注册的MergedBeanDefinitionPostProcessor的应用阶段 :
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd,
final @Nullable Object[] args) throws BeanCreationException {
// ...
// 创建bean POJO 对象
instanceWrapper = createBeanInstance(beanName, mbd, args);
// ...
// 修改 merged bean definition 的 BeanPostProcessor 的执行
// ==== 调用 MergedBeanDefinitionPostProcessor ====
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
// ...
// 填充 bean 属性:依赖注入处理,属性设置
populateBean(beanName, mbd, instanceWrapper);
// ...
// 初始化 bean : 调用设置的初始化方法,接口定义的初始化方法,
// 以及相应的 pre-/post-init 生命周期回调函数
initializeBean(beanName, exposedObject, mbd);
// ...
// 如果当前 bean 实现类有关销毁时的接口或者函数,将它进行相应的登记
// 供容器关闭时执行相应的回调函数
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
方法applyMergedBeanDefinitionPostProcessors()
的实现如下:
// 找到容器中注册的所有BeanPostProcessor中每一个MergedBeanDefinitionPostProcessor,
// 将它们应用到指定的RootBeanDefinition mbd上,这里 mbd 其实就是一个 MergedBeanDefinition。
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd,
Class<?> beanType, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof MergedBeanDefinitionPostProcessor) {
MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
}
}
}
从上面代码的代码我们只能看到,MergedBeanDefinitionPostProcessor
会被应用到bean
,在它被填充属性之前。不过这还是有点抽象了,我们下面举一个例子,这里的作用就很清楚了:
public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter
implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {
// ...
// 在每个bean实例化后,初始化前执行,获取并记录该bean属性注入的元数据,在随后的属性注入时使用
// 该方法由接口MergedBeanDefinitionPostProcessor定义
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition,
Class<?> beanType, String beanName) {
// 获取指定bean的属性注入元数据
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
// ...
}
上面的代码是Spring框架工具AutowiredAnnotationBeanPostProcessor的实现代码片段,该工具实现了MergedBeanDefinitionPostProcessor,它在一个bean的postProcessMergedBeanDefinition()阶段,如上代码所示,获取该bean的依赖注入元数据(哪些方法使用了@Autowired,@Inject,@Value等等),随后用于该bean属性填充中依赖注入执行阶段的输入。
总结
综上可见,一个MergedBeanDefinition是这样一个载体:
- 根据原始BeanDefinition及其可能存在的双亲BeanDefinition中的bean定义信息"合并"而得来的一个RootBeanDefinition;
- 每个Bean的创建需要的是一个MergedBeanDefinition,也就是需要基于原始BeanDefinition及其双亲BeanDefinition信息得到一个信息"合并"之后的BeanDefinition;
- Spring框架同时提供了一个机会给框架其他部分,或者开发人员用于在bean创建过程中,MergedBeanDefinition生成之后,bean属性填充之前,对该bean和该MergedBeanDefinition做一次回调,相应的回调接口是MergedBeanDefinitionPostProcessor
- MergedBeanDefinition没有相应的Spring建模,它是处于一个内部使用目的合并自其它BeanDefinition对象,其具体对象所使用的实现类类型是RootBeanDefinition。
演示源码
辅助演示使用的bean
类
package tut.zero;
import lombok.Data;
@Data
public class Pet {
String type;
String name;
}
演示BeanDefinition
各个实现类例如何被使用
package tut.zero;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.support.ChildBeanDefinition;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import java.util.Properties;
@Slf4j
@SpringBootApplication
public class Application implements CommandLineRunner {
@Autowired
AnnotationConfigApplicationContext applicationContext;
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Override
public void run(String... args) {
// RootBeanDefinition
demoRootBeanDefinition();
// ChildBeanDefinition
demoChildBeanDefinition();
// GenericBeanDefinition
demoGenericBeanDefinition();
}
private void demoRootBeanDefinition() {
// 此例子演示 RootBeanDefinition 的使用,通过它,提供了创建一个 bean 所需
// 的所有信息
RootBeanDefinition rbd = new RootBeanDefinition();
rbd.setBeanClass(Pet.class);
rbd.getPropertyValues().add("type", "dog");
rbd.getPropertyValues().add("name", "Jack");
applicationContext.registerBeanDefinition("rootPetDog", rbd);
Pet pet = (Pet) applicationContext.getBean("rootPetDog");
log.info("Parent pet dog is :{}", pet);
}
private void demoChildBeanDefinition() {
// 创建一个 ChildBeanDefinition 总是要依赖于另外一个 bean定义,也就是该孩子 bean定义的双亲bean定义
// 此例子演示 ChildBeanDefinition 的使用,该例子中,所创建的 ChildBeanDefinition 使用了上面定义的名
// 为rootPet的 RootBeanDefinition。
// 实际上 ChildBeanDefinition 的双亲parent bean定义的类型不必要是 RootBeanDefinition,也可以是
// ChildBeanDefinition 或者 GenericBeanDefinition
ChildBeanDefinition cbd = new ChildBeanDefinition("rootPetDog");
cbd.getPropertyValues().add("name", "Little Jack");
applicationContext.registerBeanDefinition("childPetDog", cbd);
Object pet = applicationContext.getBean("childPetDog");
log.info("Child pet dog is :{}", pet);
// 从 Spring 2.5 之后,ChildBeanDefinition 被建议使用 GenericBeanDefinition 替换。
// 通过 GenericBeanDefinition 可以动态地设置双亲bean定义。
}
private void demoGenericBeanDefinition() {
// 这里演示 GenericBeanDefinition 的使用
// 基于 GenericBeanDefinition 的双亲bean定义
GenericBeanDefinition rbd = new GenericBeanDefinition();
rbd.setBeanClass(Pet.class);
rbd.getPropertyValues().add("type", "cat");
rbd.getPropertyValues().add("name", "Tom");
applicationContext.registerBeanDefinition("parentPetCat", rbd);
Pet petParent = (Pet) applicationContext.getBean("parentPetCat");
log.info("Parent pet cat is :{}", petParent);
// 基于 GenericBeanDefinition 的孩子bean定义
GenericBeanDefinition cbd = new GenericBeanDefinition();
cbd.setParentName("parentPetCat");
cbd.getPropertyValues().add("name", "Little Tom");
applicationContext.registerBeanDefinition("childPetCat", cbd);
Object petChild = applicationContext.getBean("childPetCat");
log.info("Child pet cat is :{}", petChild);
}
}
演示输出
Parent pet dog is :Pet(type=dog, name=Jack)
Child pet dog is :Pet(type=dog, name=Little Jack)
Parent pet cat is :Pet(type=cat, name=Tom)
Child pet cat is :Pet(type=cat, name=Little Tom)
从该输出可以看出:
- 对于子
bean
定义生成的bean
实例,优先采用子bean
定义中设置的属性,其他继承使用自双亲bean
定义。
转自:https://blog.csdn.net/andy_zhang2007/article/details/85421417