spring 源码总结之BeanDefinition

1. BeanDefinition

BeanDefinition字面翻译过来就是"Bean定义",spring容器启动的时候会对每个配置的bean生成一个BeanDefinition,其中包含很多信息,有BeanClassName,Scope,ParentName,LazyInit,DependsOn,AutowireCandidate,Primary,FactoryBeanName,FactoryMethodName,ConstructorArgumentValues,PropertyValues,InitMethodName,DestroyMethodName,Role,Description,ResolvableType,ResourceDescription,OriginatingBeanDefinition,可以说BeanDefinition 接口的方法覆盖了 Spring 构造 Bean 需要的所有信息。具体源码如下

/**
 *  BeanDeifinition bean定义类
 * BeanDeifinition实际上是生成bean之前的中间态   定义的是如何实例化bean这个过程
 */
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
	
	/*BeanDefinition内部定义许多属性,但最常用实际上就下面几个:
	 * 懒加载:该bean是否实现懒加载
	 * 单例/多例:该bean是单例还是多例
	 * 初始化、销毁方法:定义该bean的初始化和销毁方法
	 */
	
	String SCOPE_SINGLETON = "singleton";
	String SCOPE_PROTOTYPE = "prototype";
	int ROLE_APPLICATION = 0;
	int ROLE_SUPPORT = 1;
	int ROLE_INFRASTRUCTURE = 2;
	// Modifiable attributes

	/**
	 * Set the name of the parent definition of this bean definition, if any.
	 */
	void setParentName(@Nullable String parentName);

	/**
	 * Return the name of the parent definition of this bean definition, if any.
	 */
	@Nullable
	String getParentName();

	/**
	 * Specify the bean class name of this bean definition.
	 * <p>The class name can be modified during bean factory post-processing,
	 * typically replacing the original class name with a parsed variant of it.
	 * @see #setParentName
	 * @see #setFactoryBeanName
	 * @see #setFactoryMethodName
	 */
	void setBeanClassName(@Nullable String beanClassName);

	/**
	 * Return the current bean class name of this bean definition.
	 * <p>Note that this does not have to be the actual class name used at runtime, in
	 * case of a child definition overriding/inheriting the class name from its parent.
	 * Also, this may just be the class that a factory method is called on, or it may
	 * even be empty in case of a factory bean reference that a method is called on.
	 * Hence, do <i>not</i> consider this to be the definitive bean type at runtime but
	 * rather only use it for parsing purposes at the individual bean definition level.
	 * @see #getParentName()
	 * @see #getFactoryBeanName()
	 * @see #getFactoryMethodName()
	 */
	@Nullable
	String getBeanClassName();

	/**
	 * Override the target scope of this bean, specifying a new scope name.
	 * @see #SCOPE_SINGLETON
	 * @see #SCOPE_PROTOTYPE
	 */
	void setScope(@Nullable String scope);

	/**
	 * Return the name of the current target scope for this bean,
	 * or {@code null} if not known yet.
	 */
	@Nullable
	String getScope();

	/**
	 * Set whether this bean should be lazily initialized.
	 * <p>If {@code false}, the bean will get instantiated on startup by bean
	 * factories that perform eager initialization of singletons.
	 */
	void setLazyInit(boolean lazyInit);

	/**
	 * Return whether this bean should be lazily initialized, i.e. not
	 * eagerly instantiated on startup. Only applicable to a singleton bean.
	 */
	boolean isLazyInit();

	/**
	 * Set the names of the beans that this bean depends on being initialized.
	 * The bean factory will guarantee that these beans get initialized first.
	 */
	void setDependsOn(@Nullable String... dependsOn);

	/**
	 * Return the bean names that this bean depends on.
	 */
	@Nullable
	String[] getDependsOn();

	/**
	 * Set whether this bean is a candidate for getting autowired into some other bean.
	 * <p>Note that this flag is designed to only affect type-based autowiring.
	 * It does not affect explicit references by name, which will get resolved even
	 * if the specified bean is not marked as an autowire candidate. As a consequence,
	 * autowiring by name will nevertheless inject a bean if the name matches.
	 */
	void setAutowireCandidate(boolean autowireCandidate);

	/**
	 * Return whether this bean is a candidate for getting autowired into some other bean.
	 */
	boolean isAutowireCandidate();

	/**
	 * Set whether this bean is a primary autowire candidate.
	 * <p>If this value is {@code true} for exactly one bean among multiple
	 * matching candidates, it will serve as a tie-breaker.
	 */
	void setPrimary(boolean primary);

	/**
	 * Return whether this bean is a primary autowire candidate.
	 */
	boolean isPrimary();

	/**
	 * Specify the factory bean to use, if any.
	 * This the name of the bean to call the specified factory method on.
	 * @see #setFactoryMethodName
	 */
	void setFactoryBeanName(@Nullable String factoryBeanName);

	/**
	 * Return the factory bean name, if any.
	 */
	@Nullable
	String getFactoryBeanName();

	/**
	 * Specify a factory method, if any. This method will be invoked with
	 * constructor arguments, or with no arguments if none are specified.
	 * The method will be invoked on the specified factory bean, if any,
	 * or otherwise as a static method on the local bean class.
	 * @see #setFactoryBeanName
	 * @see #setBeanClassName
	 */
	void setFactoryMethodName(@Nullable String factoryMethodName);

	/**
	 * Return a factory method, if any.
	 */
	@Nullable
	String getFactoryMethodName();

	/**
	 * Return the constructor argument values for this bean.
	 * <p>The returned instance can be modified during bean factory post-processing.
	 * @return the ConstructorArgumentValues object (never {@code null})
	 */
	ConstructorArgumentValues getConstructorArgumentValues();

	/**
	 * Return if there are constructor argument values defined for this bean.
	 * @since 5.0.2
	 */
	default boolean hasConstructorArgumentValues() {
		return !getConstructorArgumentValues().isEmpty();
	}

	/**
	 * Return the property values to be applied to a new instance of the bean.
	 * <p>The returned instance can be modified during bean factory post-processing.
	 * @return the MutablePropertyValues object (never {@code null})
	 */
	MutablePropertyValues getPropertyValues();

	/**
	 * Return if there are property values values defined for this bean.
	 * @since 5.0.2
	 */
	default boolean hasPropertyValues() {
		return !getPropertyValues().isEmpty();
	}

	/**
	 * Set the name of the initializer method.
	 * @since 5.1
	 */
	void setInitMethodName(@Nullable String initMethodName);

	/**
	 * Return the name of the initializer method.
	 * @since 5.1
	 */
	@Nullable
	String getInitMethodName();

	/**
	 * Set the name of the destroy method.
	 * @since 5.1
	 */
	void setDestroyMethodName(@Nullable String destroyMethodName);

	/**
	 * Return the name of the destroy method.
	 * @since 5.1
	 */
	@Nullable
	String getDestroyMethodName();

	/**
	 * Set the role hint for this {@code BeanDefinition}. The role hint
	 * provides the frameworks as well as tools with an indication of
	 * the role and importance of a particular {@code BeanDefinition}.
	 * @since 5.1
	 * @see #ROLE_APPLICATION
	 * @see #ROLE_SUPPORT
	 * @see #ROLE_INFRASTRUCTURE
	 */
	void setRole(int role);

	/**
	 * Get the role hint for this {@code BeanDefinition}. The role hint
	 * provides the frameworks as well as tools with an indication of
	 * the role and importance of a particular {@code BeanDefinition}.
	 * @see #ROLE_APPLICATION
	 * @see #ROLE_SUPPORT
	 * @see #ROLE_INFRASTRUCTURE
	 */
	int getRole();

	/**
	 * Set a human-readable description of this bean definition.
	 * @since 5.1
	 */
	void setDescription(@Nullable String description);

	/**
	 * Return a human-readable description of this bean definition.
	 */
	@Nullable
	String getDescription();


	// Read-only attributes

	/**
	 * Return a resolvable type for this bean definition,
	 * based on the bean class or other specific metadata.
	 * <p>This is typically fully resolved on a runtime-merged bean definition
	 * but not necessarily on a configuration-time definition instance.
	 * @return the resolvable type (potentially {@link ResolvableType#NONE})
	 * @since 5.2
	 * @see ConfigurableBeanFactory#getMergedBeanDefinition
	 */
	ResolvableType getResolvableType();

	/**
	 * 是否单例
	 */
	boolean isSingleton();

	/**
	 * 是否原型
	 */
	boolean isPrototype();

	/**
	 * 是否抽象
	 */
	boolean isAbstract();

	/**
	 * Return a description of the resource that this bean definition
	 * came from (for the purpose of showing context in case of errors).
	 */
	@Nullable
	String getResourceDescription();

	/**
	 * Return the originating BeanDefinition, or {@code null} if none.
	 * Allows for retrieving the decorated bean definition, if any.
	 * <p>Note that this method returns the immediate originator. Iterate through the
	 * originator chain to find the original BeanDefinition as defined by the user.
	 */
	@Nullable
	BeanDefinition getOriginatingBeanDefinition();

}

