0
点赞
收藏
分享

微信扫一扫

Spring Framework 源码阅读(二):BeanDefinition的作用


Spring Framework 源码阅读(二):BeanDefinition的作用

上一篇​​Spring Framework​​​源码阅读博客,博主介绍了​​Aware​​​接口及其实现类的作用,​​Aware​​​的设计模式是模板模式,而​​BeanDefinition​​的设计模式也是模板模式,它们都基于某种职责定义了一个模板,符合开闭原则,对扩展开放,对修改关闭,扩展在子类中实现。

  • ​​Spring Framework 源码阅读(一):Aware接口及其实现类的作用​​
  • ​​设计模式-模板模式(Template Pattern)​​
  • ​​设计模式的七大原则​​

​BeanDefinition​​接口的定义

package org.springframework.beans.factory.config;

import org.springframework.beans.BeanMetadataElement;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.core.AttributeAccessor;
import org.springframework.core.ResolvableType;
import org.springframework.lang.Nullable;

/**
* A BeanDefinition describes a bean instance, which has property values,
* constructor argument values, and further information supplied by
* concrete implementations.
* * <p>This is just a minimal interface: The main intention is to allow a
* {@link BeanFactoryPostProcessor} to introspect and modify property values
* and other bean metadata.
* * @author Juergen Hoeller
* @author Rob Harrop
* @since 19.03.2004
* @see ConfigurableListableBeanFactory#getBeanDefinition
* @see org.springframework.beans.factory.support.RootBeanDefinition
* @see org.springframework.beans.factory.support.ChildBeanDefinition
*/
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
...
}

  • ​BeanDefinition​​​描述​​bean​​​实例,比如​​bean​​实例具有的属性值、构造函数参数值以及由具体实现提供的进一步信息。
  • 主要目的是允许​​BeanFactoryPostProcessor​​​检查和修改属性值以及其他​​bean​​​元数据,​​BeanFactoryPostProcessor​​博主以后会进行介绍,不然会涉及到很多其他知识,显得杂乱无章,要尽量遵守单一职责原则。

为什么需要​​BeanDefinition​​​?这就要讨论​​Java​​​对象和​​bean​​​有什么不同,很显然​​bean​​​也是​​Java​​​对象,但它拥有​​Java​​​对象所没有的功能,它可以在​​Spring​​​容器中很容易实现自动注入、懒加载、多种作用域和根据各种限定条件进行初始化等,​​Java​​​中的类可以描述该类实例的属性和行为,因此​​bean​​​也需要有描述它附加功能的定义,不然它只是一个​​Java​​​对象而已,这就是​​BeanDefinition​​的作用,从接口的命名也可看出来。

​BeanDefinition​​接口的方法和属性:

Spring Framework 源码阅读(二):BeanDefinition的作用_自动装配


属性

  • ​SCOPE_SINGLETON​​​:​​bean​​​的单例作用域,把​​bean​​​设置为单例作用域时,​​Spring​​​容器只会创建该​​bean​​​的唯一实例。这个单一实例会被存储到单例缓存(​​singleton cache​​​)中,并且所有针对该​​bean​​的后续请求和引用都将返回被缓存的对象实例。
  • ​SCOPE_PROTOTYPE​​​:​​bean​​​的原型作用域,把​​bean​​​设置为原型作用域时,每次对​​bean​​​的请求(将其注入到另一个​​bean​​​中,或者以程序的方式调用容器的​​getBean()​​​方法)时​​Spring​​​容器都会创建一个新的​​bean​​​实例。​​bean​​​的其他作用域(​​request​​​、​​session​​​、​​globalSession​​​)需要在​​Web​​环境中才能使用,以后博主再进行详细介绍。
  • ​ROLE_APPLICATION​​​:​​bean​​​的角色指示,指示该​​BeanDefinition​​​是应用程序的主要部分。通常对应于用户定义的​​bean​​。
  • ​ROLE_SUPPORT​​​:​​bean​​​的角色指示,指示该​​BeanDefinition​​​是某些配置(通常是外部的​​ComponentDefinition​​)的支撑部分。
  • ​ROLE_INFRASTRUCTURE​​​:​​bean​​​的角色指示,指示该​​BeanDefinition​​完全提供后台角色,与终端用户无关。

