前言
本文从源码(SpringBoot 2.3.0版本)入手,学习教材上所说的Bean的生命周期的4个阶段:
- Bean定义
- Bean初始化
- Bean的生存期
- Bean的销毁
其中,Bean初始化阶段涉及的内容较多,如依赖注入,BeanPostProcessor、Aware接口的调用,比较复杂,这里先给个结论。
Bean初始化过程中的生命周期:
- 调用InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()
- Bean实例化(Instantiation)
- 调用InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()
- 完成Bean的依赖注入,如HelloController依赖注入HelloServiceImpl,注入HelloService时会触发HelloService Bean的定义、初始化,因此这是一个递归过程
- 调用BeanNameAware、BeanClassLoaderAware、BeanFactoryAware
- 调用每个BeanPostProcessor.postProcessBeforeInitialization(),当BeanPostProcessor=ApplicationContextAwareProcessor时,调用ApplicationContextAware.setApplicationContext()
- 调用InitializingBean.afterPropertiesSet()
- 调用@Bean的init-method方法
- 调用每个BeanPostProcessor.postProcessAfterInitialization()
Bean定义
在SpringBoot启动时,根据@ComponentScan指定的包路径(默认是当前包及其子包)扫描,把Bean的定义保存到IoC容器中。
SpringBoot Web应用使用的IoC容器为AnnotationConfigServletWebServerApplicationContext,这个容器包含一个属性:DefaultListableBeanFactory。DefaultListableBeanFactory是BeanFactory的实现类之一,它的作用就是保存bean定义和实例化bean。
在启动类SpringApplication.run()方法中,先确定使用的IoC容器为AnnotationConfigServletWebServerApplicationContext,然后调用此容器的refresh()方法,对DefaultListableBeanFactory进行配置,将Bean定义添加到DefaultListableBeanFactory的beanDefinitionMap中。
下面是主要的一些源码展示,这些方法间的调用链可以debug查看。
SpringApplication.run()方法:
1 2 3 4 5 6 7 8 9 10 11
| public ConfigurableApplicationContext run(String... args) { context = createApplicationContext(); exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[] { ConfigurableApplicationContext.class }, context); prepareContext(context, environment, listeners, applicationArguments, printedBanner); refreshContext(context); }
|
ClassPathBeanDefinitionScanner.doScan()方法:
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
| protected Set<BeanDefinitionHolder> doScan(String... basePackages) { Assert.notEmpty(basePackages, "At least one base package must be specified"); Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>(); for (String basePackage : basePackages) { Set<BeanDefinition> candidates = findCandidateComponents(basePackage); for (BeanDefinition candidate : candidates) { ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate); candidate.setScope(scopeMetadata.getScopeName()); String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry); if (candidate instanceof AbstractBeanDefinition) { postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName); } if (candidate instanceof AnnotatedBeanDefinition) { AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate); } if (checkCandidate(beanName, candidate)) { BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName); definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); beanDefinitions.add(definitionHolder); registerBeanDefinition(definitionHolder, this.registry); } } } return beanDefinitions; }
|
DefaultListableBeanFactory部分源码:
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
| public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable { private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
@Override public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException { if (hasBeanCreationStarted()) { synchronized (this.beanDefinitionMap) { this.beanDefinitionMap.put(beanName, beanDefinition); List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1); updatedDefinitions.addAll(this.beanDefinitionNames); updatedDefinitions.add(beanName); this.beanDefinitionNames = updatedDefinitions; removeManualSingletonName(beanName); } } else { this.beanDefinitionMap.put(beanName, beanDefinition); this.beanDefinitionNames.add(beanName); removeManualSingletonName(beanName); } }
|
到这一步,IoC容器中只有Bean的定义,还没有Bean的实例化对象。
Bean初始化
概述
Bean的初始化阶段的主要工作,就是实例化Bean再初始化Bean,初始化过程中就包含依赖注入。
默认配置的、单例且非懒加载的Bean,会在Bean定义步骤完成后立即初始化。
入口在IoC容器基类AbstractApplicationContext.finishBeanFactoryInitialization()方法:
1 2 3 4 5 6
| protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) { beanFactory.preInstantiateSingletons(); }
|
主要工作的是AbstractAutowireCapableBeanFactory.doCreateBean()方法,这个类是DefaultListableBeanFactory的基类。
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
| protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException {
BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { instanceWrapper = createBeanInstance(beanName, mbd, args); } final Object bean = instanceWrapper.getWrappedInstance();
Object exposedObject = bean; try { populateBean(beanName, mbd, instanceWrapper); exposedObject = initializeBean(beanName, exposedObject, mbd); } return exposedObject; }
|
下面介绍Bean初始化阶段的详细过程。
Bean实例化(Instantiation)
在AbstractAutowireCapableBeanFactory.doCreateBean()方法中,createBeanInstance()方法负责Bean的实例化,实例化后的bean对象的属性还是空的。
1 2 3 4 5 6 7 8 9 10
| protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException { if (instanceWrapper == null) { instanceWrapper = createBeanInstance(beanName, mbd, args); } final Object bean = instanceWrapper.getWrappedInstance(); }
|
Bean初始化(Initialization)
在AbstractAutowireCapableBeanFactory.doCreateBean()方法中,populateBean()方法和initializeBean()方法完成Bean的属性赋值(包括依赖注入),和Bean的一些扩展接口的调用。
1 2 3 4 5 6 7 8 9 10
| protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException { try { populateBean(beanName, mbd, instanceWrapper); exposedObject = initializeBean(beanName, exposedObject, mbd); } }
|
populateBean()方法中完成依赖注入,如把personServiceImpl注入到personController中。
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
| protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null); int resolvedAutowireMode = mbd.getResolvedAutowireMode(); if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs = new MutablePropertyValues(pvs); if (resolvedAutowireMode == AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } pvs = newPvs; } for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName); if (pvsToUse == null) { if (filteredPds == null) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvsToUse == null) { return; } } pvs = pvsToUse; } } if (pvs != null) { applyPropertyValues(beanName, mbd, bw, pvs); } }
|
以上大致介绍了Bean的初始化阶段的主要工作,即实例化Bean再依赖注入。但在这个阶段,还涉及到BeanPostProcessor接口和*Aware接口的调用。下面介绍这两类接口的作用和调用时机。
调用扩展接口
BeanPostProcessor接口
BeanPostProcessor是Spring IOC容器给我们提供的一个扩展接口。接口声明如下:
1 2 3 4 5 6 7 8 9 10 11
| public interface BeanPostProcessor {
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException; }
|
实现了BeanPostProcessor接口的类,被扫描进IoC容器后,在所有Bean的初始化前后都会被调用,即它对所有Bean都生效,有点像AOP。它有个子接口InstantiationAwareBeanPostProcessor。
InstantiationAwareBeanPostProcessor接口
InstantiationAwareBeanPostProcessor接口继承自BeanPostProcessor接口,它不仅继承了BeanPostProcessor接口会在Bean初始化前后调用的两个方法,还增加了会在Bean实例化前后调用的两个方法。所以这两个方法也在Bean的生命周期内。具体的调用时机在下面介绍。
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
| public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
@Nullable default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { return null; }
default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException { return true; }
@Nullable default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException { return null; }
@Deprecated @Nullable default PropertyValues postProcessPropertyValues( PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException { return pvs; } }
|
Aware接口
Aware类型的接口的作用就是让我们能够拿到Spring容器中的一些资源,Aware之前的名字就是可以拿到什么资源,例如BeanNameAware可以拿到BeanName,以此类推。
比较常见的Aware接口有BeanNameAware、BeanFactoryAware、ApplicationContextAware。
ApplicationContextAware接口
ApplicationContextAware接口可以用来获取ApplicationContext,即IoC容器。我们已知ApplicationContext包含BeanFactory接口的getBean()方法,因此我们在服务中可以借助它直接获取Bean。
1 2 3
| public interface ApplicationContextAware extends Aware { void setApplicationContext(ApplicationContext applicationContext) throws BeansException; }
|
我们在项目中,经常遇到要随时获取Bean的情况,这时就可以写一个工具类解决:ApplicationContextUtil。这个工具类就是使用了ApplicationContextAware接口的特性。
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
| @Component public class ApplicationContextUtil implements ApplicationContextAware { private static ApplicationContext context;
@Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.context = applicationContext; }
public static Object getBean(String name) { return context.getBean(name); }
public static <T> T getBean(Class<T> clazz) { return context.getBean(clazz); }
public static <T> T getBean(String name, Class<T> clazz) { return context.getBean(name, clazz); } }
|
那么,我们定义的这个Bean,ApplicationContextUtil,它的setApplicationContext()方法是在何时被调用的?答案在下面“调用时机”一节中。
调用时机
BeanFactory注册BeanPostProcessor接口
在AnnotationConfigServletWebServerApplicationContext.refresh()方法中(在Bean定义阶段中有提到),会给要使用的BeanFactory=DefaultListableBeanFactory注册BeanPostProcessor接口。
1 2 3 4 5 6 7 8 9 10 11 12 13
| public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { prepareBeanFactory(beanFactory); try { registerBeanPostProcessors(beanFactory); } } }
|
调用BeanPostProcessor和Aware接口方法
在Bean初始化阶段的initializeBean()方法中,顺序调用了BeanPostProcessor和Aware接口方法。
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
| 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 { invokeAwareMethods(beanName, bean); }
Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); }
try { 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; }
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); } } }
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd) throws Throwable {
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 { ((InitializingBean) bean).afterPropertiesSet(); } }
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。就会遍历调用所有的BeanPostProcessor接口方法,即BeanPostProcessor接口方法对所有Bean都有效。而Aware接口是由Bean自己实现的,初始化某个Bean时,会调用Bean自己的Aware接口方法,因此Aware接口方法只针对一个Bean有效。
ApplicationContextAware接口的调用
ApplicationContextAware接口的调用点如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| 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 { invokeAwareMethods(beanName, bean); }
Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } }
|
在applyBeanPostProcessorsBeforeInitialization()方法中,会遍历执行BeanFactory的所有BeanPostProcessor.postProcessBeforeInitialization()方法,当遍历到ApplicationContextAwareProcessor.postProcessBeforeInitialization()方法时,它的源码如下:
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
| public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (acc != null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { invokeAwareInterfaces(bean); return null; }, acc); } else { invokeAwareInterfaces(bean); }
return bean; }
private void invokeAwareInterfaces(Object bean) { if (bean instanceof EnvironmentAware) { ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment()); } if (bean instanceof EmbeddedValueResolverAware) { ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver); } if (bean instanceof ResourceLoaderAware) { ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext); } if (bean instanceof ApplicationEventPublisherAware) { ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext); } if (bean instanceof MessageSourceAware) { ((MessageSourceAware) bean).setMessageSource(this.applicationContext); } if (bean instanceof ApplicationContextAware) { ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext); } }
|
至于这个ApplicationContextAwareProcessor是何时添加到BeanFactory的,答案在上面介绍的“BeanFactory注册BeanPostProcessor接口”的prepareBeanFactory()方法中。
1 2 3 4 5
| protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) { beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)); }
|
InstantiationAwareBeanPostProcessor接口的调用
介绍InstantiationAwareBeanPostProcessor接口时,提到它扩展的两个方法:postProcessBeforeInstantiation()、postProcessAfterInstantiation(),分别在Bean实例化前后调用。具体的调用点如下。
postProcessBeforeInstantiation()的调用点在AbstractAutowireCapableBeanFactory.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
| @Override protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { try { Object bean = resolveBeforeInstantiation(beanName, mbdToUse); if (bean != null) { return bean; } } try { Object beanInstance = doCreateBean(beanName, mbdToUse, args); if (logger.isTraceEnabled()) { logger.trace("Finished creating instance of bean '" + beanName + "'"); } return beanInstance; } }
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) { Object bean = null; if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) { if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { Class<?> targetType = determineTargetType(beanName, mbd); if (targetType != null) { bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName); if (bean != null) { bean = applyBeanPostProcessorsAfterInitialization(bean, beanName); } } } mbd.beforeInstantiationResolved = (bean != null); } return bean; }
|
postProcessAfterInstantiation()的调用点,是我们熟悉的populateBean()方法:
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
| protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { if (bw == null) { if (mbd.hasPropertyValues()) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance"); } else { return; } }
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { return; } } } } }
|
Bean初始化阶段总结
在Bean初始化过程中的生命周期是这样的:
- BeanFactory注册BeanPostProcessor接口
- 调用InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()
- createBeanInstance()进行Bean实例化
- populateBean()
- 调用InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()
- 调用AutowiredAnnotationBeanPostProcessor.postProcessProperties(),完成依赖注入,是一个递归过程
- initializeBean()
- 调用BeanNameAware、BeanClassLoaderAware、BeanFactoryAware
- 调用每个BeanPostProcessor.postProcessBeforeInitialization(),当BeanPostProcessor=ApplicationContextAwareProcessor时,调用ApplicationContextAware.setApplicationContext()
- 调用InitializingBean.afterPropertiesSet()
- 调用@Bean的init-method方法
- 调用每个BeanPostProcessor.postProcessAfterInitialization()
可能有人会问,在Bean定义阶段使用的DefaultListableBeanFactory的成员变量beanDefinitionMap在Bean初始化阶段怎么没有出现?其实是出现了的。回顾doCreateBean()方法:
1 2
| protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException {...}
|
第二个形参RootBeanDefinition mbd是从该方法的上上一层方法AbstractBeanFactory.doGetBean()传进来的:
【调用链是 AbstractBeanFactory.doGetBean() -> AbstractAutowireCapableBeanFactory.createBean() -> AbstractAutowireCapableBeanFactory.doCreateBean()
1 2 3 4 5 6 7 8 9 10
| @SuppressWarnings("unchecked") protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); checkMergedBeanDefinition(mbd, beanName, args); createBean(beanName, mbd, args); }
|
在getMergedLocalBeanDefinition()方法中,调用DefaultListableBeanFactory.getBeanDefinition(),从beanDefinitionMap中获得Bean定义信息。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException { RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName); if (mbd != null && !mbd.stale) { return mbd; } return getMergedBeanDefinition(beanName, getBeanDefinition(beanName)); }
public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException { BeanDefinition bd = this.beanDefinitionMap.get(beanName); if (bd == null) { if (logger.isTraceEnabled()) { logger.trace("No bean named '" + beanName + "' found in " + this); } throw new NoSuchBeanDefinitionException(beanName); } return bd; }
|
Bean的生存期
Bean的生存期就是SpringBoot程序启动后,我们使用Bean的过程,这里不介绍了。
Bean的销毁
当 IoC 容器关闭时会对 Bean 进行销毁,此时会调用 Bean 的自定义销毁方法。
注意:销毁方法内只做 Bean 销毁前要做的事,比如调用下 Bean 内成员的销毁方法,Bean 资源的释放还是由 JVM 完成。
容器启动时记录定义了销毁方法的Bean
有以下3种方式来自定义 Bean 的销毁方法:
- 实现 DisposableBean 接口
- @Bean(destroyMethod=”xxx”)
- @PreDestroy
这3种方法的代码示例:
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
| public class Person2 implements DisposableBean { @Override public void destroy() throws Exception { System.out.println("===================destroy person2 bean"); } }
public class Person { public void destroy(){ System.out.println("===================destroy person bean"); } }
public class Person3 { @PreDestroy public void destroy() throws Exception { System.out.println("===================destroy person3 bean"); } }
@Configuration public class BeanConfig { @Bean(destroyMethod = "destroy") Person person() { return new Person(); }
@Bean Person2 person2() { return new Person2(); }
@Bean Person3 person3() { return new Person3(); } }
|
IoC容器启动时,在AbstractAutowireCapableBeanFactory.doCreateBean()方法中,完成当前 Bean 的初始化后(即调用完 initializeBean 方法后),会调用父类的registerDisposableBeanIfNecessary方法,判断当前 Bean 是否含自定义销毁方法,若有则记录在容器成员Map<String, Object> disposableBeans中。
这部分源码如下:
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
| protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException {
try { registerDisposableBeanIfNecessary(beanName, bean, mbd); } catch (BeanDefinitionValidationException ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex); } return exposedObject; }
protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) { AccessControlContext acc = System.getSecurityManager() != null ? this.getAccessControlContext() : null; if (!mbd.isPrototype() && this.requiresDestruction(bean, mbd)) { if (mbd.isSingleton()) { this.registerDisposableBean(beanName, new DisposableBeanAdapter(bean, beanName, mbd, this.getBeanPostProcessors(), acc)); } else { Scope 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, this.getBeanPostProcessors(), acc)); } } }
protected boolean requiresDestruction(Object bean, RootBeanDefinition mbd) { return bean != null && (DisposableBeanAdapter.hasDestroyMethod(bean, mbd) || this.hasDestructionAwareBeanPostProcessors() && DisposableBeanAdapter.hasApplicableProcessors(bean, this.getBeanPostProcessors())); }
|
this.requiresDestruction() 方法就是用于判断一个 Bean 是否有自定义销毁方法,只要以下2个条件之一成立则返回 true:
- DisposableBeanAdapter.hasDestroyMethod() = true
- Bean 是否实现了 DisposableBean 或 AutoCloseable 接口;
- 若上条不符,那么是否指定 @Bean 注解的 destroyMethod 属性;
- 若上条不符,那么 Bean 类中是否有名为“close”或“shutdown”的方法。
- this.hasDestructionAwareBeanPostProcessors() && DisposableBeanAdapter.hasApplicableProcessors() = true
容器中的 beanPostProcessorList 中有DestructionAwareBeanPostProcessor类型的 Bean,且它对当前 Bean 适用。
第二个条件中的 DestructionAwareBeanPostProcessor 接口继承自 BeanPostProcessor,扩展了2个方法:
1 2 3 4 5 6
| public interface DestructionAwareBeanPostProcessor extends BeanPostProcessor { void postProcessBeforeDestruction(Object var1, String var2) throws BeansException; boolean requiresDestruction(Object var1); }
|
那么容器中有 DestructionAwareBeanPostProcessor 类型的 Bean 吗?有!在容器 refresh 时,添加了一个ApplicationListenerDetectorBean,它只对 ApplicationListener Bean 适用;还有一个 CommonAnnotationBeanPostProcessor,它对使用了 @PreDestroy 注解的 Bean 适用。
所以,当 Bean 使用了3种方法中的任一种(也可以同时用)自定义销毁方法,this.requiresDestruction() 方法就会返回 true,这个 Bean 会被包装成DisposableBeanAdapter添加到容器的 disposableBeans Map 中。
容器关闭时调用Bean的销毁方法
IoC 容器关闭时会对 Bean 进行销毁,此时会通过容器中的 BeanFactory 调用 Bean 的自定义销毁方法。
DefaultSingletonBeanRegistry.destroySingletons()方法(DefaultSingletonBeanRegistry 是 DefaultListableBeanFactory 的间接基类):
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
| public void destroySingletons() { String[] disposableBeanNames; synchronized(this.disposableBeans) { disposableBeanNames = StringUtils.toStringArray(this.disposableBeans.keySet()); }
for(int i = disposableBeanNames.length - 1; i >= 0; --i) { this.destroySingleton(disposableBeanNames[i]); }
}
public void destroySingleton(String beanName) { this.removeSingleton(beanName); DisposableBean disposableBean; synchronized(this.disposableBeans) { disposableBean = (DisposableBean)this.disposableBeans.remove(beanName); }
this.destroyBean(beanName, disposableBean); }
protected void destroyBean(String beanName, @Nullable DisposableBean bean) { Set<String> dependencies; synchronized (this.dependentBeanMap) { dependencies = this.dependentBeanMap.remove(beanName); } if (dependencies != null) { if (logger.isTraceEnabled()) { logger.trace("Retrieved dependent beans for bean '" + beanName + "': " + dependencies); } for (String dependentBeanName : dependencies) { destroySingleton(dependentBeanName); } }
if (bean != null) { try { bean.destroy(); } catch (Throwable ex) { if (logger.isWarnEnabled()) { logger.warn("Destruction of bean with name '" + beanName + "' threw an exception", ex); } } } }
|
上面源码说明了销毁 Bean 的过程:遍历 disposableBeans Map,分别调用这些 Bean 的 destroy 方法完成销毁。从上一小节我们知道,disposableBeans Map 保存了所有含自定义销毁方法的 Bean,且这些 Bean 是被包装成 DisposableBeanAdapter 对象保存的,所以源码中调用bean.destroy()其实是调用DisposableBeanAdapter.destroy()。
在看 DisposableBeanAdapter.destroy() 方法之前,先看一下当初 Bean 是怎么被包装成 DisposableBeanAdapter 的。DisposableBeanAdapter 构造方法源码:
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
| public DisposableBeanAdapter(Object bean, String beanName, RootBeanDefinition beanDefinition, List<BeanPostProcessor> postProcessors, AccessControlContext acc) { Assert.notNull(bean, "Disposable bean must not be null"); this.bean = bean; this.beanName = beanName; this.invokeDisposableBean = this.bean instanceof DisposableBean && !beanDefinition.isExternallyManagedDestroyMethod("destroy"); this.nonPublicAccessAllowed = beanDefinition.isNonPublicAccessAllowed(); this.acc = acc; String destroyMethodName = this.inferDestroyMethodIfNecessary(bean, beanDefinition); if (destroyMethodName != null && !(this.invokeDisposableBean && "destroy".equals(destroyMethodName)) && !beanDefinition.isExternallyManagedDestroyMethod(destroyMethodName)) { this.destroyMethodName = destroyMethodName; this.destroyMethod = this.determineDestroyMethod(); if (this.destroyMethod == null) { if (beanDefinition.isEnforceDestroyMethod()) { throw new BeanDefinitionValidationException("Couldn't find a destroy method named '" + destroyMethodName + "' on bean with name '" + beanName + "'"); } } else { Class<?>[] paramTypes = this.destroyMethod.getParameterTypes(); if (paramTypes.length > 1) { throw new BeanDefinitionValidationException("Method '" + destroyMethodName + "' of bean '" + beanName + "' has more than one parameter - not supported as destroy method"); }
if (paramTypes.length == 1 && Boolean.TYPE != paramTypes[0]) { throw new BeanDefinitionValidationException("Method '" + destroyMethodName + "' of bean '" + beanName + "' has a non-boolean parameter - not supported as destroy method"); } } } this.beanPostProcessors = this.filterPostProcessors(postProcessors, bean); }
|
解释上面源码中标注的点:
- 判断条件中
beanDefinition.isExternallyManagedDestroyMethod("destroy")当使用了 @PreDestroy 注解且这个注解标注的方法名为”destroy”时为 true。这一行代码含义是,当 Bean 实现了 DisposableBean 接口且 destroy 方法未标注 @PreDestroy 时,this.invokeDisposableBean = true
- this.inferDestroyMethodIfNecessary()方法中,若定义了@Bean 的 destroyMethod 属性则直接返回;若实现了 DisposableBean 接口则返回 null;若有名为”close”方法或”shutdown”方法,则返回”close”或”shutdown”,否则返回 null
- 这里if条件成立的场景是:(destroyMethodName != null) 且 (未实现 DisposableBean 或 实现了 DisposableBean 但 destroyMethodName!=”destory”) 且 destroyMethodName 方法未标注 @PreDestroy 注解
- 从容器中所有 beanPostProcessor 中筛选对当前 Bean 有效的
从上面这几点还可以看出:
- 若 @Bean(destroyMethod=”xxx”) 和 DisposableBean 同时用,且前者定义的销毁方法与后者不同(后者只能是 destory 方法),则这两者分别定义的销毁方法都会被调用
- 若 @Bean(destroyMethod=”xxx”) 和 @PreDestroy 同时用,且前者定义的销毁方法与后者不同,则这两者分别定义的销毁方法都会被调用
- 若 DisposableBean 和 @PreDestroy 同时用,且前者定义的销毁方法(只能是 destory 方法)与后者不同,则这两者分别定义的销毁方法都会被调用
- 若只使用了 @Bean 但未定义 destroyMethod 属性,则会自动取方法名为”close”或”shutdown”的方法作为销毁方法
这里使用了“适配器模式”,DisposableBeanAdapter 适配了自定义销毁方法的3种方式。
倒回来看 DisposableBeanAdapter.destroy() 源码:
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
| @Override public void destroy() {
if (!CollectionUtils.isEmpty(this.beanPostProcessors)) { for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) { processor.postProcessBeforeDestruction(this.bean, this.beanName); } }
if (this.invokeDisposableBean) { if (logger.isDebugEnabled()) { logger.debug("Invoking destroy() on bean with name '" + this.beanName + "'"); } try { if (System.getSecurityManager() != null) { AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() { @Override public Object run() throws Exception { ((DisposableBean) bean).destroy(); return null; } }, acc); } else { ((DisposableBean) bean).destroy(); } } catch (Throwable ex) { String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'"; if (logger.isDebugEnabled()) { logger.warn(msg, ex); } else { logger.warn(msg + ": " + ex); } } }
if (this.destroyMethod != null) { invokeCustomDestroyMethod(this.destroyMethod); } else if (this.destroyMethodName != null) { Method methodToCall = determineDestroyMethod(); if (methodToCall != null) { invokeCustomDestroyMethod(methodToCall); } } }
|
综上,无论使用哪一种方式自定义销毁方法,这个 Bean 会在容器启动时包装成 DisposableBeanAdapter。容器关闭时,调用 BeanFactory 方法:DefaultSingletonBeanRegistry.destroySingletons(),这个方法内再通过 DisposableBeanAdapter 执行自定义销毁方法。
这里简单介绍下容器关闭的原理。
容器关闭时执行的方法是:AbstractApplicationContext.doClose(),就是在这个方法内调用了 DefaultSingletonBeanRegistry.destroySingletons() 方法,那么它是怎么被调用的?
IoC 容器关闭有2种情况,一个是主动调用容器的 close 方法,像下面这样:
1 2 3 4 5 6 7 8
| public class MysqlDemoApplication {
public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(BeanConfig.class); System.out.println(context.getBean(HelloWorldController.class)); context.close(); } }
|
但在一般项目中不会有这样的代码,所以第二种情况就是让 Spring 自动完成关闭容器的操作。Spring 怎么自己知道要关闭容器?
在SpringApplication.refreshContext()方法源码(如下)中可以看到,程序启动时,SpringApplication 调用完容器的 refresh 方法后,紧接着调用了容器的registerShutdownHook方法。
1 2 3 4 5 6 7 8 9
| private void refreshContext(ConfigurableApplicationContext context) { this.refresh(context); if (this.registerShutdownHook) { try { context.registerShutdownHook(); } catch (AccessControlException var3) { } } }
|
registerShutdownHook 方法是接口 ConfigurableApplicationContext 定义的,由 AbstractApplicationContext(所有容器类的基类)实现。实现代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13
| public void registerShutdownHook() { if (this.shutdownHook == null) { this.shutdownHook = new Thread() { public void run() { synchronized(AbstractApplicationContext.this.startupShutdownMonitor) { AbstractApplicationContext.this.doClose(); } } }; Runtime.getRuntime().addShutdownHook(this.shutdownHook); }
}
|
这个方法的最后调用了 JDK 的一个方法:Runtime.addShutDownHook(Thread hook) ,作用是:注册一个 JVM 关闭的钩子方法。此处可以看出,这个“钩子方法”是一个线程,线程内调用了 AbstractApplicationContext.doClose() 方法 ,这个线程会在JVM 正常关闭时被执行。
什么是钩子方法?
钩子方法是设计模式中的模板模式里用到的,它是由抽象类声明并且实现,实现内容一般是空的,子类可以选择是否扩展。钩子方法为你在实现某一个抽象类的时候提供了可选项,相当于预先提供了一个默认配置。
JVM正常关闭的条件是?
用”kill”命令而不是”kill -9”命令,在idea编辑器里点击”exit”按钮而不是”stop”按钮。