2.AttributeAccessor与BeanMetadataElement

这两个接口都被BeanDefinition继承,看一下其源码如下

AttributeAccessor

/**
 * 定义用于附加和访问元数据的通用的接口
 */
public interface AttributeAccessor {

	/** 设置属性的值 */
	void setAttribute(String name, @Nullable Object value);

	/** 获得指定属性名称的值 */
	@Nullable
	Object getAttribute(String name);

	/** 删除指定的name的属性 */
	@Nullable
	Object removeAttribute(String name);

	/** 判断指定的属性名称是否存在,注意属性名称必须是唯一的 */
	boolean hasAttribute(String name);

	/** 得到所有属性的名称 */
	String[] attributeNames();
}

BeanMetadataElement

/**
 * 用于传送配置源对象的超级接口
 */
public interface BeanMetadataElement {

	/**
	 * 获取源对象,可能返回null
	 */
	@Nullable
	default Object getSource() {
		return null;
	}

}

3.BeanDefinition的子类以及实现

先上一张图,看看BeanDefinition有哪些子类以及实现。

 其中

AbstractBeanDefinition是抽象类,

AnnotatedBeanDefinition是接口,

AnnotatedGenericBeanDefinition,ChildBeanDefinition,ConfigurationPropertiesValueObjectBeanDefinition,GenericBeanDefinition,RootBeanDefinition,ScannedGenericBeanDefinition是实现类,其中的ConfigurationPropertiesValueObjectBeanDefinition是对外不可见且是final类型的