方法

  • ​setParentName​​​、​​getParentName​​​:设置和获取父​​BeanDefinition​​​名称的方法,为了描述​​bean​​​之间的继承关系,​​BeanDefinition​​​也有父子关系,之后会介绍到合并​​BeanDefinition​​的概念。
  • ​setBeanClassName​​​、​​getBeanClassName​​​:设置和获取​​bean​​的类名。
  • ​setScope​​​、​​getScope​​​:设置和获取​​bean​​的作用域。
  • ​setLazyInit​​​、​​isLazyInit​​​:设置​​bean​​​为懒加载、判断​​bean​​是否为懒加载。
  • ​setDependsOn​​​、​​getDependsOn​​​:设置和获取​​bean​​​所依赖的​​bean​​​的名称数组(保证首先初始化这些​​bean​​)。
  • ​setAutowireCandidate​​​、​​isAutowireCandidate​​​:​​AutowireCandidate​​​表示​​bean​​​是否是自动注入到其他​​bean​​​的候选。仅影响基于类型(​​byType​​​)的自动注入。它不会影响按名称(​​byName​​​)的显式引用,即使指定的​​bean​​​未标记为​​autowire​​​候选,也会解析为显式引用。因此,如果名称匹配,会按名称自动注入​​bean​​。
  • ​setPrimary​​​、​​isPrimary​​​:设置和判断​​bean​​​是否是自动注入到其他​​bean​​的首选。
  • ​setFactoryBeanName​​​、​​getFactoryBeanName​​​:​​FactoryBean​​​和​​BeanFactory​​​是不一样的概念,​​FactoryBean​​​也是​​bean​​​,不过它可以用于创建某一类型的​​bean​​​(所有是一个​​factory​​​,也是一个​​bean​​​),因此借助​​FactoryBean​​​可以定制化创建​​bean​​​的过程。这两个方法就是设置和获取​​bean​​​的​​FactoryBeanName​​​(可以为​​null​​)。
  • ​setFactoryMethodName​​​、​​getFactoryMethodName​​​:​​FactoryBean​​​通过​​FactoryMethod​​​来创建某一类型的​​bean​​​。这两个方法就是设置和获取​​bean​​​的​​FactoryMethod​​​(可以为​​null​​)。
  • ​getConstructorArgumentValues​​​、​​hasConstructorArgumentValues​​​:获取​​bean​​​的构造器参数值、判断​​bean​​是否有构造器参数值。
  • ​getPropertyValues​​​、​​hasPropertyValues​​​:获取要应用于​​bean​​​的新实例的属性值、判断是否有要应用于​​bean​​的新实例的属性值。
  • ​setInitMethodName​​​、​​getInitMethodName​​​:设置和获取​​bean​​初始化方法的名称。
  • ​setDestroyMethodName​​​、​​getDestroyMethodName​​​:设置和获取​​bean​​销毁方法的名称。
  • ​setRole​​​、​​getRole​​​:设置和获取​​bean​​的角色。
  • ​setDescription​​​、​​getDescription​​​:设置和获取​​BeanDefinition​​​的​​human-readable description​​(便于人类阅读的描述)。
  • ​getResolvableType​​​:基于​​BeanDefinition​​​或其他特定元数据,返回该​​BeanDefinition​​​的可解析类型。这通常在运行时合并的​​BeanDefinition​​(下面会进行介绍)上完全解析,但不一定在配置时定义的实例上完全解析。
  • ​isSingleton​​​、​​isPrototype​​​:判断​​bean​​​是否是单例、原型​​bean​​。
  • ​isAbstract​​​:判断​​bean​​​是否是​​abstract​​​,如果是​​abstract​​就不需要实例化了。
  • ​getResourceDescription​​​:获取​​BeanDefinition​​​来自的​​Resource​​的描述(用于在出现错误时显示上下文)。
  • ​getOriginatingBeanDefinition​​​:返回原始的​​BeanDefinition​​​,如果没有,则返回​​null​​。

​BeanDefinition​​​接口还继承了​​AttributeAccessor​​​接口和​​BeanMetadataElement​​接口。

Spring Framework 源码阅读(二):BeanDefinition的作用_java_02

  • ​AttributeAccessor​​接口:定义了通用的接口,用于向任意对象附加元数据或从任意对象访问元数据。
  • ​BeanMetadataElement​​​接口:由携带配置源对象的​​bean​​元数据元素实现的接口。

使用这些定义来描述​​bean​​​实例,而具体实现下放到子类中,比如​​AbstractBeanDefinition​​​、​​ChildBeanDefinition​​​、​​RootBeanDefinition​​​以及​​GenericBeanDefinition​​,接下来博主会详细介绍它们的作用。

AbstractBeanDefinition

之前介绍过​​BeanDefinition​​​的设计模式是模板模式,​​AbstractBeanDefinition​​​抽象类实现了​​BeanDefinition​​接口中的通用方法。

@SuppressWarnings("serial")
public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor
implements BeanDefinition, Cloneable {
...
}

​AbstractBeanDefinition​​​是具体、完备的​​BeanDefinition​​​基类,并且分解出了​​GenericBeanDefinition​​​、​​RootBeanDefinition​​​和​​ChildBeanDefinition​​的公共属性。

Spring Framework 源码阅读(二):BeanDefinition的作用_java_03

通用方法的实现:

