Spring源码-BeanDefinition

版本 Spring Framework 6.0.9​

1. BeanDefinition

BeanDefinition接口用于描述一个bean实例,可以包含大量配置信息,包括构造函数参数、属性值和特定于容器的信息。这里只展示get方法。

public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
	boolean isLazyInit(); // 是否延迟初始化bean
	boolean isAutowireCandidate(); // 是否可以自动装配
	boolean isPrimary(); // 是否首选的自动装配Bean
	boolean isSingleton(); // 是否单例作用域
	boolean isPrototype(); // 是否原型作用域
	boolean isAbstract(); // 是否是“抽象的”,即不是要实例化本身,而只是作为具体子 Bean 定义的父级
	String getParentName(); // 父定义的名称
	String getBeanClassName(); // Bean的类名
	String getScope(); // 目标作用域的名称
	String[] getDependsOn(); // 所依赖的 Bean 名称
	String getFactoryBeanName(); // 工厂 Bean 名称
	String getFactoryMethodName(); // 工厂方法
	ConstructorArgumentValues getConstructorArgumentValues(); // 构造函数参数值
	MutablePropertyValues getPropertyValues(); // bean实例的属性值
	String getInitMethodName(); // 初始化方法名
	String getDestroyMethodName(); // 销毁方法名
	int getRole(); // 角色提示
	String getDescription(); // 可读描述
	ResolvableType getResolvableType(); // Bean 定义的可解析类型
	String getResourceDescription(); // 资源的描述
	BeanDefinition getOriginatingBeanDefinition(); // 原始 BeanDefinition,例如此bean为代理类,则返回被代理bean定义
	// 省略部分代码...
}

  • Bean的类信息:Bean实例化后的具体类型(BeanClassName、ResolvableType)、构造函数参数(ConstructorArgumentValues )、属性值(MutablePropertyValues )。
  • Bean的属性信息:包括了Bean的作用域(单例or原型);是否为主要的(primary)、描述信息、角色等等
  • Bean的行为特性:Bean是否支持延迟加载;是否可以作为自动装配的候选者、以及Bean的初始化方法和销毁方法
  • Bean的依赖关系:Bean所依赖的其他Bean,以及这个Bean是否有父Bean

2. AbstractBeanDefinition

AbstractBeanDefinition抽象类是BeanDefinition 接口的具体实现类。除了包含BeanDefinition接口的配置信息,还添加了其他配置信息,主要补充bean的行为特征。

public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor
		implements BeanDefinition, Cloneable {
	private volatile Object beanClass; // 可能是bean名称,也可能是bean类型
	private int autowireMode = AUTOWIRE_NO; // 自动装配模式
	private int dependencyCheck = DEPENDENCY_CHECK_NONE; // 依赖检查方式
	private final Map<String, AutowireCandidateQualifier> qualifiers = new LinkedHashMap<>(); // 是否具有指定的限定符
	private Supplier<?> instanceSupplier; // 用于创建 Bean 实例的回调
	private boolean nonPublicAccessAllowed = true; // 是否允许访问非公共构造函数和方法
	private boolean lenientConstructorResolution = true; // 宽松模式(true)下还是严格模式下解析构造函数
	private MethodOverrides methodOverrides = new MethodOverrides(); // 有关 IoC 容器要重写的方法的信息
	private boolean enforceInitMethod = true; // 初始化方法是否为默认方法
	private boolean enforceDestroyMethod = true; // 销毁方法是否为默认方法,
	private boolean synthetic = false; // Bean 定义是否为“合成的”
	// 省略部分代码...
}

