Spring 最重要的bean源信息 : BeanDefinition接口相关解释

本文是笔者阅读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 factorypost process阶段可能会被修改。注意该属性并不总是运行时被对应bean真正使用的类的名称:比如,bean是通过某个类的静态工厂方法生成的,这里是该类的类名,再比如,bean是通过一个工厂bean生成的,那这里为空。
scope 作用域, singleton或者prototype。在bean的作用域尚未决定之前,该属性为null
lazyInit 是否懒加载,仅适用于singleton bean。当一个singleton bean被指定lazyInitfalse时,它会在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。这些类之间的层级关系如下:
Spring 最重要的bean源信息 : BeanDefinition接口相关解释

根据类图看到BeanDefinition有GenericBeanDefinitionChildBeanDefinitionRootBeanDefinition三个实现类;

BeanDefinition是配置文件<bean>元素标签在容器中内部表示形式。

  • RootBeanDefinition可以单独作为一个BeanDefinition,也可以作为其他BeanDefinition的父类。但是他不能作为其他BeanDefinition的子类
  • ChildBeanDefinition相当于一个子类,不可以单独存在,必须要依赖一个父BeanDetintion
  • GenericBeanDefinition 可以替代RootBeanDefinitionChildBeanDefinition
  • 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是怎么生成的 ? 下面是类AbstractBeanFactorybean获取方法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是这样一个载体:

  1. 根据原始BeanDefinition及其可能存在的双亲BeanDefinition中的bean定义信息"合并"而得来的一个RootBeanDefinition;
  2. 每个Bean的创建需要的是一个MergedBeanDefinition,也就是需要基于原始BeanDefinition及其双亲BeanDefinition信息得到一个信息"合并"之后的BeanDefinition;
  3. Spring框架同时提供了一个机会给框架其他部分,或者开发人员用于在bean创建过程中,MergedBeanDefinition生成之后,bean属性填充之前,对该bean和该MergedBeanDefinition做一次回调,相应的回调接口是MergedBeanDefinitionPostProcessor
  4. 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

 

上一篇:Spring 之 FactoryBean 的使用和原因


下一篇:SpringCloud之Ribbon源码解析(三)--@LoadBalanced