/**
* 指定bean定义的bean类名
*/
@Override
public void setBeanClassName(@Nullable String beanClassName) {
this.beanClass = beanClassName;
}

/**
* 返回bean定义的bean类名
*/
@Override
@Nullable
public String getBeanClassName() {
Object beanClassObject = this.beanClass;
if (beanClassObject instanceof Class) {
return ((Class<?>) beanClassObject).getName();
}
else {
return (String) beanClassObject;
}
}

/**
* 设置bean的作用域
*/
@Override
public void setScope(@Nullable String scope) {
this.scope = scope;
}

/**
* 返回bean的作用域名称
*/
@Override
@Nullable
public String getScope() {
return this.scope;
}

/**
* 是否是单例bean
*/
@Override
public boolean isSingleton() {
return SCOPE_SINGLETON.equals(this.scope) || SCOPE_DEFAULT.equals(this.scope);
}

/**
*是否是原型bean
*/
@Override
public boolean isPrototype() {
return SCOPE_PROTOTYPE.equals(this.scope);
}

/**
* 是否是abstract,如果是就不会进行实例化
*/
@Override
public boolean isAbstract() {
return this.abstractFlag;
}

/**
* 设置bean的加载方式为懒加载
*/
@Override
public void setLazyInit(boolean lazyInit) {
this.lazyInit = lazyInit;
}

/**
* 判断bean是否设置懒加载
*/
@Override
public boolean isLazyInit() {
return (this.lazyInit != null && this.lazyInit.booleanValue());
}
...

也添加了新的属性和方法,涉及到​​autowire​​​(装配​​bean​​的属性):

/**
* 表示没有自动装配的常量
*/
public static final int AUTOWIRE_NO = AutowireCapableBeanFactory.AUTOWIRE_NO;

/**
* 表示按名称自动装配bean属性的常量
*/
public static final int AUTOWIRE_BY_NAME = AutowireCapableBeanFactory.AUTOWIRE_BY_NAME;

/**
* 表示按类型自动装配bean属性的常量
*/
public static final int AUTOWIRE_BY_TYPE = AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE;

/**
* 表示通过构造函数自动装配bean属性的常量
*/
public static final int AUTOWIRE_CONSTRUCTOR = AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR;

/**
* 表示通过bean类的内部检测来确定适当的自动装配策略的常量
*/
@Deprecated
public static final int AUTOWIRE_AUTODETECT = AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT;

/**
* 设置自动装配模式
*/
public void setAutowireMode(int autowireMode) {
this.autowireMode = autowireMode;
}

/**
* 返回自动装配模式
*/
public int getAutowireMode() {
return this.autowireMode;
}

/**
* 返回已解析的自动装配模式编码
*/
public int getResolvedAutowireMode() {
if (this.autowireMode == AUTOWIRE_AUTODETECT) {
// 确定是应用setter自动装配还是构造函数自动装配
// 如果它有一个无参数构造函数,则被视为setter自动装配
// 否则将尝试构造函数自动装配
Constructor<?>[] constructors = getBeanClass().getConstructors();
for (Constructor<?> constructor : constructors) {
if (constructor.getParameterCount() == 0) {
return AUTOWIRE_BY_TYPE;
}
}
return AUTOWIRE_CONSTRUCTOR;
}
else {
return this.autowireMode;
}
}
...

涉及到​​dependency check​​(依赖项检查):

/**
* 表示没有依赖项检查的常量
*/
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;

...

/**
* 设置依赖项检查的编码,就是上面的0、1、2以及3
*/
public void setDependencyCheck(int dependencyCheck) {
this.dependencyCheck = dependencyCheck;
}

/**
* 返回当前依赖项检查的编码
*/
public int getDependencyCheck() {
return this.dependencyCheck;
}

涉及到​​qualifier​​(限定符):

/**
* 注册一个用于autowire候选解析的限定符。
*/
public void addQualifier(AutowireCandidateQualifier qualifier) {
this.qualifiers.put(qualifier.getTypeName(), qualifier);
}

/**
* 返回bean是否具有指定的限定符
*/
public boolean hasQualifier(String typeName) {
return this.qualifiers.containsKey(typeName);
}

/**
* 返回映射到提供的类型名称的限定符
*/
@Nullable
public AutowireCandidateQualifier getQualifier(String typeName) {
return this.qualifiers.get(typeName);
}

/**
* 返回所有的限定符。
*/
public Set<AutowireCandidateQualifier> getQualifiers() {
return new LinkedHashSet<>(this.qualifiers.values());
}

/**
* 将限定符从提供的AbstractBeanDefinition复制到此AbstractBeanDefinition
*/
public void copyQualifiersFrom(AbstractBeanDefinition source) {
Assert.notNull(source, "Source must not be null");
this.qualifiers.putAll(source.qualifiers);
}