另外提供overrideFrom和applyDefaults两个方法

  • overrideFrom:从给定的 Bean 定义覆盖此 Bean 定义中的设置(可能是从父子继承关系中复制的父项)。
  • applyDefaults:将提供的缺省值应用于此 Bean。
	// 
	public void overrideFrom(BeanDefinition other) {
		if (StringUtils.hasLength(other.getBeanClassName())) {
			setBeanClassName(other.getBeanClassName());
		}
		if (StringUtils.hasLength(other.getScope())) {
			setScope(other.getScope());
		}
		setAbstract(other.isAbstract());
		if (StringUtils.hasLength(other.getFactoryBeanName())) {
			setFactoryBeanName(other.getFactoryBeanName());
		}
		if (StringUtils.hasLength(other.getFactoryMethodName())) {
			setFactoryMethodName(other.getFactoryMethodName());
		}
		setRole(other.getRole());
		setSource(other.getSource());
		copyAttributesFrom(other);

		if (other instanceof AbstractBeanDefinition otherAbd) {
			if (otherAbd.hasBeanClass()) {
				setBeanClass(otherAbd.getBeanClass());
			}
			if (otherAbd.hasConstructorArgumentValues()) {
				getConstructorArgumentValues().addArgumentValues(other.getConstructorArgumentValues());
			}
			if (otherAbd.hasPropertyValues()) {
				getPropertyValues().addPropertyValues(other.getPropertyValues());
			}
			if (otherAbd.hasMethodOverrides()) {
				getMethodOverrides().addOverrides(otherAbd.getMethodOverrides());
			}
			Boolean lazyInit = otherAbd.getLazyInit();
			if (lazyInit != null) {
				setLazyInit(lazyInit);
			}
			setAutowireMode(otherAbd.getAutowireMode());
			setDependencyCheck(otherAbd.getDependencyCheck());
			setDependsOn(otherAbd.getDependsOn());
			setAutowireCandidate(otherAbd.isAutowireCandidate());
			setPrimary(otherAbd.isPrimary());
			copyQualifiersFrom(otherAbd);
			setInstanceSupplier(otherAbd.getInstanceSupplier());
			setNonPublicAccessAllowed(otherAbd.isNonPublicAccessAllowed());
			setLenientConstructorResolution(otherAbd.isLenientConstructorResolution());
			if (otherAbd.getInitMethodNames() != null) {
				setInitMethodNames(otherAbd.getInitMethodNames());
				setEnforceInitMethod(otherAbd.isEnforceInitMethod());
			}
			if (otherAbd.getDestroyMethodNames() != null) {
				setDestroyMethodNames(otherAbd.getDestroyMethodNames());
				setEnforceDestroyMethod(otherAbd.isEnforceDestroyMethod());
			}
			setSynthetic(otherAbd.isSynthetic());
			setResource(otherAbd.getResource());
		}
		else {
			getConstructorArgumentValues().addArgumentValues(other.getConstructorArgumentValues());
			getPropertyValues().addPropertyValues(other.getPropertyValues());
			setLazyInit(other.isLazyInit());
			setResourceDescription(other.getResourceDescription());
		}
	}

	public void applyDefaults(BeanDefinitionDefaults defaults) {
		Boolean lazyInit = defaults.getLazyInit();
		if (lazyInit != null) {
			setLazyInit(lazyInit);
		}
		setAutowireMode(defaults.getAutowireMode());
		setDependencyCheck(defaults.getDependencyCheck());
		setInitMethodName(defaults.getInitMethodName());
		setEnforceInitMethod(false);
		setDestroyMethodName(defaults.getDestroyMethodName());
		setEnforceDestroyMethod(false);
	}

AbstractBeanDefinition有三个子类

  • RootBeanDefinition表示在运行时支持 Spring BeanFactory 中特定 Bean 的 合并 Bean 定义
  • ChildBeanDefinition会从其父bean定义中继承部分配置,如构造函数参数值、属性值和方法覆盖。
  • GenericBeanDefinition是一站式服务的bean定义,即可指定类以及可选的构造函数参数值和属性值,也可用过“parentName”从父 Bean 定义派生的内容。
    在这里插入图片描述

3. RootBeanDefinition

在spring的refresh过程中,会进行bean定义的合并,即给定 Bean 的定义是子 Bean 定义,则通过与父级 Bean 合并,返回给定顶级 Bean 的 RootBeanDefinition,相当于是完整的bean定义。具体方法org.springframework.beans.factory.support.AbstractBeanFactory#getMergedLocalBeanDefinition。

4. ChildBeanDefinition

从ChildBeanDefinition的构造方法中知道,其父bean名称需要传入,对父 Bean 定义具有固定的依赖关系。

public class ChildBeanDefinition extends AbstractBeanDefinition {

	@Nullable
	private String parentName;

	public ChildBeanDefinition(String parentName) {
		super();
		this.parentName = parentName;
	}

	public ChildBeanDefinition(String parentName, MutablePropertyValues pvs) {
		super(null, pvs);
		this.parentName = parentName;
	}

