Spring源码-BeanDefinition
AbstractBeanDefinition抽象类是BeanDefinition 接口的具体实现类。除了包含BeanDefinition接口的配置信息,还添加了其他配置信息,主要补充bean的行为特征。// 可能是bean名称,也可能是bean类型// 自动装配模式// 依赖检查方式// 是否具有指定的限定符// 用于创建 Bean 实例的回调// 是否允许访问非公共构造函数和方法// 宽松模式(
版本 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进一步确认
- 处理content命名空间的类是:org.springframework.context.config.ContextNamespaceHandler
- 处理自动装配的类是: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定义类除了展示的创建/使用方法外,也可能在其他地方被实例化,只是提供一个观察入口。
参考
更多推荐
所有评论(0)