这些都是​​AbstractBeanDefinition​​​中新增加的内容(基于特定业务的抽象),当然这些还不是​​AbstractBeanDefinition​​​的全貌,大家可以自己去探索一下。接下来会介绍​​AbstractBeanDefinition​​​三个比较重要的子类​​ChildBeanDefinition​​​、​​RootBeanDefinition​​​以及​​GenericBeanDefinition​​。

ChildBeanDefinition

子​​Bean​​​(继承了父​​Bean​​​)的​​BeanDefinition​​​。子​​BeanDefinition​​​对父​​BeanDefinition​​有固定的依赖关系。

子​​BeanDefinition​​​将从父​​BeanDefinition​​​继承构造函数参数值、属性值和方法重写,并具有添加新值的选项。如果指定了​​init method​​​、​​destroy method​​​或​​static factory method​​​,它们将覆盖相应父​​BeanDefinition​​​的设置。其余设置将始终取自子​​BeanDefinition​​​:​​depends on​​​、​​autowire mode​​​、​​dependency check​​​、​​singleton​​​以及​​lazy init​​。

自​​Spring2.5​​​以来,以编程方式注册​​BeanDefinition​​​的首选方法是​​GenericBeanDefinition​​​类,它允许通过​​setParentName​​​方法动态定义父依赖项。对于大多数用例,这有效地取代了​​ChildBeanDefinition​​​类。因此这里不会详细地介绍​​ChildBeanDefinition​​,它的源码也比较短,大家可以自己去看看。

RootBeanDefinition

​RootBeanDefinition​​​表示在运行时支持​​Spring BeanFactory​​​中特定​​bean​​​的合并​​BeanDefinition​​​。它可能是从相互继承的多个原始​​BeanDefinition​​​创建的(通常注册为​​GenericBeanDefinition​​​)。​​RootBeanDefinition​​​本质上是运行时的统一​​BeanDefinition​​视图。

​RootBeanDefinition​​​也可用于在配置阶段注册单个​​BeanDefinition​​​。然而,自​​Spring2.5​​​以来,以编程方式注册​​BeanDefinition​​​的首选方法是​​GenericBeanDefinition​​​类。​​GenericBeanDefinition​​​的优点是它允许动态定义父依赖项,而不是将角色硬编码(​​hard-coding​​​)为​​RootBeanDefinition​​。

GenericBeanDefinition

​GenericBeanDefinition​​​是标准​​BeanDefinition​​​的一站式服务。与任何​​BeanDefinition​​​一样,它允许指定类以及可选的构造函数参数值和属性值。可以灵活地配置​​parentName​​​属性,以便从父​​BeanDefinition​​​中进行派生。通常,使用​​GenericBeanDefinition​​​类注册用户可见的​​BeanDefinition​​​。在父子关系恰好是预先确定的情况下,使用​​RootBeanDefinition​​​和​​ChildBeanDefinition​​。

代码也很短:

Spring Framework 源码阅读(二):BeanDefinition的作用_后端_04

创建module

先在​​Spring Framework​​​源码中增加一个​​application module​​,这在之前的博文中已经介绍过了,这里就不再赘述:

  • ​​编译 Spring Framework 5.2.17源码 & 在源码中使用 ApplicationContext 获取定义的Bean​​

Spring Framework 源码阅读(二):BeanDefinition的作用_java_05

​IMessageService​​接口:

package com.kaven.service;

/**
* @Author: ITKaven
* @Date: 2021/09/25 14:04
* @Leetcode: https://leetcode-cn.com/u/kavenit
* @Notes:
*/

public interface IMessageService {
String getMessage();
}

​MessageServiceImpl​​实现类:

package com.kaven.service.impl;

import com.kaven.service.IMessageService;
import org.springframework.stereotype.Service;

/**
* @Author: ITKaven
* @Date: 2021/09/25 14:05
* @Leetcode: https://leetcode-cn.com/u/kavenit
* @Notes:
*/

@Service("message")
public class MessageServiceImpl implements IMessageService {
@Override
public String getMessage() {
return "Hello Kaven";
}
}

​Application​​启动类:

package com.kaven;

import com.kaven.service.IMessageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
* @Author: ITKaven
* @Date: 2021/09/25 13:54
* @Leetcode: https://leetcode-cn.com/u/kavenit
* @Notes:
*/

@ComponentScan({"com.kaven"})
public class Application {

public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Application.class);

IMessageService messageServiceBean = (IMessageService) applicationContext.getBean("message");
System.out.println(messageServiceBean.getMessage());

Test test = (Test) applicationContext.getBean("test");
System.out.println("message bean: " + (test.messageService == messageServiceBean));

Test test2 = (Test) applicationContext.getBean("test");
System.out.println("message bean: " + (test2.messageService == messageServiceBean));
System.out.println("test bean: " + (test == test2));

