- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章Spring源码解析之Bean的生命周期由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
前一篇分析了BeanDefinition的封装过程,最终将beanName与BeanDefinition以一对一映射关系放到beanDefinitionMap容器中,这一篇重点分析如何利用bean的定义信息BeanDefinition实例化bean.
其实bean的实例化过程比较复杂,中间细节很多,为了抓住重点,先将核心流程梳理出来,主要包含以下几个流程:
step1
: 通过反射创建实例;step2
:给实例属性赋初始值;step3
:如果Bean类实现BeanNameAware接口,则将通过传递Bean的名称来调用setBeanName()方法;如果Bean类实现BeanClassLoaderAware接口,则将通过传递加载此Bean的ClassLoader对象的实例来调用setBeanClassLoader()方法;如果Bean类实现BeanFactoryAware接口,则将通过传递BeanFactory对象的实例来调用setBeanFactory()方法;step4
: 如果有类实现BeanPostProcessors接口,则将在初始化之前调用postProcessBeforeInitialization()方法;step5
:如果Bean类实现了InitializingBean接口,将调用afterPropertiesSet()方法,如果配置文件中的Bean定义包含init-method属性,则该属性的值将解析为Bean类中的方法名称,并将调用该方法;step6
: 如果有类实现BeanPostProcessors接口,则将在初始化之后调用postProcessAfterInitialization()方法;step7
:如果Bean类实现DisposableBean接口,则当Application不再需要Bean引用时,将调用destroy()方法;如果配置文件中的Bean定义包含destroy-method属性,那么将调用Bean类中的相应方法定义。进入AbstractApplicationContext中的fresh()方法,找到finishBeanFactoryInitialization(beanFactory)方法,该类是bean的实例化的入口,具体的实例化由preInstantiateSingletons()方法触发,见如下代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
public
void
preInstantiateSingletons()
throws
BeansException
if
(logger.isTraceEnabled()) {
logger.trace(
"Pre-instantiating singletons in "
+
this
);
}
// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
//xml解析时,把所有beanName都缓存到beanDefinitionNames了
List<String> beanNames =
new
ArrayList<>(
this
.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
for
(String beanName : beanNames) {
//把父BeanDefinition里面的属性拿到子BeanDefinition中
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
//如果不是抽象的,单例的,非懒加载的就实例化
if
(!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
//判断bean是否实现了FactoryBean接口
if
(isFactoryBean(beanName)) {
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if
(bean
instanceof
FactoryBean) {
FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean
isEagerInit;
if
(System.getSecurityManager() !=
null
&& factory
instanceof
SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(
(PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
}
else
{
isEagerInit = (factory
instanceof
SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if
(isEagerInit) {
getBean(beanName);
}
}
}
else
{
// 实例化过程
getBean(beanName);
}
}
}
|
上述代码主要看getBean方法,随后进入doGetBean方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
|
protected
<T> T doGetBean(
String name,
@Nullable
Class<T> requiredType,
@Nullable
Object[] args,
boolean
typeCheckOnly)
throws
BeansException {
String beanName = transformedBeanName(name);
Object bean;
// 从缓存中获取bean.
Object sharedInstance = getSingleton(beanName);
if
(sharedInstance !=
null
&& args ==
null
) {
if
(logger.isTraceEnabled()) {
if
(isSingletonCurrentlyInCreation(beanName)) {
logger.trace(
"Returning eagerly cached instance of singleton bean '"
+ beanName +
"' that is not fully initialized yet - a consequence of a circular reference"
);
}
else
{
logger.trace(
"Returning cached instance of singleton bean '"
+ beanName +
"'"
);
}
}
bean = getObjectForBeanInstance(sharedInstance, name, beanName,
null
);
}
else
{
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
if
(isPrototypeCurrentlyInCreation(beanName)) {
throw
new
BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
BeanFactory parentBeanFactory = getParentBeanFactory();
if
(parentBeanFactory !=
null
&& !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
if
(parentBeanFactory
instanceof
AbstractBeanFactory) {
return
((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else
if
(args !=
null
) {
// Delegation to parent with explicit args.
return
(T) parentBeanFactory.getBean(nameToLookup, args);
}
else
if
(requiredType !=
null
) {
// No args -> delegate to standard getBean method.
return
parentBeanFactory.getBean(nameToLookup, requiredType);
}
else
{
return
(T) parentBeanFactory.getBean(nameToLookup);
}
}
if
(!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try
{
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
String[] dependsOn = mbd.getDependsOn();
if
(dependsOn !=
null
) {
for
(String dep : dependsOn) {
if
(isDependent(beanName, dep)) {
throw
new
BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '"
+ beanName +
"' and '"
+ dep +
"'"
);
}
registerDependentBean(dep, beanName);
try
{
getBean(dep);
}
catch
(NoSuchBeanDefinitionException ex) {
throw
new
BeanCreationException(mbd.getResourceDescription(), beanName,
"'"
+ beanName +
"' depends on missing bean '"
+ dep +
"'"
, ex);
}
}
}
// Create bean instance
// 创建bean实例
if
(mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try
{
return
createBean(beanName, mbd, args);
}
catch
(BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw
ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
...
}
|
由上述代码可知,先从缓存中获取bean,如果没有,则创建bean,最重要的方法就是getSingleton,该方法第二个参数是个函数式接口,进入getSingleton方法,当调用singletonObject = singletonFactory.getObject()时,会触发函数式接口中的createBean方法,随后一路进入doCreateBean,这个方法里面完成了所有实例化所需的步骤
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
|
protected
Object doCreateBean(String beanName, RootBeanDefinition mbd,
@Nullable
Object[] args)
throws
BeanCreationException {
// Instantiate the bean.
// 真正开始创建bean的实例.
BeanWrapper instanceWrapper =
null
;
if
(mbd.isSingleton()) {
instanceWrapper =
this
.factoryBeanInstanceCache.remove(beanName);
}
if
(instanceWrapper ==
null
) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if
(beanType != NullBean.
class
) {
mbd.resolvedTargetType = beanType;
}
// Allow post-processors to modify the merged bean definition.
synchronized
(mbd.postProcessingLock) {
if
(!mbd.postProcessed) {
try
{
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch
(Throwable ex) {
throw
new
BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed"
, ex);
}
mbd.postProcessed =
true
;
}
}
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
boolean
earlySingletonExposure = (mbd.isSingleton() &&
this
.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if
(earlySingletonExposure) {
if
(logger.isTraceEnabled()) {
logger.trace(
"Eagerly caching bean '"
+ beanName +
"' to allow for resolving potential circular references"
);
}
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try
{
// 属性赋值
populateBean(beanName, mbd, instanceWrapper);
// 初始化bean
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch
(Throwable ex) {
if
(ex
instanceof
BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw
(BeanCreationException) ex;
}
else
{
throw
new
BeanCreationException(
mbd.getResourceDescription(), beanName,
"Initialization of bean failed"
, ex);
}
}
if
(earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName,
false
);
if
(earlySingletonReference !=
null
) {
if
(exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else
if
(!
this
.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans =
new
LinkedHashSet<>(dependentBeans.length);
for
(String dependentBean : dependentBeans) {
if
(!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if
(!actualDependentBeans.isEmpty()) {
throw
new
BeanCurrentlyInCreationException(beanName,
"Bean with name '"
+ beanName +
"' has been injected into other beans ["
+
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been "
+
"wrapped. This means that said other beans do not use the final version of the "
+
"bean. This is often the result of over-eager type matching - consider using "
+
"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example."
);
}
}
}
}
// Register bean as disposable.
// 有必要时,注册bean的销毁
try
{
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch
(BeanDefinitionValidationException ex) {
throw
new
BeanCreationException(
mbd.getResourceDescription(), beanName,
"Invalid destruction signature"
, ex);
}
return
exposedObject;
}
|
从上述源码中看出bean的实例化主要分为以下三步:
step1
:bean的创建;step2
:给bean的属性赋值;step3
:bean的初始化;接着得到exposedObject这个已经完全实例化后的bean返回,其中当有必要时,注册bean的销毁,后面再详细看,先抓住主要流程。其中step3也是比较重要的方法,进入该方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
protected
Object initializeBean(String beanName, Object bean,
@Nullable
RootBeanDefinition mbd) {
if
(System.getSecurityManager() !=
null
) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return
null
;
}, getAccessControlContext());
}
else
{
// 激活aware接口
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if
(mbd ==
null
|| !mbd.isSynthetic()) {
// 初始化前处理的beanPostProcessor
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try
{
// 激活 init-method方法
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch
(Throwable ex) {
throw
new
BeanCreationException(
(mbd !=
null
? mbd.getResourceDescription() :
null
),
beanName,
"Invocation of init method failed"
, ex);
}
if
(mbd ==
null
|| !mbd.isSynthetic()) {
// 初始化后处理的beanPostProcessor
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return
wrappedBean;
}
|
从上面源码可知,梳理出主要的四个步骤:
step1
:激活aware接口,完成aware接口的相关操作;step2
:初始化前处理的beanPostProcessor;step3
:完成init-method方法;step4
:初始化后处理的beanPostProcessor;BeanPostProcessor作用是对初始化后的bean进行增强处理,在该阶段 BeanPostProcessor 会处理当前容器内所有符合条件的实例化后的 bean 对象。它主要是对 Spring 容器提供的 bean 实例对象进行有效的扩展,允许Spring在初始化 bean 阶段对其进行定制化修改,如处理标记接口或者为其提供代理实现.
定义一个MyBeanPostProcessor实现BeanPostProcessor接口 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
public
class
MyBeanPostProcessor
implements
BeanPostProcessor {
@Override
public
Object postProcessBeforeInitialization(Object bean, String beanName)
throws
BeansException {
System.out.println(
"post Process Before Initialization 被调用..."
);
return
bean;
}
@Override
public
Object postProcessAfterInitialization(Object bean, String beanName)
throws
BeansException {
System.out.println(
"post Process after Initialization 被调用..."
);
return
bean;
}
}
|
定义一个LifeCycleBean类,实现如下接口:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
|
public
class
LifeCycleBean
implements
BeanNameAware, BeanFactoryAware, BeanClassLoaderAware,
InitializingBean, DisposableBean {
private
String property;
public
String getProperty() {
return
property;
}
public
void
setProperty(String property) {
System.out.println(
"属性注入...."
);
this
.property = property;
}
public
LifeCycleBean(){
System.out.println(
"构造函数调用..."
);
}
@Override
public
void
setBeanClassLoader(ClassLoader classLoader) {
System.out.println(
"BeanClassLoaderAware 被调用..."
);
}
@Override
public
void
setBeanFactory(BeanFactory beanFactory)
throws
BeansException {
System.out.println(
"BeanFactoryAware 被调用..."
);
}
@Override
public
void
setBeanName(String name) {
System.out.println(
"BeanNameAware 被调用..."
);
}
@Override
public
void
destroy()
throws
Exception {
System.out.println(
"DisposableBean destroy 被调用..."
);
}
@Override
public
void
afterPropertiesSet()
throws
Exception {
System.out.println(
"InitializingBean afterPropertiesSet 被调用..."
);
}
public
void
initMethod(){
System.out.println(
"init-method 被调用..."
);
}
public
void
destroyMethod(){
System.out.println(
"destroy-method 被调用..."
);
}
public
void
display(){
System.out.println(
"方法调用..."
);
}
}
|
指定配置文件spring.xml,配置init-method与destroy-method方法 。
1
2
3
4
5
6
|
<bean id=
"lifeCycle"
class
=
"com.wzj.bean.LifeCycleBean"
init-method=
"initMethod"
destroy-method=
"destroyMethod"
>
<property name=
"property"
value=
"property"
/>
</bean>
<bean id=
"myBeanPostProcessor"
class
=
"com.wzj.bean.MyBeanPostProcessor"
>
</bean>
|
测试类如下:
1
2
3
4
5
6
7
8
9
|
@RunWith
(SpringJUnit4ClassRunner.
class
)
@ContextConfiguration
(locations = {
"classpath:spring.xml"
})
public
class
TestSpring {
@Test
public
void
testLifeCycleBean() {
ClassPathXmlApplicationContext context =
new
ClassPathXmlApplicationContext(
"spring.xml"
);
}
|
执行结果:
构造函数调用... 属性注入.... BeanNameAware 被调用... BeanClassLoaderAware 被调用... BeanFactoryAware 被调用... post Process Before Initialization 被调用... InitializingBean afterPropertiesSet 被调用... init-method 被调用... post Process after Initialization 被调用... DisposableBean destroy 被调用... destroy-method 被调用... 。
本篇从一个初学者的角度概览了bean的整个生命周期,并描述了其中的主要流程,阅读源码的初始阶段,优先抓住主要流程,别陷入细节,并通过跑案例、写注解、画流程图等方式加深理解,后续将继续分析bean实例化中的核心流程、设计思想等.
到此这篇关于Spring源码解析之Bean的生命周期的文章就介绍到这了,更多相关Bean的生命周期内容请搜索我以前的文章或继续浏览下面的相关文章希望大家以后多多支持我! 。
原文链接:https://www.cnblogs.com/father-of-little-pig/p/14927428.html 。
最后此篇关于Spring源码解析之Bean的生命周期的文章就讲到这里了,如果你想了解更多关于Spring源码解析之Bean的生命周期的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
ACO.Visualization项目 本项目演示蚁群算法求解旅行商问题的可视化过程,包括路径上的信息素浓度、蚁群的运动过程等。项目相关的代码:https://github.com/anycad/A
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
我需要用Sql数据库制作并包含的PHP票务系统源码用户客户端和管理员。我需要个人 CMS 的这个来源。谢谢你帮助我。 最佳答案 我在不同的情况下使用了 osticket。 这里: http://ost
我的场景:我想在日志文件中写入发生异常的部分代码(例如,发生异常的行前 5 行和行后 5 行 - 或者至少是该方法的所有代码)。 我的想法是用 C# 代码反编译 pdb 文件,并从该反编译文件中找到一
RocketMQ设定了延迟级别可以让消息延迟消费,延迟消息会使用 SCHEDULE_TOPIC_XXXX 这个主题,每个延迟等级对应一个消息队列,并且与普通消息一样,会保存每个消息队列的消费进度
先附上Hystrix源码图 在微服务架构中,根据业务来拆分成一个个的服务,服务与服务之间可以相互调用(RPC),在Spring Cloud可以用RestTemplate+Ribbon和
此篇博客学习的api如标题,分别是: current_url 获取当前页面的url; page_source 获取当前页面的源码; title 获取当前页面的titl
? 1 2
1、前言 作为一个数据库爱好者,自己动手写过简单的sql解析器以及存储引擎,但感觉还是不够过瘾。<<事务处理-概念与技术>>诚然讲的非常透彻,但只能提纲挈领,不能让你
gory"> 目录 运行时信号量机制 semaphore 前言 作用是什么 几个主要的方法 如何实现
自己写的一个评论系统源码分享给大家,包括有表情,还有评论机制。用户名是随机的 针对某一篇文章进行评论 function subcomment() {
一、概述 StringBuilder是一个可变的字符串序列,这个类被设计去兼容StringBuffer类的API,但不保证线程安全性,是StringBuffer单线程情况下的一个替代实现。在可能的情
一、概述 System是用的非常多的一个final类。它不能被实例化。System类提供了标准的输入输出和错误输出流;访问外部定义的属性和环境变量;加载文件和库的方法;以及高效的拷贝数组中一部分元素
在JDK中,String的使用频率和被研究的程度都非常高,所以接下来我只说一些比较重要的内容。 一、String类的概述 String类的声明如下: public final class Str
一、概述 Class的实例代表着正在运行的Java应用程序的类和接口。枚举是一种类,而直接是一种接口。每一个数组也属于一个类,这个类b被反射为具有相同元素类型和维数的所有数组共享的类对象。八大基本树
一、概述 Compiler这个类被用于支持Java到本地代码编译器和相关服务。在设计上,这个类啥也不做,他充当JIT编译器实现的占位符。 放JVM虚拟机首次启动时,他确定系统属性java.comp
一、概述 StringBuffer是一个线程安全的、可变的字符序列,跟String类似,但它能被修改。StringBuffer在多线程环境下可以很安全地被使用,因为它的方法都是通过synchroni
一、概述 Enum是所有Jav中枚举类的基类。详细的介绍在Java语言规范中有说明。 值得注意的是,java.util.EnumSet和java.util.EnumMap是Enum的两个高效实现,
一、概述 此线程指的是执行程序中的线程。 Java虚拟机允许应用程序同时执行多个执行线程。 每个线程都有优先权。 具有较高优先级的线程优先于优先级较低的线程执行。 每个线程可能也可能不会被标记为守
一、抽象类Number 类继承关系 这里面的原子类、BigDecimal后面都会详细介绍。 属性和抽象方法 二、概述 所有的属性,最小-128,最大127,SIZE和BYTES代码比
我是一名优秀的程序员,十分优秀!