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();
}