System.out.println(applicationContext.getBeanDefinitionCount());
Arrays.stream(applicationContext.getBeanDefinitionNames()).forEach(System.out::println);
}

@Component("test")
@Scope("prototype")
static class Test {
@Autowired
private IMessageService messageService;
}
}

运行输出:

> Task :application:Application.main()
Hello Kaven
message bean: true
message bean: true
test bean: false
7
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
application
test
message

BUILD SUCCESSFUL in 19s
61 actionable tasks: 2 executed, 59 up-to-date

源码分析 - 注册​​BeanDefinition​

上下文中有​​7​​​个​​BeanDefinition​​​,而​​test bean​​​被获取了两次,为什么没有两个​​test BeanDefinition​​​?因为每个​​BeanDefinition​​​描述了一类​​bean​​​,并且​​BeanDefinition​​​是根据​​beanName​​​获取的,​​BeanDefinition​​​类似于类(对象定义),而​​bean​​​类似于对象,所以​​beanName​​​就类似于​​className​​​,类描述了该类所有对象的行为和属性,​​BeanDefinition​​​也是如此。从输出结果上来看,​​bean​​​默认是单例(除非使用​​@Scope​​​注解改变其作用域),其实在​​AbstractBeanDefinition​​的源码中也可以发现作用域的默认值。

@SuppressWarnings("serial")
public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor
implements BeanDefinition, Cloneable {

/**
* 默认作用域名称的常量:"",等同于单例状态(会被替换为单例,在相关源码的注释中有解释)
*/
public static final String SCOPE_DEFAULT = "";
@Nullable
private String scope = SCOPE_DEFAULT;
...
}

​AbstractBeanDefinition​​​的源码中还有一些比较常见配置的默认值,比如​​bean​​​默认不是​​abstract​​​的(因此需要被实例化)、​​lazyInit​​​为​​null​​​(因此不会被懒加载)、没有自动装配、依赖项检查为​​DEPENDENCY_CHECK_NONE​​​(没有依赖项检查)、是自动注入的候选​​bean​​​和不是首选​​bean​​​(​​primary​​):

private boolean abstractFlag = false;
@Nullable
private Boolean lazyInit;
private int autowireMode = AUTOWIRE_NO;
private int dependencyCheck = DEPENDENCY_CHECK_NONE;
private boolean autowireCandidate = true;
private boolean primary = false;

很显然下面这​​4​​​个​​BeanDefinition​​​是​​Spring​​定义的:

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory

它们在​​AnnotationConfigUtils​​​抽象类的​​registerAnnotationConfigProcessors​​方法中出现:

public abstract class AnnotationConfigUtils {
/**
* 内部管理Configuration注解的处理器的bean名称
*/
public static final String CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME =
"org.springframework.context.annotation.internalConfigurationAnnotationProcessor";

/**
* 内部管理Autowired注解的处理器的bean名称
*/
public static final String AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME =
"org.springframework.context.annotation.internalAutowiredAnnotationProcessor";

/**
* 内部管理JSR-250注解的处理器的bean名称
*/
public static final String COMMON_ANNOTATION_PROCESSOR_BEAN_NAME =
"org.springframework.context.annotation.internalCommonAnnotationProcessor";

/**
* 内部管理JPA注解的处理器的bean名称
*/
public static final String PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME =
"org.springframework.context.annotation.internalPersistenceAnnotationProcessor";

/**
* 内部管理EventListener注解的处理器的bean名称
*/
public static final String EVENT_LISTENER_PROCESSOR_BEAN_NAME =
"org.springframework.context.event.internalEventListenerProcessor";

/**
* 内部管理EventListenerFactory的bean名称
*/
public static final String EVENT_LISTENER_FACTORY_BEAN_NAME =
"org.springframework.context.event.internalEventListenerFactory";

/**
* 在给定registry中注册所有相关的注解post processors
* @param registry 要在其上操作的registry
* @param source 触发此注册的配置源元素(已提取),可能为null
* @return Set<BeanDefinitionHolder>,其中包含此调用实际注册的所有BeanDefinition
*/
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, @Nullable Object source) {

DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
if (beanFactory != null) {
if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
}
if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
}
}

Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);

if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}

if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}

// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
}

// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition();
try {
def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
AnnotationConfigUtils.class.getClassLoader()));
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
}
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
}

if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
}

if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
}
return beanDefs;
}

...
}

其实这个​​BeanDefinitionRegistry registry​​​参数就是博主在​​Application​​​类中创建的​​AnnotationConfigApplicationContext​​​实例。并且这里定义的​​BeanDefinition​​​是​​RootBeanDefinition​​​ 实例(​​RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);​​,博主在后面会进行讨论)。

Spring Framework 源码阅读(二):BeanDefinition的作用_后端_06


