前言
spring容器 中一个非常重要的概念: BeanDeFinition
注:本文springboot、spring版本如下图
spring容器的强大之处:获取对象时,不需要我们手工主动new对象,完全交给spring容器管理。
Spring 将管理的对象称之为 Bean,容器会先实例化 Bean,然后自动注入,实例化的过程就需要依赖 BeanDeFinition。
BeanDeFinition 用于保存 Bean 的相关信息,包括属性、构造方法参数、依赖的 Bean 名称及是否单例、延迟加载等,它是实例化 Bean 的原材料,Spring 就是根据 BeanDeFinition 中的信息实例化 Bean。
BeanDeFinition对象详解
BeanDeFinition是一个接口类,实现类以及子接口很多,如下:
BeanDeFinition 用于保存 Bean 的相关信息,包括属性、构造方法参数、依赖的 Bean 名称及是否单例、延迟加载等,详细核心内容如下:
/**
BeanDeFinition描述了一个bean实例,它有属性值,
构造函数参数值,以及提供的进一步信息
具体实现。
这只是一个最小的接口:主要目的是允许一个
{@link beanfactoryPostProcessor}来自省和修改属性值
和其他bean元数据。
* @see ConfigurableListablebeanfactory#getBeanDeFinition * @see org.springframework.beans.factory.support.RootBeanDeFinition * @see org.springframework.beans.factory.support.ChildBeanDeFinition */ public interface BeanDeFinition extends AttributeAccessor, BeanMetadataElement { /** * 标准单例、原型模式标识符 * @see #setScope * @see Configurablebeanfactory#ScopE_SINGLetoN */ String ScopE_SINGLetoN = Configurablebeanfactory.ScopE_SINGLetoN; String ScopE_PROTOTYPE = Configurablebeanfactory.ScopE_PROTOTYPE; /** * 标识Bean的类别 0-用户定义的Bean 1-来源于配置文件的Bean 2-Spring内部的Bean*/ int ROLE_APPLICATION = 0; int ROLE_SUPPORT = 1; int ROLE_INFRASTRUCTURE = 2; // Modifiable attributes /** * 设置、返回父类名称 */ void setParentName(@Nullable String parentName); String getParentName(); /** * 设置、返回 className * @see #setParentName * @see #setfactorybeanName * @see #setFactoryMethodName */ void setBeanClassName(@Nullable String beanClassName); String getBeanClassName(); /** * 设置、返回作用域 * @see #ScopE_SINGLetoN * @see #ScopE_PROTOTYPE */ void setScope(@Nullable String scope); String getScope(); /** * 设置、返回 是否懒加载*/ void setLazyInit(boolean lazyInit); boolean isLazyInit(); /** * 设置、返回当前Bean对象所依赖的其他Bean名称 */ void setDependsOn(@Nullable String... dependsOn); String[] getDependsOn(); /** *设置、返回是否可以自动注入,对应@Autowired 注解 */ void setAutowireCandidate(boolean autowireCandidate); boolean isAutowireCandidate(); /** * 设置、返回当前Bean 是否为主要候选Bean 一个接口多个实例对象,可以通过此属性来设置指定具体实例对象*/ void setPrimary(boolean primary); boolean isPrimary(); /** * 设置、返回Bean的工长类*/ void setfactorybeanName(@Nullable String factorybeanName); String getfactorybeanName(); /** * 工厂方法 * @see #setfactorybeanName * @see #setBeanClassName */ void setFactoryMethodName(@Nullable String factoryMethodName); String getFactoryMethodName(); /** *返回构造参数值、属性值*/ constructorargumentValues getconstructorargumentValues(); default boolean hasconstructorargumentValues() { return !getconstructorargumentValues().isEmpty(); } MutablePropertyValues getPropertyValues(); default boolean hasPropertyValues() { return !getPropertyValues().isEmpty(); } /** * 初始化方法名称*/ void setinitMethodName(@Nullable String initMethodName); String getinitMethodName(); /** * 销毁方法的名称*/ void setDestroyMethodName(@Nullable String destroyMethodName); String getDestroyMethodName(); /** * Bean的类别 * @see #ROLE_APPLICATION * @see #ROLE_SUPPORT * @see #ROLE_INFRASTRUCTURE */ void setRole(int role); int getRole(); ........ 此处省略其他源码 }
AnnotatedBeanDeFinition
AnnotatedBeanDeFinition 是 BeanDeFinition 子接口之一,该接口扩展了 BeanDeFinition 的功能,其用来操作注解元数据。一般情况下,通过注解方式得到的 Bean(@Component、@Bean)。
public interface AnnotatedBeanDeFinition extends BeanDeFinition { // 获得当前 Bean 的注解元数据 AnnotationMetadata getMetadata(); // 获得当前 Bean 的工厂方法上的元数据 MethodMetadata getFactoryMethodMetadata(); }
该接口可以返回两个元数据的类:
-
AnnotationMetadata:主要对 Bean 的注解信息进行操作,如:获取当前 Bean 标注的所有注解、判断是否包含指定注解。
-
MethodMetadata:方法的元数据类。提供获取方法名称、此方法所属类的全类名、是否是抽象方法、判断是否是静态方法、判断是否是final方法等。
AbstractBeanDeFinition
AbstractBeanDeFinition 是 BeanDeFinition 的子抽象类,也是其他 BeanDeFinition 类型的基类,其实现了接口中定义的一系列操作方法,并定义了一系列的常量属性,这些常量会直接影响到 Spring 实例化 Bean 时的策略。核心属性如下。
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 中定义的一些常量和属性,该类中还有一部分是操作这些属性的 set 和 get 方法,这些方法都由子类来操作,且应用程序中真正使用的也是这些子类 BeanDeFinition。
先来看 AbstractBeanDeFinition 直接实现类:RootBeanDeFinition、GenericBeanDeFinition、ChildBeanDeFinition。
RootBeanDeFinition
该类继承自 AbstractBeanDeFinition,它可以单独作为一个 BeanDeFinition,也可以作为其他 BeanDeFinition 的父类。
RootBeanDeFinition 在 AbstractBeanDeFinition 的基础上定义了更多属性。
public class RootBeanDeFinition extends AbstractBeanDeFinition { // BeanDeFinitionHolder 存储 Bean 的名称、别名、BeanDeFinition private BeanDeFinitionHolder decoratedDeFinition; // AnnotatedElement 是java反射包的接口,通过它可以查看 Bean 的注解信息 private AnnotatedElement qualifiedElement; // 允许缓存 boolean allowCaching = true; // 工厂方法是否唯一 boolean isFactoryMethodUnique = false; // 封装了 java.lang.reflect.Type,提供了泛型相关的操作 volatile ResolvableType targettype; // 缓存 Class,表示 RootBeanDeFinition 存储哪个类的信息 volatile Class<?> resolvedtargettype; // 缓存工厂方法的返回类型 volatile ResolvableType factoryMethodReturnType; // 这是以下四个构造方法字段的通用锁 final Object constructorargumentLock = new Object(); // 用于缓存已解析的构造方法或工厂方法 Executable resolvedConstructorOrFactoryMethod; // 将构造方法参数标记为已解析 boolean constructorargumentsResolved = false; // 用于缓存完全解析的构造方法参数 Object[] resolvedconstructorarguments; // 缓存待解析的构造方法参数 Object[] preparedconstructorarguments; // 这是以下两个后处理字段的通用锁 final Object postProcessingLock = new Object(); // 表明是否被 MergedBeanDeFinitionPostProcessor 处理过 boolean postProcessed = false; // 在生成代理的时候会使用,表明是否已经生成代理 volatile Boolean beforeInstantiationResolved; // 实际缓存的类型是 Constructor、Field、Method 类型 private Set<Member> externallyManagedConfigMembers; // InitializingBean中 的 init 回调函数名 afterPropertiesSet 会在这里记录,以便进行生命周期回调 private Set<String> externallyManagedInitMethods; // disposableBean 的 destroy 回调函数名 destroy 会在这里记录,以便进生命周期回调 private Set<String> externallyManagedDestroyMethods; ...... }
ChildBeanDeFinition
该类继承自 AbstractBeanDeFinition。其相当于一个子类,不可以单独存在,必须依赖一个父 BeanDetintion,构造 ChildBeanDeFinition 时,通过构造方法传入父 BeanDetintion 的名称或通过 setParentName 设置父名称。它可以从父类继承方法参数、属性值,并可以重写父类的方法,同时也可以增加新的属性或者方法。若重新定义 init 方法,destroy 方法或者静态工厂方法,ChildBeanDeFinition 会重写父类的设置。
从 Spring 2.5 开始,以编程方式注册 Bean 定义的首选方法是 GenericBeanDeFinition,GenericBeanDeFinition 可以有效替代 ChildBeanDeFinition 的绝大分部使用场合。@H_404_94@GenericBeanDeFinition
GenericBeanDeFinition 是 Spring 2.5 以后新引入的 BeanDeFinition,是 ChildBeanDeFinition 更好的替代者,它同样可以通过 setParentName 方法设置父 BeanDeFinition。
最后三个 BeanDeFinition 既实现了 AnnotatedBeanDeFinition 接口,又间接继承 AbstractBeanDeFinition 抽象类,这些 BeanDeFinition 描述的都是注解形式的 Bean。
ConfigurationClassBeanDeFinition
该类继承自 RootBeanDeFinition ,并实现了 AnnotatedBeanDeFinition 接口。这个 BeanDeFinition 用来描述在标注 @Configuration 注解的类中,通过 @Bean 注解实例化的 Bean。
其功能特点如下:
1、如果 @Bean 注解没有指定 Bean 的名字,默认会用方法的名字命名 Bean。
2、标注 @Configuration 注解的类会成为一个工厂类,而标注 @Bean 注解的方法会成为工厂方法,通过工厂方法实例化 Bean,而不是直接通过构造方法初始化。
AnnotatedGenericBeanDeFinition
该类继承自 GenericBeanDeFinition ,并实现了 AnnotatedBeanDeFinition 接口。这个 BeanDeFinition 用来描述标注 @Configuration 注解的 Bean。
ScannedGenericBeanDeFinition
该类继承自 GenericBeanDeFinition ,并实现了 AnnotatedBeanDeFinition 接口。这个 BeanDeFinition 用来描述标注 @Component 注解的 Bean,其派生注解如 @Service、@Controller 也同理。
总结
BeanDeFinition 主要是用来描述 Bean,其存储了 Bean 的相关信息,Spring 实例化 Bean 时需读取该 Bean 对应的 BeanDeFinition。BeanDeFinition 整体可以分为两类,一类是描述通用的 Bean,还有一类是描述注解形式的 Bean。一般前者在 XML 时期定义 <bean‘> 标签以及在 Spring 内部使用较多,而现今我们大都使用后者,通过注解形式加载 Bean。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。