Spring源码 --- BeanDefinition接口,及其各种子类结构关系

2023-11-27 17:50

本文主要是介绍Spring源码 --- BeanDefinition接口,及其各种子类结构关系,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

BeanDefinition就是用于描叙Spring中的Bean  

Spring中关于一个Bean的基本描叙接口 --

        BeanDefinition的定义:

                                        

       BeanMetadataElement接口:获取Source。

public interface BeanMetadataElement {/*** Return the configuration source {@code Object} for this metadata element* (may be {@code null}).*/@NullableObject getSource();}

   AttributeAccessor:   

public interface AttributeAccessor {void setAttribute(String name, @Nullable Object value);@NullableObject getAttribute(String name);@NullableObject removeAttribute(String name);boolean hasAttribute(String name);String[] attributeNames();}

      其基本实现类:BeanMetadataAttributeAccessor:     

public abstract class AttributeAccessorSupport implements AttributeAccessor, Serializable {private final Map<String, Object> attributes = new LinkedHashMap<>(0);@Overridepublic void setAttribute(String name, @Nullable Object value) {Assert.notNull(name, "Name must not be null");if (value != null) {this.attributes.put(name, value);}else {removeAttribute(name);}}
..................
}

然后是其Abstract实现:AbstractBeanDefinition

   此类定义了注入Bean的几种类型:

/*** Constant that indicates no autowiring at all.* @see #setAutowireMode*/
public static final int AUTOWIRE_NO = AutowireCapableBeanFactory.AUTOWIRE_NO;public static final int AUTOWIRE_BY_NAME = AutowireCapableBeanFactory.AUTOWIRE_BY_NAME;public static final int AUTOWIRE_BY_TYPE = AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE;public static final int AUTOWIRE_CONSTRUCTOR = AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR;@Deprecated
public static final int AUTOWIRE_AUTODETECT = AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT;

第一个是默认的,然后最后一个AUTOWIRE_AUTODETECT 已经是过时的了@Deprecated。在使用的这几种类型看名字也知道其是什么类型的了。而过时的那种,我们找到其中的一个使用的地方是会将其转换为转换为“AUTOWIRE_BY_TYPE”、“AUTOWIRE_CONSTRUCTOR”:

public int getResolvedAutowireMode() {if (this.autowireMode == AUTOWIRE_AUTODETECT) {// Work out whether to apply setter autowiring or constructor autowiring.// If it has a no-arg constructor it's deemed to be setter autowiring,// otherwise we'll try constructor autowiring.Constructor<?>[] constructors = getBeanClass().getConstructors();for (Constructor<?> constructor : constructors) {if (constructor.getParameterCount() == 0) {return AUTOWIRE_BY_TYPE;}}return AUTOWIRE_CONSTRUCTOR;}else {return this.autowireMode;}
}

     再AbstractBeanDefinition的直接子类:

               ChildBeanDefinition、RootBeanDefinition、GenericBeanDefinition、AnnotatedBeanDefinition

    这四个的区别:

     

     AnnotatedBeanDefinition

        就是描叙通过注解的方式注入的BeanDefinition

     RootBeanDefinition

       看下RootBeanDefinition的注释:

A root bean definition represents the merged bean definition that backs ,a specific bean in a Spring BeanFactory at runtime。

       用不太好的英语看下其主要意思。其是一个merged bean definition(合并的Bean定义),在BeanFactory at runtime(BeanFactory 运行使用的时候)。

  我们看下BeanFactory在获取Bean的时候:

     在AbstractBeanFactory通过Bean名称第一次获取对应Bean的getBean(String name)方法的过程中。是会调一个方法:

           final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);

         最后会调到这段代码