Spring Framework 源码阅读(二):BeanDefinition的作用_后端_07


​AnnotationConfigApplicationContext​​​类的父类​​GenericApplicationContext​​​实现了​​BeanDefinitionRegistry​​ 接口。

Spring Framework 源码阅读(二):BeanDefinition的作用_ide_08


下一步调用了​​AnnotationConfigUtils​​​抽象类的的​​registerPostProcessor​​​方法(可以看见​​role​​​设置为​​ROLE_INFRASTRUCTURE​​):

private static BeanDefinitionHolder registerPostProcessor(
BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {

definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(beanName, definition);
return new BeanDefinitionHolder(definition, beanName);
}

之后又调用了​​GenericApplicationContext​​​类的​​registerBeanDefinition​​​方法,很显然是​​AnnotationConfigApplicationContext​​​类继承了父类​​GenericApplicationContext​​​的​​registerBeanDefinition​​方法。

@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {

this.beanFactory.registerBeanDefinition(beanName, beanDefinition);
}

​GenericApplicationContext​​​类的​​beanFactory​​​属性是​​DefaultListableBeanFactory​​类的实例。

private final DefaultListableBeanFactory beanFactory;

​DefaultListableBeanFactory​​​类是​​Spring​​​默认实现的​​ConfigurableListableBeanFactory​​​和​​BeanDefinitionRegistry​​​接口:一个基于​​bean definition​​​元数据的成熟​​bean factory​​。

先不纠结这些类的作用,类太多了,无法把所有类的作用和原理都理解的一清二楚,需要关注的是​​DefaultListableBeanFactory​​​类中的​​beanDefinitionMap​​​和​​beanDefinitionNames​​​属性,很显然它们存储了​​beanName​​​以及相关​​BeanDefinition​​实例的信息。

/** BeanDefinition对象的映射,bean名称为key */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
/** 按注册顺序列出BeanDefinition名称 */
private volatile List<String> beanDefinitionNames = new ArrayList<>(256);

下一步调用了​​DefaultListableBeanFactory​​​类中的​​registerBeanDefinition​​​方法,在该方法中,将​​beanName​​​和​​beanDefinition​​​信息存储到了​​beanDefinitionMap​​​和​​beanDefinitionNames​​属性中:

@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {

Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");

if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}

BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
if (existingDefinition != null) {
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
}
else if (existingDefinition.getRole() < beanDefinition.getRole()) {
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
if (logger.isInfoEnabled()) {
logger.info("Overriding user-defined bean definition for bean '" + beanName +
"' with a framework-generated bean definition: replacing [" +
existingDefinition + "] with [" + beanDefinition + "]");
}
}
else if (!beanDefinition.equals(existingDefinition)) {
if (logger.isDebugEnabled()) {
logger.debug("Overriding bean definition for bean '" + beanName +
"' with a different definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
else {
if (logger.isTraceEnabled()) {
logger.trace("Overriding bean definition for bean '" + beanName +
"' with an equivalent definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
if (hasBeanCreationStarted()) {
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
removeManualSingletonName(beanName);
}
}
else {
// Still in startup registration phase
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;
}

if (existingDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
else if (isConfigurationFrozen()) {
clearByTypeCache();
}
}

这​​4​​​个内置​​bean​​​的​​BeanDefinition​​就完成了注册。

为什么会注册这些内置​​bean​​?可以看一下调用链:

Spring Framework 源码阅读(二):BeanDefinition的作用_ide_09


先是在​​main​​​方法中调用了​​AnnotationConfigApplicationContext​​类的构造函数:

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
this();
register(componentClasses);
refresh();
}

又接着调用了​​AnnotationConfigApplicationContext​​类的无参构造函数:

public AnnotationConfigApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}

然后连续调用了​​AnnotatedBeanDefinitionReader​​类的两个构造函数:

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
this(registry, getOrCreateEnvironment(registry));
}

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
Assert.notNull(environment, "Environment must not be null");
this.registry = registry;
this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}

从这里就开始注册内置​​bean​​​的​​BeanDefinition​​了。

AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);

接着会注册​​application bean​​​的​​BeanDefinition​​,调用链如下图所示:

Spring Framework 源码阅读(二):BeanDefinition的作用_自动装配_10


Spring Framework 源码阅读(二):BeanDefinition的作用_ide_11

@Override
public void register(Class<?>... componentClasses) {
Assert.notEmpty(componentClasses, "At least one component class must be specified");
this.reader.register(componentClasses);
}

在调用链的​​doRegisterBean​​​方法中可以发现​​application bean​​​的​​BeanDefinition​​​是​​AnnotatedGenericBeanDefinition​​​(​​GenericBeanDefinition​​​的子类)实例,明显和内置​​bean​​​的​​RootBeanDefinition​​实例不一样。

private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
@Nullable BeanDefinitionCustomizer[] customizers) {

AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}

