举足轻重的BeanDefinition

读懂Spring的必经之路—BeanDefinition

最近有人问我:我想学习spring源码,可是源码量那么大,我应该从哪里开始学?有没有哪个切入点啊,应该从哪里开始看啊?我想了想,决定写一篇博客,说说自己个人的看法,希望能对想学spring源码但又不知道从何开始的人有点帮助。

从那开始看?

对于异常庞大的Spring源码,可能很多人在一开始就望而生畏,不知道应该怎么去阅读,从哪开始阅读。
如果我们将Spring比喻成一个奶茶店,一个个的bean比喻成一杯杯的奶茶。那在我们要做一杯奶茶之前,我们最应该知道什么—这杯奶茶的信息
波霸奶茶,去冰无糖,走奶,不要茶
只有在店员知道了你对这杯奶茶的需求的描述之后,才能给你做一杯你想要的奶茶

Spring中如何定义Bean的信息

在spring中,处处都离不开Bean。跟上面例子同样的道理,如果我们要知道Spring怎么生成一个Bean,我觉得应该从Bean的信息开始看起—BeanDefinition

我们会发现,在Spring中,如果我们在一个类上面加了@Lazy注解,这个类就会变成懒加载模式(即不会在容器初始化的时候马上生成bean,而是在第一次获取bean的时候才生成bean)
如果我们在类上面加了@DependsOn("b")注解,那么这个类就会在b这个bean实例化之后才进行实例化
而这,也就是我们对于我们需要创建的bean的描述,就像我们描述我们需要的奶茶一样!

BeanDefinition

在Spring中,BeanDefnition是一个接口,他继承了两个接口,并且提供了许多实现类供Spring自己和程序员使用
在这里插入图片描述

BeanDefinition继承的两个类

  • BeanMetadataElement
	public interface BeanMetadataElement {
	
	//用来获取这个类所在的路径
   @Nullable
   Object getSource();
   
   }
  • AttributeAccessor
    这个接口提供了5个方法,所有方法都与Attribute有关。这只是一个接口,在具体实现类中,会维护一个Map用于保存Bean的一些额外信息,程序员也可以通过提供的api往某个BeanDefinition中存入自己想要进行储存的信息。
public interface AttributeAccessor {

	void setAttribute(String name, @Nullable Object value);

	Object getAttribute(String name);

	Object removeAttribute(String name);

	boolean hasAttribute(String name);

	String[] attributeNames();

}

可能的应用场景

       对于第一个接口BeanMetadataElement可能会比较容易理解,在具体实现类中就是用来获取类所在路径的

       但是对于第二个可能如果对于第一次看到的话,会想不明白这个接口提供的这些方法有什么用?在这里我简单举一个例子:

       对于我们自己手动注册的BeanDefinition(后面文章会讲到怎么自己手动注册bd),我们可以调用 setAttribute(“zes”, true) 方法,为里面加入一个标识符,在我们下次需要判断这个BeanDefinition是不是我们自己注册的时候,只需要通过 getAttribute(“zes”) 来判断是否为 true 就可以了

实际的应用场景

       在Spring的ConfigurationClassUtils#checkConfigurationClassCandidate()中有这么一段

		//确定是不是一个全配置类  判断是否加了 @Configuration
		if (isFullConfigurationCandidate(metadata)) {
			beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
		}
		else if (isLiteConfigurationCandidate(metadata)) {
			beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
		}

       在Spring中通过这种方式来判断这个bd到底是不是一个配置类,也就是在这里判断配置类到底有没有加 @Configuration 注解,如果加了这个注解,则这个配置类最终将通过cglib进行动态代理!

BeanDefinition除了上面的两个接口之外,像上面UML图里面的,还有许多的实现类,这里会讲一下几个实现类

  • RootBeanDefinition:
    这个实现类经常被用作源码当中的载体,在对bd的封装和信息的处理过程中,大多数都使用了RootBeanDefinition作为载体。在几乎所有的Spring的内部类,都是使用了RootBeanDefinition作为载体将数据进行封装。
  • ChildBeanDefinition:
    这个实现类曾经是和RootBeanDefinition相对立的存在,在之前如果一个BeanDefinition设置了父BeanDefinition之后,子bd将会使用ChildBeanDefinition来装在类信息。而在现在,GenericBeanDefinition已经可以代替ChildBeanDefinition了
  • GenericBeanDefinition:
    见名知意,这是一个通用的bd,在我们自己写得类当中,几乎绝大多数的类,都是使用这个来封装类信息的!

       在Spring中还有许多的bd没有讲(详细可参见上面的UML类图),但是只要理解了这三个bd,其他的通过名字都可以很好的理解其作用和含义。

bd在源码当中的使用
在源码中有这样一个判断

//这三个方法都是调用BeanDefinition中的API
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
	......
}

1. 判断这个类是不是抽象类
2. 判断这个类是不是单例的
3. 判断这个类需不需要懒加载

       这只是BeanDefinition在源码中的冰山一角,源码中还有许多地方通过bd来获取类的信息,来实现对类更加丰富的实例化过程

可能会有一些人觉得,这些东西都不重要,更想知道Spring是怎么实例化一个bean
但是如果这些基础都不打好的话,想读懂Spring只能是囫囵吞枣
我虽然接触Java可能时间并不长,但是对于Spring源码前前后后读了三次,也看了很多书籍
但是之前的两次,都让我有一种我只读懂了代码的感觉,甚至有一些代码都读不懂!
所以在我踩了很多坑之后,想写一篇文章,可以让后来的人学得没那么费力。
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
BeanDefinitionSpring中的一个核心概念,它表示了一个Bean的定义。在Spring中,根据BeanDefinition来创建Bean对象。BeanDefinition具有很多属性用来描述Bean的信息和配置。 AnnotatedBeanDefinition是AnnotatedBeanDefinition接口的实现类,表示注解的BeanDefinition。它包含了注解元数据和基本类元数据的信息。AnnotatedBeanDefinition有两个主要的实现类:AnnotatedGenericBeanDefinition和ScannedGenericBeanDefinition。 RootBeanDefinition代表普通的BeanDefinition实现,通过直接实例化BeanDefinition对象来创建。ChildBeanDefinition代表可以设置父BeanDefinition的子BeanDefinition。GenericBeanDefinition代表一般的BeanDefinition,AnnotatedGenericBeanDefinition和ScannedGenericBeanDefinition都是它的两个主要实现类。 综上所述,BeanDefinitionSpring中用来描述Bean的定义的概念,它包含了Bean的各种属性和配置信息。AnnotatedBeanDefinition是注解的BeanDefinition的实现类,它包含了注解元数据和类元数据的信息。RootBeanDefinition和ChildBeanDefinitionBeanDefinition的不同实现方式,GenericBeanDefinition是一般的BeanDefinition,它的两个主要实现类是AnnotatedGenericBeanDefinition和ScannedGenericBeanDefinition。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [BeanDefinition](https://blog.csdn.net/xxssyyyyssxx/article/details/124819785)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值