ClassDerivedBeanDefinition是实现类,是定义在GenericApplicationContext类中的一个静态内部类,

ConfigurationClassBeanDefinition是实现类,是定义在ConfigurationClassBeanDefinitionReader类中的一个静态内部类

3.1常用的BeanDefinition实现类

AnnotatedGenericBeanDefinition,GenericBeanDefinition,ChildBeanDefinition,RootBeanDefinition,ScannedGenericBeanDefinition这几个

其中AnnotatedGenericBeanDefinition与ScannedGenericBeanDefinition都继承自GenericBeanDefinition而且其中并未重写BeanDefinition相关的方法,这里也不再介绍

RootBeanDefinition、ChildBeanDefinition

RootBeanDefinition可以单独作为一个BeanDefinition,也可以作为其他BeanDefinition的父类,但是他不能作为其他BeanDefinition的子类。

ChildBeanDefinition相当于一个子类,不可以单独存在,必须要依赖一个父BeanDetintion。

RootBeanDefinition中无法设置ParentName,该方法会直接抛出异常,而获取ParentName也会直接返回null,其源码如下:

	@Override
	public String getParentName() {
		return null;
	}

	@Override
	public void setParentName(@Nullable String parentName) {
		if (parentName != null) {
			throw new IllegalArgumentException("Root bean cannot be changed into a child bean with parent reference");
		}
	}