	public ChildBeanDefinition(
			String parentName, ConstructorArgumentValues cargs, MutablePropertyValues pvs) {

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

	public ChildBeanDefinition(
			String parentName, Class<?> beanClass, ConstructorArgumentValues cargs, MutablePropertyValues pvs) {

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

	public ChildBeanDefinition(
			String parentName, String beanClassName, ConstructorArgumentValues cargs, MutablePropertyValues pvs) {

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

	public ChildBeanDefinition(ChildBeanDefinition original) {
		super(original);
	}
	// 省略其他代码...
}

5. GenericBeanDefinition

GenericBeanDefinition是常规注册bean定义所使用的类,同时它允许通过 GenericBeanDefinition.setParentName 该方法动态定义父依赖项,是ChildBeanDefinition的替代方式。

当我们使用熟悉的ClassPathXmlApplicationContext创建ioc容器时,通过xml配置bean所创建的bean定义即是GenericBeanDefinition。

  • 启动类
public class Main {
	public static void main(String[] ags) {
		ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
	}
}
  • User.class
public class User {
	private String name;
	private Integer level;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Integer getLevel() {
		return level;
	}
	public void setLevel(Integer level) {
		this.level = level;
	}
}
  • beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

	<bean id="user" name="user" class="org.springframework.learn.ioc.User">
		<property name="name" value="魔法师"/>
		<property name="level" value="1"/>
	</bean>

</beans>

通过debug,可以知道在refresh的obtainFreshBeanFactory阶段,创建bean定义使用的是GenericBeanDefinition。
在这里插入图片描述

从bean工厂中获取的bean定义,打印bean定义的类型

public class Main {
	public static void main(String[] ags) {
		ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
		BeanDefinition beanDefinition = context.getBeanFactory().getBeanDefinition("user");
		System.out.println(beanDefinition.getClass().getName());
	}
}

在这里插入图片描述

6. GenericBeanDefinition的子类

GenericBeanDefinition有两个子类,AnnotatedGenericBeanDefinition和ScannedGenericBeanDefinition
在这里插入图片描述

6.1 ScannedGenericBeanDefinition

当我们通过扫描包的方式,如果类上包含@Component @Servicec @Repository等注解,则会加载到ioc容器中。相较于GenericBeanDefinition,保存了类上的注解信息,这使得Spring能够在运行时读取和处理这些注解。

public class ScannedGenericBeanDefinition extends GenericBeanDefinition implements AnnotatedBeanDefinition {

	private final AnnotationMetadata metadata;
	
	public ScannedGenericBeanDefinition(MetadataReader metadataReader) {
		Assert.notNull(metadataReader, "MetadataReader must not be null");
		this.metadata = metadataReader.getAnnotationMetadata();
		setBeanClassName(this.metadata.getClassName());
		setResource(metadataReader.getResource());
	}


	@Override
	public final AnnotationMetadata getMetadata() {
		return this.metadata;
	}

	@Override
	@Nullable
	public MethodMetadata getFactoryMethodMetadata() {
		return null;
	}

}

我们使用ClassPathXmlApplicationContext自动装配或AnnotationConfigApplicationContext扫描包的方式,创建bean定义使用的是ScannedGenericBeanDefinition 。

  • 启动类
public class Main {

	public static void main(String[] args) {
		ClassPathXmlApplicationContext classPathXmlApplicationContext 
			= new ClassPathXmlApplicationContext("scanbeans.xml");
		BeanDefinition beanDefinition = classPathXmlApplicationContext.getBeanFactory().getBeanDefinition("user");
		System.out.println("ClassPathXmlApplicationContext user beanDefinition:" + beanDefinition.getClass().getName());

		AnnotationConfigApplicationContext annotationConfigApplicationContext 
			= new AnnotationConfigApplicationContext("org.springframework.learn.beanDefinition");
		BeanDefinition beanDefinition2 = annotationConfigApplicationContext.getBeanFactory().getBeanDefinition("user");
		System.out.println("AnnotationConfigApplicationContext user beanDefinition:" + beanDefinition2.getClass().getName());
	}
}
  • User.class
package org.springframework.learn.beanDefinition;

import org.springframework.stereotype.Service;

@Service("user")
public class User {
	private String name;
	private Integer level;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Integer getLevel() {
		return level;
	}
	public void setLevel(Integer level) {
		this.level = level;
	}
}
  • scanbeans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	   xmlns:context="http://www.springframework.org/schema/context"
	   xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd">
	<!--开启组件扫描功能-->
	<context:component-scan base-package="org.springframework.learn.beanDefinition"/>
</beans>

输出如下:
在这里插入图片描述
ClassPathXmlApplicationContext自动装配 和 AnnotationConfigApplicationContext指定扫描路径中, 虽然创建的bean定义类型一样,但处理的类不一样。

6.1.1 ClassPathXmlApplicationContext自动装配

ClassPathXmlApplicationContext在refresh的obtainFreshBeanFactory阶段,由于scanbeans.xml文件上配置的是自动扫描(“context:component-scan”),属于其他命名空间,不属于默认命名空间。spring内置命名空间handler通过扫描META-INF/spring.handlers路径获取,扫描执行类是org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver
在这里插入图片描述
可以看到解析context命名空间的是org.springframework.context.config.ContextNamespaceHandler,从ContextNamespaceHandler源码上可知处理自动装配“component-scan”的类是ComponentScanBeanDefinitionParser。
在这里插入图片描述
通过debug进一步确认

  1. 处理content命名空间的类是:org.springframework.context.config.ContextNamespaceHandler
  2. 处理自动装配的类是:org.springframework.context.annotation.ComponentScanBeanDefinitionParser
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

6.1.2 AnnotationConfigApplicationContext指定扫描路径

AnnotationConfigApplicationContext则没有那么多弯弯绕绕,在调用AnnotationConfigApplicationContext有参构造方法中,实例化一个ClassPathBeanDefinitionScanner对象,执行扫描和为bean工厂加载bean定义。

public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {

	private final AnnotatedBeanDefinitionReader reader;
	private final ClassPathBeanDefinitionScanner scanner;
	
	public AnnotationConfigApplicationContext() {
		StartupStep createAnnotatedBeanDefReader = this.getApplicationStartup().start("spring.context.annotated-bean-reader.create");
		this.reader = new AnnotatedBeanDefinitionReader(this);
		createAnnotatedBeanDefReader.end();
		// 实例化一个ClassPathBeanDefinitionScanner对象,用于扫描
		this.scanner = new ClassPathBeanDefinitionScanner(this);
	}
	
	public AnnotationConfigApplicationContext(String... basePackages) {
		this();
		scan(basePackages);
		refresh();
	}
	
	@Override
	public void scan(String... basePackages) {
		Assert.notEmpty(basePackages, "At least one base package must be specified");
		StartupStep scanPackages = this.getApplicationStartup().start("spring.context.base-packages.scan")
				.tag("packages", () -> Arrays.toString(basePackages));
		this.scanner.scan(basePackages);
		scanPackages.end();
	}
	// 省略其他代码

6.2 AnnotatedGenericBeanDefinition

AnnotatedGenericBeanDefinition 相较于ScannedGenericBeanDefinition,都保存了类上的注解信息外,不同点是本身也可以解析类上的注解信息。

public class AnnotatedGenericBeanDefinition extends GenericBeanDefinition implements AnnotatedBeanDefinition {

	private final AnnotationMetadata metadata;

	@Nullable
	private MethodMetadata factoryMethodMetadata;

	public AnnotatedGenericBeanDefinition(Class<?> beanClass) {
		setBeanClass(beanClass);
		this.metadata = AnnotationMetadata.introspect(beanClass);
	}

	public AnnotatedGenericBeanDefinition(AnnotationMetadata metadata) {
		Assert.notNull(metadata, "AnnotationMetadata must not be null");
		if (metadata instanceof StandardAnnotationMetadata sam) {
			setBeanClass(sam.getIntrospectedClass());
		}
		else {
			setBeanClassName(metadata.getClassName());
		}
		this.metadata = metadata;
	}

	public AnnotatedGenericBeanDefinition(AnnotationMetadata metadata, MethodMetadata factoryMethodMetadata) {
		this(metadata);
		Assert.notNull(factoryMethodMetadata, "MethodMetadata must not be null");
		setFactoryMethodName(factoryMethodMetadata.getMethodName());
		this.factoryMethodMetadata = factoryMethodMetadata;
	}


	@Override
	public final AnnotationMetadata getMetadata() {
		return this.metadata;
	}

	@Override
	@Nullable
	public final MethodMetadata getFactoryMethodMetadata() {
		return this.factoryMethodMetadata;
	}

}

我们通过给定的组件类的AnnotationConfigApplicationContext有参构造方法,创建AnnotatedGenericBeanDefinition 。

  • 启动类
public class AnnoMain {

	public static void main(String[] args) {
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(User.class);
		BeanDefinition beanDefinition = context.getBeanFactory().getBeanDefinition("user");
		System.out.println(beanDefinition.getClass().getName());
	}
}
  • User.class
@Service("user")
public class User {

	private String name;

	private Integer level;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Integer getLevel() {
		return level;
	}

	public void setLevel(Integer level) {
		this.level = level;
	}
}

输出如下:

在这里插入图片描述

上文中所有bean定义类除了展示的创建/使用方法外,也可能在其他地方被实例化,只是提供一个观察入口。

参考

  • 54
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值