abd.setInstanceSupplier(supplier);
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));

AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
if (qualifiers != null) {
for (Class<? extends Annotation> qualifier : qualifiers) {
if (Primary.class == qualifier) {
abd.setPrimary(true);
}
else if (Lazy.class == qualifier) {
abd.setLazyInit(true);
}
else {
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
}
if (customizers != null) {
for (BeanDefinitionCustomizer customizer : customizers) {
customizer.customize(abd);
}
}

BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}

可以回顾一下博主对​​RootBeanDefinition​​的介绍:

​RootBeanDefinition​​​表示在运行时支持​​Spring BeanFactory​​​中特定​​bean​​​的合并​​BeanDefinition​​​。​​RootBeanDefinition​​​本质上是运行时的统一​​BeanDefinition​​视图。

​RootBeanDefinition​​​也可用于在配置阶段注册单个​​BeanDefinition​​​。然而,自​​Spring2.5​​​以来,以编程方式注册​​BeanDefinition​​​的首选方法是​​GenericBeanDefinition​​类。

博主的理解:因为内置​​bean​​​没有父​​bean​​​,继承关系是明确的,因此内置​​bean​​​的​​BeanDefinition​​​也不会有父​​BeanDefinition​​​,也就不需要进行合并​​BeanDefinition​​​的操作,此时的​​BeanDefinition​​​就是内置​​bean​​​的统一​​BeanDefinition​​​视图,所以可以直接是​​RootBeanDefinition​​实例。

而​​application bean​​​是用户自定义的​​bean​​​,继承关系并不明确,是有可能存在继承关系的,因此有可能需要进行合并​​BeanDefinition​​​的操作,此时的​​BeanDefinition​​​就不一定是​​application bean​​​的统一​​BeanDefinition​​​视图,因此定义为​​AnnotatedGenericBeanDefinition​​​实例,以便之后可以进行合并​​BeanDefinition​​​的操作(通过设置​​parentName​​​)。而什么时候会进行合并​​BeanDefinition​​的操作,下面会进行介绍。

​test​​​以及​​message bean​​​的​​BeanDefinition​​都是在如下图所示的调用链中被定义:

Spring Framework 源码阅读(二):BeanDefinition的作用_ide_12


Spring Framework 源码阅读(二):BeanDefinition的作用_ide_13


现在所有​​bean​​​的​​BeanDefinition​​​都被注册了,下面介绍合并​​BeanDefinition​​。

源码分析 - 合并​​BeanDefinition​

合并​​BeanDefinition​​​的操作,在​​bean​​​需要实例化之前会被执行,如​​AbstractBeanFactory​​​抽象类的​​doGetBean​​方法(删除了不相关的代码):

protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
try {
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
}

接着调用了​​AbstractBeanFactory​​​抽象类的​​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 && !mbd.stale) {
return mbd;
}
return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}

​AbstractBeanFactory​​​抽象类的​​mergedBeanDefinitions​​​属性是一个​​ConcurrentHashMap​​​实例,存储了以​​bean​​​名称为​​key​​​,合并的​​RootBeanDefinition​​​为​​value​​的键值对。

/** 从bean名称映射到合并的RootBeanDefinition */
private final Map<String, RootBeanDefinition> mergedBeanDefinitions = new ConcurrentHashMap<>(256);

​RootBeanDefinition​​​类中的​​stale​​​属性,使用​​volatile​​修饰符修饰,保证了可见性。

/** 确定是否需要重新合并BeanDefinition */
volatile boolean stale;

如果之前没有合并过,或者需要重新合并,就会调用​​AbstractBeanFactory​​​抽象类的​​getMergedBeanDefinition​​​方法,而先会调用​​DefaultListableBeanFactory​​​类的​​getBeanDefinition​​​方法获取​​beanName​​​对应的​​BeanDefinition​​:

public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
BeanDefinition bd = this.beanDefinitionMap.get(beanName);
if (bd == null) {
if (logger.isTraceEnabled()) {
logger.trace("No bean named '" + beanName + "' found in " + this);
}
throw new NoSuchBeanDefinitionException(beanName);
}
return bd;
}

通过源码,其实可以发现该​​this​​​(​​DefaultListableBeanFactory​​​实例)就是之前说的在​​main​​​方法中创建的​​AnnotationConfigApplicationContext​​​实例的​​beanFactory​​属性。

Spring Framework 源码阅读(二):BeanDefinition的作用_自动装配_14


Spring Framework 源码阅读(二):BeanDefinition的作用_后端_15


在调用​​AbstractApplicationContext​​​类的​​refresh​​​方法时,将​​AnnotationConfigApplicationContext​​​实例的​​beanFactory​​属性传进去了(删除了部分代码):