ChildBeanDefinition必须依赖一个父BeanDetintion,其构造方法必须指定ParentName,源码如下:

	@Nullable
	private String parentName;


	/**
	 * Create a new ChildBeanDefinition for the given parent, to be
	 * configured through its bean properties and configuration methods.
	 * @param parentName the name of the parent bean
	 * @see #setBeanClass
	 * @see #setScope
	 * @see #setConstructorArgumentValues
	 * @see #setPropertyValues
	 */
	public ChildBeanDefinition(String parentName) {
		super();
		this.parentName = parentName;
	}

	/**
	 * Create a new ChildBeanDefinition for the given parent.
	 * @param parentName the name of the parent bean
	 * @param pvs the additional property values of the child
	 */
	public ChildBeanDefinition(String parentName, MutablePropertyValues pvs) {
		super(null, pvs);
		this.parentName = parentName;
	}

	/**
	 * Create a new ChildBeanDefinition for the given parent.
	 * @param parentName the name of the parent bean
	 * @param cargs the constructor argument values to apply
	 * @param pvs the additional property values of the child
	 */
	public ChildBeanDefinition(
			String parentName, ConstructorArgumentValues cargs, MutablePropertyValues pvs) {

		super(cargs, pvs);
		this.parentName = parentName;
	}

	/**
	 * Create a new ChildBeanDefinition for the given parent,
	 * providing constructor arguments and property values.
	 * @param parentName the name of the parent bean
	 * @param beanClass the class of the bean to instantiate
	 * @param cargs the constructor argument values to apply
	 * @param pvs the property values to apply
	 */
	public ChildBeanDefinition(
			String parentName, Class<?> beanClass, ConstructorArgumentValues cargs, MutablePropertyValues pvs) {

		super(cargs, pvs);
		this.parentName = parentName;
		setBeanClass(beanClass);
	}

	/**
	 * Create a new ChildBeanDefinition for the given parent,
	 * providing constructor arguments and property values.
	 * Takes a bean class name to avoid eager loading of the bean class.
	 * @param parentName the name of the parent bean
	 * @param beanClassName the name of the class to instantiate
	 * @param cargs the constructor argument values to apply
	 * @param pvs the property values to apply
	 */
	public ChildBeanDefinition(
			String parentName, String beanClassName, ConstructorArgumentValues cargs, MutablePropertyValues pvs) {

		super(cargs, pvs);
		this.parentName = parentName;
		setBeanClassName(beanClassName);
	}

	/**
	 * Create a new ChildBeanDefinition as deep copy of the given
	 * bean definition.
	 * @param original the original bean definition to copy from
	 */
	public ChildBeanDefinition(ChildBeanDefinition original) {
		super(original);
	}

GenericBeanDefinition

GenericBeanDefinition是用于标准bean定义的一站式服务。与其他bean定义一样,它允许指定一个类加上optionallyconstructor参数值和属性值。此外,可以通过“parentName”属性灵活地配置从父bean定义派生的内容。一般来说,使用GenericBeanDefinition来注册用户可见bean定义(后处理程序可能会对其进行操作,甚至可能重新配置父名称)。使用RootBeanDefinition/ ChildBeanDefinition,其中父/子关系恰好是预先确定的。

AnnotatedBeanDefinition

这是一个BeanDefinition的子接口,其定义如下:

/**
 * AnnotatedBeanDefinition是BeanDefinition的子接口,在Definition定义了bean的一些基本属性的基础上定义方法
 * 	--MetaData称为元数据,指的是数据的数据,包括类名,方法名,注释名等等
 */
public interface AnnotatedBeanDefinition extends BeanDefinition {

	AnnotationMetadata getMetadata();
	@Nullable
	MethodMetadata getFactoryMethodMetadata();
}

猜你喜欢

转载自blog.csdn.net/luo_mu_hpu/article/details/108234596