Spring版本:
<version>5.2.1.RELEASE</version>
目录
上一篇:18-Spring源码解析之Bean的生命周期(3)——【doCreateBean】和【createBeanInstance】
上一篇我们讲解了doCreateBean
方法来创建Bean
实例,它首先调用createBeanInstance
方法来实例化Bean
,其次处理依赖问题,接着对该Bean
进行属性赋值(populateBean
)方法,再接着对Bean
进行初始化工作(initializeBean
),本篇文章就看一下Spring
是如何帮我们完成Bean
的初始化的。
一、initializeBean
还记得在实体类中我们通过实现InitializingBean
接口后需要重写afterPropertiesSet
方法吗?这个方法的执行时机就是在Bean
属性赋值(populateBean
)后调用initiali
在这里插入代码片zeBean
指定的方法来根据用户业务进行相应的实例化。
protected Object initializeBean(final String beanName, final 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()) {
//-------------------------------------------------【功能二】--三、 详细介绍----------------------------------------------
// 应用后处理器
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
//-------------------------------------------------【功能三】--四、 详细介绍----------------------------------------------
// 激活用户自定义的initMethod或者afterPropertiesSet方法
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()) {
//-------------------------------------------------【功能四】--五、 详细介绍----------------------------------------------
// 应用后处理器
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
从上面可以看出,该方法一共做了四件事情:
- 【功能一】激活
Aware
方法 - 【功能二】应用所有
BeanPostProcessor
的postProcessBeforeInitialization
方法 - 【功能三】调用用户自定义的
initMethod
或者afterPropertiesSet
方法 - 【功能四】应用所有
BeanPostProcessor
的postProcessAfterInitialization
方法
下面我们就来依次说一下这几个功能是如何实现的。
二、【功能一】激活Aware
方法
在分析这个功能实现的原理之前,我们需要先知道什么是Aware
以及它是干什么的。
Spring
中提供给了一些Aware
接口,比如:
而实现了对应Aware
接口的Bean
在实例化之后,可以获取一些相对应的资源,比如:实现了BeanFactoryAware
接口的Bean
在实例化之后,Spring
会给这个Bean
注入BeanFactory
实例,而实现了ApplicationContextAware
的Bean
,在在实例化之后,Spring
会给这个Bean
注入ApplicationContextAware
实例。我们首先通过示例的方式来了解一下Aware
的简单使用。
1.1 Aware
的例子
1.1.1 定义普通的Bean
package com.spring.aware;
import org.springframework.stereotype.Component;
@Component
public class Hello {
public void say() {
System.out.println("hello");
}
}
1.1.2 定义BeanFactoryAware
的实现类
package com.spring.aware;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.stereotype.Component;
@Component
public class BeanFactoryAwareTest implements BeanFactoryAware {
private BeanFactory beanFactory;
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
public void testAware() {
Hello hello = beanFactory.getBean(Hello.class);
hello.say();
}
}
1.1.3 配置类
@Configuration
@ComponentScan("com.spring")
public class MainConfig {
}
1.1.4 测试类
public class Test {
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
BeanFactoryAwareTest beanFactoryAwareTest = applicationContext.getBean(BeanFactoryAwareTest.class);
beanFactoryAwareTest.testAware();
}
}
1.1.5 测试结果
控制台输出:
hello
首先,我们要意识到一点,Spring
中代表容器的beanFactory
我们普通类是无法得到的,因为他是一个内部类。如果想要得到,我们需要增加一些操作。
接着,我们分析一下上述例子,Hello
类是一个普通类,通过Component
注解注册到容器中,BeanFactoryAwareTest
类是实现了BeanFactoryAware
接口,实现了这个接口后,我们需要实现setBeanFactory
方法,而这个方法会在BeanFactoryAwareTest
类在创建对应Bean
的初始化之前调用,即我们1.节
讲到的时候调用。这样,这个BeanFactoryAwareTest
类就得到了Spring
中代表容器的beanFactory
,并且可以根据得到的beanFactory
获取容器中所有的Bean
。
1.2 invokeAwareMethods
方法
现在知道了Aware
的作用后,我们就可以看看initializeBean
中调用invokeAwareMethods
方法,这个invokeAwareMethods
的具体实现了。
private void invokeAwareMethods(final String beanName, final Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
可以看到,实际上这个代码很简单,就是根据Bean
的类型来将对应类型的Bean
放到Bean
中。
因为刚刚1.1节
的例子实现的是BeanFactoryAware
接口,所以走到第三个if
判断条件的地方,然后调用setBeanFactory
方法,这个setBeanFactory
方法即我们1.1.2节
中的代码:
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
三、【功能二】applyBeanPostProcessorsBeforeInitialization
BeanPostProcessor
大家都不陌生,这是Spring
开放式架构中一个必不可少的亮点,给用户充足的权限去更改或者扩展Spring
,而除了BeanPostProcessor
外还有很多其他的PostProcessor
,当然大部分都是以此为基础,继承自BeanPostProcessor
。
而且在前面BeanPostProcessor
大家也有接触过,这里就不再详细的介绍了,而且代码很简单。
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
四、【功能三】invokeInitMethods
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {
//-------------------------------------------------【功能一】------------------------------------------------
// 判断当前Bean对应的实体类是否实现了InitializingBean接口
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isTraceEnabled()) {
logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((InitializingBean) bean).afterPropertiesSet();
return null;
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
// 若实现InitializeBean接口,就执行afterPropertiesSet方法
((InitializingBean) bean).afterPropertiesSet();
}
}
//-------------------------------------------------【功能二】------------------------------------------------
// 判断当前Bean对应的实体类没有实现InitializingBean接口,但是有initMethod方法,则执行它的initMethod方法
if (mbd != null && bean.getClass() != NullBean.class) {
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName) &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
从上面代码可以看出:@Bean(initMethod)
与afterPropertiesSet
都是在Bean
时执行的,执行顺序时afterPropertiesSet
先执行, @Bean(initMethod)
后执行。
五、总结
initializeBean
方法主要包含以下四个功能
- 【功能一】激活
Aware
方法 - 【功能二】应用所有
BeanPostProcessor
的postProcessBeforeInitialization
方法 - 【功能三】调用用户自定义的
initMethod
或者afterPropertiesSet
方法 - 【功能四】应用所有
BeanPostProcessor
的postProcessAfterInitialization
方法
到本篇结束,Bean
的生命周期就剩下DisposableBean
没有讲解了。DisposableBean
是提供了销毁方法的扩展入口。这个方法很简单,在以后会添加到之前的文章中。
下一篇讲解Spring
的一个非常重要的功能!依赖注入!在注解驱动中,就是与@Autowired
注解有关的知识。