然后,您必须掌握本文的内容。
本文主要解释了Bean的生命周期,该生命周期分为13个链接。在每个链接中,Spring提供了一些扩展点。我们将详细解释,让每个人都充分掌握该作品的知识。
这个阶段主要是豆信息的定义阶段。
首先,此方法,因为其他几种方法最终将使用此方法来定义BEAN配置信息。
在弹簧容器的开始期间,BEAN将被解析到弹簧内的BeanDefinition结构中。它是XML配置文件的标签,注释的配置或标记的类别或扫描类的标签,它最终将是解析为豆类定义对象。最后,实例,初始化和其他对BEAN的操作。
您可以将BeanDefinition扔给Bean Factory,然后Bean Factory将根据此信息帮助您生产Bean实例并使用它。
BeanDefinition包含由BEAN定义的各种信息,例如:类,范围,懒惰信息,依赖器信息,自动授权(是否是候选人),主要(是否是主要候选人)和其他信息。
BeanDefinition是一个接口,有几个实现类,请查看类图:
BeanDefinition接口:BEAN定义信息接口以表示BEAN定义信息的接口,该信息定义了各种获取BEAN定义配置信息的方法。查看源代码:
BeanDefinition接口还继承了两个接口:
attributeaccessor接口:属性访问接口
该接口等同于键 - >值数据结构的一种操作。BeanDefinition继承了这一点。内部实际上使用LinkedHashMap来实现此接口中的所有方法。通常,我们通过这些方法在豆定义定义过程中保留一些其他添加。
BeanMetadataelement接口查看其源代码:
BeanDefinition继承了此接口,GetSource返回BeanDefinition的源定义。例如,我们通过XML定义BeanDefinition。目前,getOrce表示BEAN的XML资源的定义;当类错误时,您可以根据此源来促进错误。
rootbeanDefinition类:指示根定义信息通常使用此指示,如果bean中没有父亲bean,
ChildBeanDefininion类:这意味着,如果孩子bean定义信息,如果您需要指定父bean,则可以使用condrybeandefinition来定义子bean的配置信息。其中有一个属性来指定父bean的名称。
通用定义类别:常规 - purpose bean定义信息可以表明没有父bean配置信息,也可以指示父bean的父bean配置信息。该类还具有parentname属性来指定父bean的名称。
ConfigurationClassBeanDefinition类:这意味着可以通过配置类中的@BEAN方法定义BEAN信息。您可以在配置类中使用@BEAN来标记某些方法。这些方法配置的BEAN信息将转换为ConfigurationClassBeanDefininion。
注释BeanDefinition界面:指示通过注释方法定义的BEAN信息中有一种方法
用于获取有关此Bean类的定义的所有注释。
BeanDefinitionBuilder:为了促进Build buide Beandefinition工具类中BeanDefinition的操作,一类提供了很多静态方法。通过这些方法,我们可以轻松地组装BeanDefinition对象。
案例1:将简单的豆组装成简单的类
测试用例
相当于
运行输出
案例2:组装属性bean代码
@1:致电AddPropertyValue设置汽车中名称的值
@2:创建一个弹簧容器
@3:将CarbeanDefinition的Bean配置信息注册到弹簧容器。Bean的名字是汽车
@4:在童话中获取这款豆子,最后输出
运行输出
第二行输出在童话容器中获得的BEAN实例对象。
情况3:再次组装依赖的豆。该课程中有一个汽车属性。我们通过春季注入此属性。
关键代码
@1:注入bean,您需要使用addPropertyReference方法,2个参数,第一个是属性的名称,第二个是您需要注入的bean的名称
以上代码等同于
运行输出
案例4:让2豆与父子关系
相当于
运行输出
情况5:在API设置(地图,设置,列表)属性下方,我们将演示注入列表,地图和集合,内部元素是普通类型和其他BEAN元素。
一类
注意:上面省略了GET和设置方法。记得在写作时为每个人弥补
首先使用XML定义复合obj的bean,如下
下面我们使用纯API实施,如下
有几点要说:
RuntimeBeanReference:它用于表示BEAN参考类型,类似于XML中的参考
托管清单:如果属性是列表类型,则需要使用此类进行操作。该类继承arraylist
托管集:如果属性设置了类型,则需要将此类使用进行操作。此类继承LinkedHashset
MANSTEDMAP:如果属性是映射类型,则需要使用此类进行操作。此类继承LinkedHashmap
以上是这些类别组合的结果。
查看效果,运行输出
该方法已经谈到了很多次,每个人都更熟悉,也就是说,bean由xml定义,如下
XML中的BEAN配置信息将由解析器解析为BeanDefinition对象,这将在第二阶段的第二阶段进行解释。
估计该方法不熟悉。将BEAN定义信息放在属性文件中,然后通过解析器分析配置信息到BeanDefinition对象。
属性内容格式如下:
2种常见类型:
Bean注册仅标识BeanDefinition对象。无论如何,这些豆定义的信息将转换为beandefinition对象,然后注册到弹簧容器。
BEAN形而上学信息的分析是分析以各种方式定义为BeanDefinition对象的BEAN配置信息。
Spring提供了一个将XML中定义为BeanDefinition对象定义的BEAN的类。
直接查看案例代码
这是bean XML配置文件
上面有4个豆子,没有太多解释。
将bean xml作为豆类定义对象付款
以上评论更详细,在这里不会说明。
注意:创建XMLBEANDEFINITINITIONREEDRER时,您需要传递BeanDefinitionRegistry,并且在分析过程中生成的BeanDefinition将被扔入BEAN注册表中。
运行输出
看看上面的输出。这些豆类定义就是所有这些,也就是说,XML中定义的豆在解析后用这种类型表示。
Spring提供了一个类,将XML中定义为BeanDefinition对象定义的BEAN分析。该过程类似于XML方法。
查看案例代码。
下面,由上述XML方法定义的BEAN由属性文件实现。
让我们附带一个属性文件:beans.properties
将bean属性文件分析为beandefinition对象
运行输出
输出和XML输出基本上是一致的。
属性方法不太方便,因此我们很少看到有人在使用它。
需要使用注释方法定义的豆类使用属性类别beandefinitinitinitinitinitinitininitininitininininininininininininininireadereareader进行分析。该方法类似于上述两种方式。直接看案件。
通过注释,标记两种类型的服务1
该课程使用三个注释。这些注释早些时候介绍了,可用于配置Bean的信息
以上豆是多种情况。
服务2
@1:标记@Autowired,指示您需要注入此对象
注释定义的BEAN分析是BeanDefinition,如下:
运行输出
可以在输出中可以看出,在beandefinition的beandefinition中的懒惰确实是正确的,主体也是正确的,范围是原型,这表明三个注释信息在beandefinition中标记为标记。
注意:为什么在最后一行中service1?
这个地方提前破坏了。是否不理解它都没关系。本文结束后,您了解。
调整上述代码,以及以下@1代码,如下:
再次运行,最后一行值得:
目前,有14个阶段。有14个阶段。本文的内容相对较长。建议先收集它。慢慢看。让我们继续。
BEAN注册阶段需要使用一个非常重要的接口:BeanDefinitionRegistry
该接口定义了注册Bean常用的一些方法。源代码如下:
接口继承了接口。该界面定义了一些操作Bean别名的方法。查看源代码:
Spring的BeanDefinitionRegistry界面中有一个唯一的实现类:
您可能会看到,有许多类别也实现了接口。例如,我们经常使用它,但实际上,它已重新播放到处理,因此真正意识到该界面的类。
每个人都回头看开头的开始,所有这些开始都用作豆寄存器。目前,您应该能够理解原因。
让我们采取案例来演示上面的一些常见方法。
代码
运行输出
以下内容从第4阶段到第14阶段,也就是说,从:从以下方式进行,通过在GetBean的GetBean校准中获取Bean对象发送的操作,请注意。源代码,以下过程来自此方法:
也许当我们定义Bean时,父子之间存在关系。目前,BeanDefinition中的信息不完整。例如,设置属性时,在父亲beandefinition中配置。目前,Child BeanDefinition中没有信息。BeanDefinition和Bean Bean的BeanDefinition合并以获取最后一个。合并后,获得了BEAN定义的所有信息,其中包含来自父亲Bean Relay.ongoing的所有信息。
以下方法将通过合并beandefinition使用:
Bean定义了多层父亲 - 森关系。合并合并时,递归合并,最后获得包含完整信息的rootbeanDefinition
来到普通班
定义与XML的父亲关系的3个豆
第2课等同于第1课的儿子,第三课等同于第1课的孙子。
分析下面的XML注册BEAN将分析XML,注册BEAN,然后穿越Bean的名称,在分析过程中注册的原始BeanDefinition,合并后的BeanDefinition以及合并之前和之后的BeanDefinition的属性信息
运行输出
从输出结果可以看出,在合并之前,BeanDefinition不完整,课程2和第3课中的类是无效的,并且属性信息不完整,但是在合并后,信息完成了。
在合并之前,是在合并后获得的。
在获得课程3的BeanDefinition时,将合并内部递归合并。首先合并课程1和第2课,然后将课程2与课程3合并。最后,获得了beandefinition。
随后的阶段将用于使用rootbeanDefinition。
此阶段是将BEAN的类名称转换为类类型的对象。
BeanDefinition中有一个对象类型字段:BeanClass
它用于表示bean的类对象。通常,该字段的值有两种类型,一个是与Bean相对应的类类型的对象,另一个是与Bean相对应的类的完整类名称。第二种情况:此字段是bean的名称为需要通过类加载程序将其转换为类对象。
目前,将分析对第4阶段合并的分析,并将BEAN的类名称转换为字段。
源代码位置:
在上面获得了Bean类对象和合并后的BeanDefinition,以下将开始进入实例化对象的阶段。
BEAN实例分为3个阶段:以前的阶段,实例化阶段和阶段;下面的详细介绍。
让我们首先看一下,在此类别中有一个非常非常重要的领域:
是一种系列
BeanPostProcessor是一个接口,并且有许多子接口。这些接口提供了许多方法。在Bean生命周期的不同阶段,Spring会在上面列表中的BeanPostProcessor中调用一些方法来扩大生命周期。周期中的豆类生命iSall扩展依赖于该系列中的BeanPostProcessor来实现它,因此,如果您想干预Bean的生命周期,则必须掌握此作品。
注意:本文中的许多BeanPostProcessor实现了BeanPostProcessor接口,其中一些是直接实现的,其中一些实现了其子接口。
BEAN在实例化之前将调用一部分代码:
该代码在豆实例化之前给开发人员留下了嘴。开发人员可以直接在此位置作为Bean实例创建一个对象,并跳过Spring内部的实例化bean的过程。
在上面的代码中,如果类型为,请尝试调用bean的实例对象。如果您可以得到它,则将返回值用作当前bean的实例,然后将实例化的bean过程带有弹簧,则跳过了。
如下:
这个地方为开发人员提供了一个扩展点,使开发人员可以直接在此方法中返回BEAN实例。
让我们看一个案子。
案件
@1:创建一个InstantiawareBeanBeanPostProcessor,然后将其扔到容器中的BeanPostProcessor列表中
@2:创建了一辆汽车豆,名称是奥迪
运行输出
定义bean时,名称为:奥迪,最终输出为:保时捷
定义和输出不一致的原因是因为我们在方法中手动创建一个直接返回的实例,而不是依靠内部弹簧来创建此实例。
实际上,实际上,在预先实现的阶段创造Bean的创作非常小,因此大多数Bean的创造将继续下一个阶段。
在此过程中我该怎么办?此过程将称为Bean的构造函数来创建BEAN实例。
需要使用哪个构造函数,Spring为开发人员提供了一个接口,该接口允许开发人员确定使用哪个构造函数。
看一下此作品的代码逻辑:
调用方法,此方法将返回候选构造函数列表,您也可以返回到空,请参阅此方法的源代码:
该方法具有更重要的实施类
您可以将标记方法作为候选构造函数返回。如果您有兴趣,可以查看代码。
就案件而言,我们来定制注释。当构造函数以此注释为标记时,让Spring自动选择使用此构造函数来创建对象。
自定义注释。以下注释可以在构造函数上标记。使用此标签后,创建bean时将使用此构造函数。
出现一个普通的类,以下3个构造函数,其中一个用作Bean实例化的方法。
自定义smartinstantiawarebeanbeanpostProcessor代码逻辑:返回标记的构造函数列表
让我们服用测试案例
运行输出
从输出可以看出,构造函数被称为@myautowired。
到目前为止,豆的实例化阶段已经结束,并继续进入后期。
该作品的源代码如下
将调用该方法以查看此方法的源代码:
春季将询问,打电话
第一个参数是BeanDefinition,这是指合并的rootbeanDefinition。我们可以在此方法中合并后处理
有两个用于后处理的实施类。我们已经介绍了它,并使用了更多。我经常在面试时问:
调用接口的方法,调用逻辑如下:
查看特定的呼叫逻辑,如下:
当返回false时,将跳过处理之前的后续BEAN属性分配和BEAN属性分配。
看一下此方法的定义
查看情况,在情况下返回false,然后跳过属性的分配。
班级的情况
测试案例非常简单,让我们注册一个usermodel bean
上面定义的2个bean:[user1,user2],获得后输出
运行输出
目前,UserModel中的两个属性值得。
让我们防止用户的分配,转换代码并添加以下代码:
再次运行测试输出:
User1的属性分配被跳过。
在此阶段,调用接口,调用逻辑的方法:
从上面可以看出,当中国人和两者都返回空中时,这意味着该豆不需要设置属性,直接返回,直接进入下一阶段。
看一下此方法的定义:
属性值保留了Bean实例对象中所有属性值的设置,因此我们可以在此方法中修改属性值。
该方法具有两个更重要的实施类别类别,该方法在此方法中以@autowired标记的字段和方法注入值,@value.commonannantationbeantationbeanpostprocessor在此方法中,字段和方法注入值在@resource.come.come.come.come.come.come.come.come.come.come.come come come case a case a case。案例的PV。
案例代码
@1:user1此bean未设置属性的值
@0:org.springframework.beans.factory.config.instantiawarebeanbeanpostProcessor#后Prosproperperties的此实现,以修改Beaan内部的属性信息。
运行输出
上述过程还可以,输入bean分配操作
这个过程相对简单。周期处理中的属性信息设置为通过反映集合方法来设置属性到BEAN实例的值。
属性值中的值由Bean XML中的属性元素配置,或调用由Mutable PropertyValues中的add方法设置设置的值。
该作品的源代码:
如果我们的BEAN实例实现了上述接口,则将按以下顺序调用:
让我们感到一个案子
上课,意识到上述三个接口。
让我们上一个测试课,创建上述对象的豆
运行输出
此阶段的源代码:
该方法将被调用,如果返回null,当前方法将结束。
该方法通常称为后处理。
该接口中有两个实现类,更重要:
ApplicationContextawareProcessor注入6个意识接口对象。如果Bean实现以下接口,请在中间会议中的下面接口中调用该方法,然后将前缀注入Bean实例。
可以从此类开始的名称中可以看出,表明此类只能在环境中使用。
commonAnnotationBeanPostProcessor调用@postConstruct标签,您将调用BEAN中标记为@postConstruct and的所有方法
案子并感受到它。
该情况下有两种方法,并且上述六个意识的接口已实现。
来测试案例
运行输出
您可以查看AnnotationConfigapplicationContext的源代码,这将为它增加很多。
2个步骤调用初始化界面的AfterPropertiesset方法
当我们的bean实现此界面时,将在此阶段调用
调用bean定义时,bean的指定初始化方法首先查看如何指定bean的初始化方法。
方法1:XML方法指定初始化方法
方法2: @bean的方法指定初始化方法
方法3:API方法指定初始化方法
初始化方法最终将为以下字段分配一个值
班级的情况
下面我们定义服务bean,将初始方法指定为初始化方法
运行输出
呼叫订单:初始化中的propertiesset,然后调用自定义初始化方法
该作品的源代码:
返回NULL时致电并返回操作。
通常称为后处理方法:操作后初始化BEAN。
来吧:
运行输出
所有单身豆是实例化的,Spring将回电以下接口:
以以下方法调用逻辑
该方法将首先触发非删除加载的所有单个case bean初始化,然后在退伍军人中找到bean的类型,然后调用它们的方法。
如果您有兴趣,可以查看带有ApplicationContext的容器。最后,将调用上述方法以触发所有单个bean的初始化。
让我们有两种案例来证明使用智能化的使用。
服务1:
服务2:
自定义智能化元素
参加测试课,通过扫描注册以上3个豆子
运行输出
通过上面的API方法注册bean
最后,调用所有非流行单曲初始化。毕竟Bean组装了,您将回电SmartInitializationingingleton界面。
我不会说这个阶段。调用GetBean方法获取BEAN后,每个人都可以随意使用它并任意播放。
查看源代码:
该接口中有一个关键实现类:
commonAnnotationBeanPostProcessor#postprocessbeforeDruction方法将调用bean中的所有@predestroy方法。
方法1:在XML中指定破坏方法
方法2:在@BEAN中指定破坏方法
方法3:API方法指定破坏方法
初始化方法最终将为以下字段分配一个值
让我们看一下案件
一类
定制DestructionWareBeanPostProcessor
让我们参加考试课
上述方法用于触发bean的破坏[@1和@2]
运行输出
您可以看到,后期贝斯福利德术语被称为3次,又销毁了三个定制的bean
上面的注释在中间处理,因此您只需要将其添加到BeanPostProcessor列表中。
再次凯特
@1:Mark @predestroy注意
测试用例
@1:放置自定义DestructionBeanPostProcessor
@2:将其放入CommonNotionPostProcessor,它将处理Bean Note @predestroy注释的方法
查看效果运行输出
实际上,ApplicationContext已在弹簧内部自动组装,例如以下内容:我们很熟悉:我们很熟悉
因此,要通过ApplicationContext销毁Bean,这将触发3种中文式的执行。
在下面,我们将通过AnnotationConfigapplicationContext演示破坏操作。
这里是一堂课
上面有2种标记为@predestroy的方法
该类实现可支配BEAN接口,重写接口中的销毁方法
@1:此destroymethod将通过@BEAN注释方法将其指定为自定义方法。
看测试用例
上面的类带有@configuration标记,表明它是一个配置类,内部有@Bean标记的方法,表明使用此方法定义bean。
@1:定制destroymethod指定为带有destroymethod属性的自定义破坏方法
@2:关闭容器并触发豆破坏操作
来运行test1,输出
可以看出,破坏方法的顺序调用:
这是一个非常非常重要的课程。起床,您必须注意它。
看一下UML图:
![图片]()
我们已经熟悉了豆厂的顶级接口
实现了BeanFactory接口。可以说,这可能是beanFactory接口的唯一真实实现。生命周期中的所有代码都是在内部真正实施的。
其他一些类取决于DefaultListableBeanFactory类,并将请求转发到defaultListableBeanFactory用于BEAN处理。
这堂课还有2种重要的方法
您是否注意到,当我们使用它时,他们经常将其称为,并且这两种方法将在此方法中被调用。
第一个方法:getBeanFactory()返回当前应用程序的上下文,这也是接口类型。该界面具有独特的实现类:
上面提到的是否有任何熟悉:DefaultListableBeanFactory是BeanFactory的唯一真实实现。
这在在线文章中用于操作弹簧容器。
查看此方法的源代码:
该请求将转发到。
内部相对较长。您可以查看源代码。此方法主要使用4种列表集合。
首先让我们谈谈:当方法是方法时,所有BEAN的注册都已在弹簧容器中完成。
Spring将在童话容器中找到所有类型的BeanPostProcessor的BeanPostProcessor列表,然后将其放在以下规则上方的4组中。在这4集中,将添加到DefaultListableBeanFactory#BeanPostProcessors列表中,让我们看一下。这四个集合是那些BeanPostProcessor的分离:
PriortyoredPostProcessor(特别是BeanPostProcessor)实现了org.springframework.core.core.priorityomed界面,但不包括MergeDBeanDefinitionProcesor类型
上述2中的非债券postProcessor(BeanPostProcessor)放置在上述2中,并且
InternalPostProcesssrsmergedBeanDefinitionItionPostProcesor type beanPostProcessor列表。
你可以看看他。这两个类别都达到了接口,但它们也实现了界面,因此最终将被投入到该集合中,并将将它们放在BeanPostProcessor的末尾。