Spring从一个Bean定义变成容器中可以使用的Bean实例的过程,称为Spring中Bean的生命周期,Spring的Bean定义可以参考上篇文章《深入理解Spring中的Bean定义》。本篇文章将结合Spring初始化过程中的部分源码介绍如何从一个Bean定义变成一个可以使用的Bean实例。
从Bean定义变为可用的Bean实例的主要步骤如下图所示:
上图中介绍了从Bean定义注册中心拿到一个Bean定义之后,是如何变为一个可以使用的Bean的关键步骤。其中和Bean的生命周期有关的重要步骤为如下的几步:
一、Bean实例化 bean的实例化,调用的是AbstractAutowireCapableBeanFactory工厂类的createBeanInstance方法,其核心源码如下:protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// 解析Bean的class类型
Class> beanClass = resolveBeanClass(mbd, beanName);
// 如果Bean不是public,而且是不允许共有权限访问,直接抛出异常.
if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
throw exception; // 省略异常...
}
/**
* 通过指定的回调方法去创建bean实例,Spring5.0版本之后新增的方法。
* 创建完成之后,会在初始化的时候指定bean的属性值转换器。即:ConversionService
*/
Supplier> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
/**
* 如果当前bean指定了对应的工厂方法,则通过工厂方法去创建bean实例
* 底层会获取工厂方法【静态工厂方法|实例化方法】--> 然后解析方法入参 --> 然后执行反射调用创建实例 --> 封装为包装对象返回.
*/
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
/** 表示构造函数的参数是否已经解析妥当 */
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
if (resolved) {
/** 如果构造函数的参数已经解析妥当 */
if (autowireNecessary) {
/** 则通过构造函数完成实例的创建 */
return autowireConstructor(beanName, mbd, null, null);
}
else {
/**
* 使用默认的bean对象创建策略进行bean对象的创建
* 【设计模式:策略设计模式】
*/
return instantiateBean(beanName, mbd);
}
}
/** 推断构造方法,获取候选的用来创建bean对象的构造函数 */
Constructor>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
// 获取到了构造函数 || 注入模式为使用构造函数 || bean定义中指定了带参数的构造函数 || 创建bean对象时的入参args[参数列表对应的值列表]不为null
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
// 使用构造函数及入参进行bean对象的创建
return autowireConstructor(beanName, mbd, ctors, args);
}
/** 获取指定的用来创建bean对象的默认构造函数 */
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
return autowireConstructor(beanName, mbd, ctors, null);
}
/**
* 如果上述情况都没有:没有创建bean的回调方法 && 没有工厂方法 && 构造函数的参数未解析完毕 && 没有预先指定的默认构造函数
* 则使用默认策略来创建bean对象
*/
return instantiateBean(beanName, mbd);
}
从代码中可以看到,Bean实例的创建过程也并不是直接使用构造方法new出来这么简单。在Spring中,创建实例的方法常用有三种:构造方法、工厂方法和工厂Bean。而构造方法中又可能存在着多个重载的构造方法,具体使用哪一个,在该方法中会有一个推断过程,根据入参参数去反射调用参数列表相同的构造方法;如果使用工厂方法,则也会根据参数列表去调用特定的工厂方法;如果使用工厂Bean的方法,即:要创建的Bean实现了FactoryBean接口,则在此处会回调FactoryBean的getObject方法去创建Bean实例。通常在中间件开发中,会使用到该接口去创建一些定制化的Bean。
二、预解析注解元数据 在项目中,常用的注解例如:@Autowired,@Resource,@Required,@PostConstruct、@Scheduled等会在此处通过容器中默认的后置处理器去进行预解析,然后放入到元数据缓存中,在后期进行依赖注入的时候,会使用到该元数据信息去完成依赖关系确定以及依赖注入。此处主要有如下几个可能会执行的后置处理器:3.1 AutowiredAnnotationBeanPostProcessor
主要用来解析@Autowired和@Inject注解元数据。
3.2 CommonAnnotationBeanPostProcessor
主要用来解析@Resource注解元数据。
3.3 RequiredAnnotationBeanPostProcessor
主要用来解析@Required注解元数据。
3.4 InitDestroyAnnotationBeanPostProcessor
主要用来解析@PreDestroy和@PostConstruct注解元数据。该注解是用来标注方法的,但是标注的方法此处并不会执行。
3.5 ScheduledAnnotationBeanPostProcessor
如果项目中开启了任务调度,则该后置处理器会去解析@Scheduled注解元数据。
该过程调用的是AbstractAutowireCapaleBeanFactory工厂类中的applyMergedBeanDefinitionPostProcessors方法,主要核心源码如下:
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class> beanType, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof MergedBeanDefinitionPostProcessor) {
MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
}
}
}
上述的5个主要接口都是实现了MergedBeanDefinitionPostProcessor接口的postProcessMergedBeanDefinition方法,在此处会被回调,也是Spring留给开发人员的一个扩展点,在Bean对象实例化之后执行一些自定义的处理逻辑。
三、暴露早期Bean对象
什么是早期对象?
即Spring中的earlySingleton。之所以称为早期对象,是因为这个对象并不是一个可以使用的Bean,因为Bean创建至该步骤之后,仅仅是一个对象,它所依赖的属性还并不具备值。
早期对象是干什么用的?
早期对象主要是来解决Spring中的循环依赖而引入的一种对象,这种对象通过提前将自己暴露到容器中,使得其他依赖该对象的Bean可以顺利完成初始化操作。具体是如何解决的,期待下篇文章。
四、属性填充 属性填充其实指的就是完成Bean对象中对其他对象属性的依赖注入。例如:UserService中有一个UserDao的属性,此处就是完成将UserDao作为UserService的属性注入到UserService中。 在注入之前,会先根据bean定义中指定的注入方式【即:通过名称注入(by-name)还是根据类型(by-type)注入】去容器中寻找依赖的Bean。如果未找到依赖的Bean,则会先去解决依赖,例如:UserService中有一个UserDao的属性,则会先去获取UserDao对应的Bean,如果没有,则会先去创建UserDao对应的Bean。创建完成之后,通过反射给对象完成属性赋值操作。 五、初始化 上述过程完成之后,对应的Bean对象已经拥有了属性值。此时如果Bean存在着一些实例化之后的自定义操作,例如:回调Aware方法,执行初始化方法(init-method),执行InitializingBean的后置处理方法、执行Bean自己的后置处理器方法等,这个过程就是Bean的初始化过程。当然执行这些初始化过程的方法是需要满足一定条件的,例如要执行Aware方法,就需要对应的Bean实现了相应的Aware接口,如果要执行init-method方法就需要Bean中存在init-method。初始化过程中调用的是 AbstractAutowireCapa -b l e BeanFactory 类的 initial izeBean方法,核心源码下:protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction) () -> {
invokeAwareMethods(beanName, bean);return null;
}, getAccessControlContext());
}else {/**
* 调用Bean实现的Aware接口的方法,主要包括下面三个接口
* BeanNameAware ----> setBeanName()
* BeanClassLoaderAware ----> setBeanClassLoader()
* BeanFactoryAware ----> setBeanFactory()
*/
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;if (mbd == null || !mbd.isSynthetic()) {/** 调用Bean对象的postProcessBeforeInitialization方法,此处会执行标注@PostConstruct注解的方法 */
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}try {/**
* 执行Bean的初始化方法:
*
* 1.先判断Bean是否实现了InitializingBean接口,如果实现了InitializingBean接口,则调用Bean对象的afterPropertiesSet方法;
* 2.然后判断Bean是否有指定init-method方法,如果指定了init-method方法,则调用bean对象的init-method指定的方法.
*/
invokeInitMethods(beanName, wrappedBean, mbd);
}catch (Throwable ex) {throw ex;// 抛异常简写.
}if (mbd == null || !mbd.isSynthetic()) {/**
* 调用Bean对象的postProcessAfterInitialization方法
*
* 如果需要创建代理,在该步骤中执行postProcessAfterInitialization方法的时候会去创建代理
* 调用AbstractAutoProxyCreator类的postProcessAfterInitialization方法,然后调用wrapIfNecessary方法去创建代理.
*
*
* 另外还有一些Aware接口,也会在该步骤中执行,例如:ApplicationContextAwareProcessor后置处理器,对应的setApplicationContext方法会被执行.
*/
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}return wrappedBean;
}
5.1、initAwareMethod方法
该方法即用来完成Aware接口的回调,核心源码如下:
private void invokeAwareMethods(final String beanName, final Object bean) {
// 如果Bean实现了Aware接口
if (bean instanceof Aware) {
// 如果实现了BeanNameAware接口,则调用Bean的setBeanName方法
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
// 如果实现了BeanClassLoaderAware接口,则调用Bean的setBeanClassLoader方法
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
// 如果实现了BeanFactoryAware接口,则调用Bean的setBeanFactory方法
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
5.2、applyBeanPostProcessorsBeforeInitialization方法
如果对应的Bean实现了BeanPostProcessor接口,则此处会回调Bean实例对应的postProcessBeforeInitialization方法,常用的@PostConstruct注解的执行就在该步骤中完成。执行@PostConstruct标注的方法对应的后置处理器为InitDestroyAnnotationBeanPostProcessor。对应的后置处理器方法核心源码如下:
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
/** 查找与Bean的生命周期相关的注解元数据 */
LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
try {
/** 反射执行标注@PostConstruct注解的方法 */
metadata.invokeInitMethods(bean, beanName);
}
catch (InvocationTargetException ex) {
throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException());
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Failed to invoke init method", ex);
}
return bean;
}
5.3、invokeInitMethods方法
该方法就是用来执行Bean的初始化方法的,此处的初始化方法主要包括两个。如果Bean实现了InitializingBean接口,此处会回调对应的afterPropertiesSet方法。如果在Bean中通过init-method指定了初始化方法,则还会调用init-method指定的初始化方法。该过程调用的是AbstractAutowireCapableBeanFactory的invokeInitMethods方法,其核心源码如下:
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)throws Throwable {
// 判断bean对象是否为InitializingBean的实例
// 如果实现了InitializingBean接口,则只掉调用bean的afterPropertiesSet方法
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
((InitializingBean) bean).afterPropertiesSet();
}
// 判断是否指定了init-method方法,如果指定了init-method方法,而且初始化方法不是afterPropertiesSet
// 则通过反射执行指定的初始化方法。就是为了init-method也指定afterPropertiesSet而导致重复执行
if (mbd != null && bean.getClass() != NullBean.class) {
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName) &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
// 调用init-method方法
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
5.4、applyBeanPostProcessorsAfterInitialization方法
执行Bean的后置处理方法,如果Bean实现了BeanPostProcessor接口,则此处会回调BeanPostProcessor接口的postProcessAfterInitialization方法。常见的如生成AOP代理对象就在该步骤中完成。生成代理对象使用的后置处理器为AbstractAutoProxyCreator,核心源码如下:
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
// 创建代理对象
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
在后置处理器中调用wrapIfNecessary方法完成代理对象创建。wrapIfNessary中会根据增强点使用Jdk动态代理或者Cglib动态代理技术去创建增强之后的代理对象。具体代码可以参考AbstractAutoProxyCreator中的wrapIfNecessary方法。
六、注册销毁上述过程执行完之后,这个Bean已经可以投入使用了,此时将要把创建好的Bean加入到单实例缓存池中。在被加入单实例缓存池之前,还需要判断其在容器关闭的时候是否需要执行销毁逻辑,该逻辑的源码位于AbstractBeanFactory类的registerDisposableBeanIfNecessary方法中,核心代码如下:
protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
// 如果不是多例的 && 需要被销毁
if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
// 如果是单实例Bean
if (mbd.isSingleton()) {
// 如果当前的bean不是空Bean && (存在着销毁方法 || (实现了DestructionAwareBeanPostProcessor接口 && requiresDestruction后置方法返回值为true))
// 如果存在着(销毁方法 || 需要被销毁) && 是单例Bean 则会将当前的bean保存到一个disposableBeans对应的Map集合中,map的key为bean名称,value为要被销毁的bean
registerDisposableBean(beanName,
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
}
else {
// 除了prototype之外其他作用域的Bean,则注册自定义的bean销毁回调方法
Scope scope = this.scopes.get(mbd.getScope());
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
}
scope.registerDestructionCallback(beanName,
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
}
}
}
上述注册逻辑中的requiresDestruction方法的核心源码如下:
protected boolean requiresDestruction(Object bean, RootBeanDefinition mbd) {
return (bean.getClass() != NullBean.class && // 不是NullBean
(DisposableBeanAdapter.hasDestroyMethod(bean, mbd) || // 存在着销毁方法,实现了DisposableBean接口或者Autocloseable接口
// 实现了DestructionAwareBeanPostProcessor,而且对应的requiresDestruction方法返回了true【Spring的一个扩展点,可以自定义是否需要销毁】
(hasDestructionAwareBeanPostProcessors()
&& DisposableBeanAdapter.hasApplicableProcessors(bean, getBeanPostProcessors()))));
}
那么如何判断当前bean中是否存在着销毁方法呢?通过DisposableBeanAdapter类的hasDestroyMethod方法来判断,核心源码如下:
public static boolean hasDestroyMethod(Object bean, RootBeanDefinition beanDefinition) {
// bean实现了DisposableBean接口或者AutoCloseable接口
if (bean instanceof DisposableBean || bean instanceof AutoCloseable) {
return true;
}
// 存在着(inferred)方法【注意:一般如果未配置,默认的destroyMethod名称就是这个】,而且bean定义对应的class中存在着名称为close或者shutdown的方法
String destroyMethodName = beanDefinition.getDestroyMethodName();
if (AbstractBeanDefinition.INFER_METHOD.equals(destroyMethodName)) {
return (ClassUtils.hasMethod(bean.getClass(), CLOSE_METHOD_NAME) ||
ClassUtils.hasMethod(bean.getClass(), SHUTDOWN_METHOD_NAME));
}
return StringUtils.hasLength(destroyMethodName);
}
首先判断了是否实现了DesposableBean接口或者Autocloseable接口。如果实现了,那么肯定也会实现对应的销毁方法,即:destroy方法或者close方法。如果未实现,则会判断当前的bean中是否存在着名称为close或者shutdown的方法。如果存在,也会被当做需要被销毁的Bean放入到一个名称为disposableBeans的map集合中。map的key为Bean的名称,value为对应的Bean实例。
七、放入单实例缓存池Bean的生命周期过程执行完毕之后,此时Bean就是一个容器中可以使用的Bean。这个已经创建完成的Bean会被保存到Spring的单实例缓存池singletonObjects中。核心源码在DefaultSingletonBeanRegistry类的addSingleton方法中,如下所示:
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
/** 将创建好的单实例bean放入到单例缓存池中 */
this.singletonObjects.put(beanName, singletonObject);
/** 从三级缓存中删除 */
this.singletonFactories.remove(beanName);
/** 从二级缓存中删除(早期对象:已经实例化,但是未完成属性赋值的对象) */
this.earlySingletonObjects.remove(beanName);
/** 保存到已注册单实例Bean名称集合中 */
this.registeredSingletons.add(beanName);
}
}
至此,Spring的生命周期整个过程介绍完毕。这个过程中涉及到的更细节内容,后期文章会继续按照小点展开。例如:如何通过多级缓存解决Bean之间的循环依赖问题,如何推断构造方法,如果去选择默认的工厂方法等等。
关注菜鸟封神记,定期分享技术干货!
有收获的劳烦点个在看,然后帮转,感谢↓↓↓