@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
prepareRefresh();
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
prepareBeanFactory(beanFactory);
try {
postProcessBeanFactory(beanFactory);
invokeBeanFactoryPostProcessors(beanFactory);
registerBeanPostProcessors(beanFactory);
initMessageSource();
initApplicationEventMulticaster();
onRefresh();
registerListeners();
finishBeanFactoryInitialization(beanFactory);
finishRefresh();
}
}
}

Spring Framework 源码阅读(二):BeanDefinition的作用_ide_16


因此调用​​DefaultListableBeanFactory​​​类的​​getBeanDefinition​​​方法就是获取之前定义的​​BeanDefinition​​​(通过​​beanName​​​,内置​​bean​​​对应​​RootBeanDefinition​​​实例,而自定义​​bean​​​对应​​GenericBeanDefinition​​实例)。

BeanDefinition bd = this.beanDefinitionMap.get(beanName);

获取​​beanName​​​对应的​​BeanDefinition​​​后,返回到​​AbstractBeanFactory​​​抽象类的​​getMergedBeanDefinition​​方法(方法命名相同,和之前不是一样的方法):

protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd)
throws BeanDefinitionStoreException {

return getMergedBeanDefinition(beanName, bd, null);
}

又继续调用​​AbstractBeanFactory​​​抽象类的​​getMergedBeanDefinition​​方法(方法命名相同,和之前不是一样的方法):

protected RootBeanDefinition getMergedBeanDefinition(
String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
throws BeanDefinitionStoreException {

// 合并BeanDefinition时需要上锁,避免发生线程安全问题
synchronized (this.mergedBeanDefinitions) {
RootBeanDefinition mbd = null;
RootBeanDefinition previous = null;
if (containingBd == null) {
mbd = this.mergedBeanDefinitions.get(beanName);
}
// 没有合并过或者需要重新合并BeanDefinition
if (mbd == null || mbd.stale) {
previous = mbd;
// 没有父BeanDefinition,不需要合并,将原有的BeanDefinition拷贝即可
if (bd.getParentName() == null) {
if (bd instanceof RootBeanDefinition) {
mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
}
// 非RootBeanDefinition实例,可能是GenericBeanDefinition类或其子类的实例
else {
mbd = new RootBeanDefinition(bd);
}
}
// 有父BeanDefinition,需要合并
else {
BeanDefinition pbd;
try {
String parentBeanName = transformedBeanName(bd.getParentName());
if (!beanName.equals(parentBeanName)) {
// 合并父BeanDefinition
pbd = getMergedBeanDefinition(parentBeanName);
}
else {
BeanFactory parent = getParentBeanFactory();
if (parent instanceof ConfigurableBeanFactory) {
// 合并父BeanDefinition
pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
}
else {
throw new NoSuchBeanDefinitionException(parentBeanName,
"Parent name '" + parentBeanName + "' is equal to bean name '" + beanName +
"': cannot be resolved without a ConfigurableBeanFactory parent");
}
}
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
"Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
}
// 将合并的父BeanDefinition转换成RootBeanDefinition实例
mbd = new RootBeanDefinition(pbd);
// 子BeanDefinition重写合并的父BeanDefinition得到合并的子BeanDefinition
mbd.overrideFrom(bd);
}
// 作用域为""时(默认),会被替代为SCOPE_SINGLETON(单例),和上面说的对应起来了
if (!StringUtils.hasLength(mbd.getScope())) {
mbd.setScope(SCOPE_SINGLETON);
}
// 非单例bean中包含的bean本身不能是单例bean
// 更正这个问题,因为这可能是外部bean的父子合并,在这种情况下,原始内部BeanDefinition将不会继承合并的外部bean的单例状态。
if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
mbd.setScope(containingBd.getScope());
}
// 暂时缓存合并的BeanDefinition
// 以后可能会重新合并,以获取元数据更改
if (containingBd == null && isCacheBeanMetadata()) {
this.mergedBeanDefinitions.put(beanName, mbd);
}
}
if (previous != null) {
copyRelevantMergedBeanDefinitionCaches(previous, mbd);
}
return mbd;
}
}

可见合并的​​BeanDefinition​​​默认就是​​RootBeanDefinition​​​实例,这也就是为什么说​​RootBeanDefinition​​​本质上是运行时的统一​​BeanDefinition​​​视图的原因了。该方法通过递归调用的形式合并​​BeanDefinition​​​,这也符合​​bean​​之间的继承关系图。

合并​​BeanDefinition​​​之后,就能知道​​bean​​​的所有配置信息,就可以进行​​bean​​的实例化了。

阅读源码需要耐心,一步步进行​​Debug​​,每个人的理解不同,如果博主有说错的地方或者大家有不同的见解,欢迎大家评论补充。


举报

相关推荐

0 条评论