getMergedBeanDefinition(String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
{..............  if (bd.getParentName() == null) {  if (bd instanceof RootBeanDefinition) {     mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();}else {mbd = new RootBeanDefinition(bd);}..........
}
RootBeanDefinition(BeanDefinition original) {super(original);
}
protected AbstractBeanDefinition(BeanDefinition original) {setParentName(original.getParentName());setBeanClassName(original.getBeanClassName());setScope(original.getScope());setAbstract(original.isAbstract());setLazyInit(original.isLazyInit());..........
}

也就是说,你在获取的Bean的时候,不管是哪种BeanDefinition的定义,如果不是RootBeanDefinition,都会转换为RootBeanDefinition。

     ChildBeanDefinition

public class ChildBeanDefinition extends AbstractBeanDefinition {@Nullableprivate String parentName;.........@Overridepublic void setParentName(@Nullable String parentName) {this.parentName = parentName;}@Override@Nullablepublic String getParentName() {return this.parentName;}...........
}

其会有一个有父的BeanDefinition。而前面的RootBeanDefinition是没有parentName的(因为在获取Bean的时候其他的类型都是需要归并为RootBeanDefinition来最终使用):

public class RootBeanDefinition extends AbstractBeanDefinition {......@Overridepublic String getParentName() {return null;}..........}

 我们再来看其在获取Bean的时候是怎样使用的(前面是走的bd.getParentName() == null的逻辑,现在走的是下面的内容): 

if (bd.getParentName() == null) {.........
}
else {BeanDefinition pbd;try {String parentBeanName = transformedBeanName(bd.getParentName());if (!beanName.equals(parentBeanName)) {pbd = getMergedBeanDefinition(parentBeanName);}else {BeanFactory parent = getParentBeanFactory();if (parent instanceof ConfigurableBeanFactory) {pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);}.............mbd = new RootBeanDefinition(pbd);mbd.overrideFrom(bd);}
}

这里的getMergedBeanDefinition就是会回到最初的获取MergedBean。这里就有有个循环调用。去获取父Bean,然后合并为RootBeanDefinition

  GenericBeanDefinition

    GenericBeanDefinition其也是有ParentName属性的。那这个GenericBeanDefinition与ChildrenBeanDefinitin的区别是什么呢?

    其两者的区别主要是ChildrenBeanDefinitin没有子类了,而GenericBeanDefinition还有子类。(目前了解的使用情况:如果一个Bean有父Bean,Spring内部在使用BeanDefinition的时候也用的是这个GenericBeanDefinition,而ChildrenBeanDefinitin在Spring源码内部,Spring一般并没有主动去创建使用这个类)。

       GenericBeanDefinition的子类:AnnotatedGenericBeanDefinition、ScannedGenericBeanDefinition

             这两个子类一个是通过注解的方式注入的Bean、例如@Configuration等这种注直接指明一个对应的注解类注入的BeanDefinition就会装配为AnnotatedGenericBeanDefinition、而通过扫描包的方式其添加的BeanDefinition就会装配为ScannedGenericBeanDefinition。我们通过代码来说明:

           AnnotatedGenericBeanDefinition:       

<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,@Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {return;}
...........
}

往上找这个方法的调用:

public void registerBean(Class<?> annotatedClass) {doRegisterBean(annotatedClass, null, null, null);
}
public class AnnotatedBeanDefinitionReader {........public void register(Class<?>... annotatedClasses) {for (Class<?> annotatedClass : annotatedClasses) {registerBean(annotatedClass);}............}

    再找个调用此方法的测试demo:     

@Test
public void annotatedBeanDefinitionReader_inheritsEnvironmentFromEnvironmentCapableBDR() {GenericApplicationContext ctx = new GenericApplicationContext();ctx.setEnvironment(prodEnv);new AnnotatedBeanDefinitionReader(ctx).register(Config.class);
}
@Configuration
@Import({DevConfig.class, ProdConfig.class})
static class Config {@Beanpublic EnvironmentAwareBean envAwareBean() {return new EnvironmentAwareBean();}
}

        ScannedGenericBeanDefinition            

private Set<BeanDefinition> scanCandidateComponents(String basePackage) {Set<BeanDefinition> candidates = new LinkedHashSet<>();try {String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +resolveBasePackage(basePackage) + '/' + this.resourcePattern;Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);............for (Resource resource : resources) {if (resource.isReadable()) {try {MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);if (isCandidateComponent(metadataReader)) {ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);..........
}
@Test
public void testSimpleScanWithDefaultFiltersAndPrimaryLazyBean() {GenericApplicationContext context = new GenericApplicationContext();ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);scanner.scan(BASE_PACKAGE);scanner.scan("org.springframework.context.annotation5");..........
}

可以看到这个就是通过basePackage基本包,然后从对应包下面找到要注入的BeanDefinition会描叙为ScannedGenericBeanDefinition。

   从成员变量的角度来说:

public class AnnotatedGenericBeanDefinition extends GenericBeanDefinition implements AnnotatedBeanDefinition {private final AnnotationMetadata metadata;@Nullableprivate MethodMetadata factoryMethodMetadata;......
}
public class ScannedGenericBeanDefinition extends GenericBeanDefinition implements AnnotatedBeanDefinition {private final AnnotationMetadata metadata;..........
}

AnnotatedGenericBeanDefinition 比ScannedGenericBeanDefinition 多了一个MethodMetadata :

public interface MethodMetadata extends AnnotatedTypeMetadata {String getMethodName();String getDeclaringClassName();String getReturnTypeName();boolean isAbstract();boolean isStatic();boolean isFinal();boolean isOverridable();
}

      ConfigurationClassBeanDefinition:

class ConfigurationClassBeanDefinitionReader {  ..........private static class ConfigurationClassBeanDefinition extends RootBeanDefinition implements AnnotatedBeanDefinition {private final AnnotationMetadata annotationMetadata;private final MethodMetadata factoryMethodMetadata;...........}

可以看到其是定义在ConfigurationClassBeanDefinitionReader

    那这个ConfigurationClassBeanDefinition是用来描叙哪种类型的BeanDefinition的呢。我们看下其的使用demo:

public static void main(String[] args)
{GenericApplicationContext listableBeanFactory = new GenericApplicationContext();new AnnotatedBeanDefinitionReader(listableBeanFactory).register(Config.class);listableBeanFactory.refresh();TestBean bean = listableBeanFactory.getBean(TestBean.class);
}
@Configuration
public class Config
{@Beanpublic TestBean getTestBean(){return new TestBean();}
}

可以看到通过在@Configuration 中使用@Bean会将其注册为ConfigurationClassBeanDefinition。而@Configuration是注册为前面讲的AnnotatedGenericBeanDefinition:

    

       

 

     

这篇关于Spring源码 --- BeanDefinition接口,及其各种子类结构关系的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/428222

相关文章

Spring Boot整合Redis注解实现增删改查功能(Redis注解使用)

《SpringBoot整合Redis注解实现增删改查功能(Redis注解使用)》文章介绍了如何使用SpringBoot整合Redis注解实现增删改查功能,包括配置、实体类、Repository、Se... 目录配置Redis连接定义实体类创建Repository接口增删改查操作示例插入数据查询数据删除数据更

Java Lettuce 客户端入门到生产的实现步骤

《JavaLettuce客户端入门到生产的实现步骤》本文主要介绍了JavaLettuce客户端入门到生产的实现步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要... 目录1 安装依赖MavenGradle2 最小化连接示例3 核心特性速览4 生产环境配置建议5 常见问题

Java使用Swing生成一个最大公约数计算器

《Java使用Swing生成一个最大公约数计算器》这篇文章主要为大家详细介绍了Java使用Swing生成一个最大公约数计算器的相关知识,文中的示例代码讲解详细,感兴趣的小伙伴可以了解一下... 目录第一步:利用欧几里得算法计算最大公约数欧几里得算法的证明情形 1:b=0情形 2:b>0完成相关代码第二步:加

Java 的ArrayList集合底层实现与最佳实践

《Java的ArrayList集合底层实现与最佳实践》本文主要介绍了Java的ArrayList集合类的核心概念、底层实现、关键成员变量、初始化机制、容量演变、扩容机制、性能分析、核心方法源码解析、... 目录1. 核心概念与底层实现1.1 ArrayList 的本质1.1.1 底层数据结构JDK 1.7

Java Map排序如何按照值按照键排序

《JavaMap排序如何按照值按照键排序》该文章主要介绍Java中三种Map(HashMap、LinkedHashMap、TreeMap)的默认排序行为及实现按键排序和按值排序的方法,每种方法结合实... 目录一、先理清 3 种 Map 的默认排序行为二、按「键」排序的实现方式1. 方式 1:用 TreeM

Java中流式并行操作parallelStream的原理和使用方法

《Java中流式并行操作parallelStream的原理和使用方法》本文详细介绍了Java中的并行流(parallelStream)的原理、正确使用方法以及在实际业务中的应用案例,并指出在使用并行流... 目录Java中流式并行操作parallelStream0. 问题的产生1. 什么是parallelS

Java中Redisson 的原理深度解析

《Java中Redisson的原理深度解析》Redisson是一个高性能的Redis客户端,它通过将Redis数据结构映射为Java对象和分布式对象,实现了在Java应用中方便地使用Redis,本文... 目录前言一、核心设计理念二、核心架构与通信层1. 基于 Netty 的异步非阻塞通信2. 编解码器三、

SpringBoot基于注解实现数据库字段回填的完整方案

《SpringBoot基于注解实现数据库字段回填的完整方案》这篇文章主要为大家详细介绍了SpringBoot如何基于注解实现数据库字段回填的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以了解... 目录数据库表pom.XMLRelationFieldRelationFieldMapping基础的一些代

一篇文章彻底搞懂macOS如何决定java环境

《一篇文章彻底搞懂macOS如何决定java环境》MacOS作为一个功能强大的操作系统,为开发者提供了丰富的开发工具和框架,下面:本文主要介绍macOS如何决定java环境的相关资料,文中通过代码... 目录方法一:使用 which命令方法二:使用 Java_home工具(Apple 官方推荐)那问题来了,

Java HashMap的底层实现原理深度解析

《JavaHashMap的底层实现原理深度解析》HashMap基于数组+链表+红黑树结构,通过哈希算法和扩容机制优化性能,负载因子与树化阈值平衡效率,是Java开发必备的高效数据结构,本文给大家介绍... 目录一、概述:HashMap的宏观结构二、核心数据结构解析1. 数组(桶数组)2. 链表节点(Node