Spring容器系列-bean的生命周期
Spring容器系列-bean的生命周期
概要
对于Spring Bean的生命周期来说,可以分为四个阶段,其中初始化完成之后,就代表这个Bean可以使用了,四个阶段如下:
- 实例化 Instantiation : 为Bean分配内存空间
- 属性赋值 Populate :将当前类依赖的Bean属性,进行注入和装配
- 初始化 Initialization
- 销毁 Destruction
一、Spring Bean生命周期
1. Spring Bean 生命周期流程图
先来看看Spring Bean生命周期流程图如下:
下面对Spring Bean生命周期进行详细描述:
1. Bean容器在配置文件中找到Spring Bean的定义。
2. Bean容器使用Java Reflection API创建Bean的实例。
3. 如果声明了任何属性,声明的属性会被设置。如果属性本身是Bean,则将对其进行解析和设置。
4. 如果Bean类实现BeanNameAware接口,则将通过传递Bean的名称来调用setBeanName()方法。
5. 如果Bean类实现BeanClassLoaderAware接口,则将通过传递加载此Bean的ClassLoader对象的实例来调用setBeanClassLoader()方法。
6. 如果Bean类实现BeanFactoryAware接口,则将通过传递BeanFactory对象的实例来调用setBeanFactory()方法。
7. 如果有任何与BeanFactory关联的BeanPostProcessors对象已加载Bean,则将在设置Bean属性之前调用postProcessBeforeInitialization()方法。
8. 如果Bean类实现了InitializingBean接口,则在设置了配置文件中定义的所有Bean属性后,将调用afterPropertiesSet()方法。
9. 如果配置文件中的Bean定义包含init-method属性,则该属性的值将解析为Bean类中的方法名称,并将调用该方法。
10. 如果为Bean Factory对象附加了任何Bean 后置处理器,则将调用postProcessAfterInitialization()方法。
11. 如果Bean类实现DisposableBean接口,则当Application不再需要Bean引用时,将调用destroy()方法。
12. 如果配置文件中的Bean定义包含destroy-method属性,那么将调用Bean类中的相应方法定义。
说明:4、5、6步骤都可以统一看做是第三阶段初始化中的检查aware相关接口并设置相关依赖
2. 举个例子
1)定义一个PersonBean
类,实现了DisposableBean, InitializingBean, BeanFactoryAware, BeanNameAware
这4个接口,同时还有自定义的init-method
和destroy-method
。这里,如果不了解这几个接口的读者,可以先去看看这几个接口的定义。
1 public class PersonBean implements InitializingBean, BeanNameAware,BeanFactoryAware, DisposableBean { 2 /** 3 * 身份证号 4 */ 5 private Integer idNo; 6 7 /** 8 * 姓名 9 */ 10 private String name; 11 12 public PersonBean() { 13 System.out.println("1.调用构造方法:我出生了!"); 14 } 15 16 public Integer getIdNo() { 17 return idNo; 18 } 19 20 public void setIdNo(Integer idNo) { 21 this.idNo = idNo; 22 } 23 24 public String getName() { 25 return name; 26 } 27 28 public void setName(String name) { 29 this.name = name; 30 System.out.println("2.设置属性:我的名字叫"+name); 31 } 32 33 public void setBeanName(String name) { 34 System.out.println("3.调用BeanNameAware#setBeanName方法:我要上学了,起了个学名"); 35 36 } 37 38 public void setBeanFactory(BeanFactory beanFactory) throws BeansException { 39 System.out.println("4.调用BeanFactoryAware#setBeanFactory方法:选好学校了"); 40 } 41 42 public void afterPropertiesSet() throws Exception { 43 System.out.println("6.InitializingBean#afterPropertiesSet方法:入学登记"); 44 } 45 46 public void init() { 47 System.out.println("7.自定义init方法:努力上学ing"); 48 } 49 50 public void destroy() throws Exception { 51 System.out.println("9.DisposableBean#destroy方法:平淡的一生落幕了"); 52 } 53 54 public void destroyMethod() { 55 System.out.println("10.自定义destroy方法:睡了,别想叫醒我"); 56 } 57 58 public void work(){ 59 System.out.println("Bean使用中:工作,只有对社会没有用的人才放假。。"); 60 } 61 62 }
2)定义一个MyBeanPostProcessor
实现BeanPostProcessor
接口。
1 public class MyBeanPostProcessor implements BeanPostProcessor { 2 public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { 3 System.out.println("5.BeanPostProcessor.postProcessBeforeInitialization方法:到学校报名啦"); 4 return bean; 5 } 6 7 public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { 8 System.out.println("8.BeanPostProcessor#postProcessAfterInitialization方法:终于毕业,拿到毕业证啦!"); 9 return bean; 10 } 11 }
3)配置文件spring-config.xml,指定init-method
和destroy-method
属性
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> 5 6 <bean name="myBeanPostProcessor" class="ric.study.demo.ioc.life_cycle_demo_set.MyBeanPostProcessor" /> 7 <bean name="personBean" class="ric.study.demo.ioc.life_cycle_demo_set.Person" 8 init-method="init" destroy-method="destroyMethod"> 9 <property name="name" value="Richard Yi" /> 10 </bean> 11 12 </beans>
4)启动类,运行代码
1 public static void main( String[] args ) 2 { 3 ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml"); 4 PersonBean personBean = (PersonBean) context.getBean("personBean"); 5 personBean.work(); 6 ((ClassPathXmlApplicationContext) context).destroy(); 7 8 } 9 10 11 //运行结果如下: 12 1.调用构造方法:我出生了! 13 2.设置属性:我的名字叫张铁钢 14 3.调用BeanNameAware#setBeanName方法:我要上学了,起了个学名 15 4.调用BeanFactoryAware#setBeanFactory方法:选好学校了 16 5.BeanPostProcessor.postProcessBeforeInitialization方法:到学校报名啦 17 6.InitializingBean#afterPropertiesSet方法:入学登记 18 7.自定义init方法:努力上学ing 19 8.BeanPostProcessor#postProcessAfterInitialization方法:终于毕业,拿到毕业证啦! 20 Bean使用中:工作,只有对社会没有用的人才放假。。 21 9.DisposableBean#destroy方法:平淡的一生落幕了 22 10.自定义destroy方法:睡了,别想叫醒我 23
二、 Spring Bean生命周期源码分析
Bean实例化的时机也分为两种,BeanFactory管理的Bean是在使用到Bean的时候才会实例化Bean,ApplicantContext管理的Bean在容器初始化的时候就会完成Bean实例化。
1. getBean()方法
AbstractApplicationContext
类里的refresh
方法,这个方法是 ApplicationContext 容器初始化的关键点。在这个方法里,调用了finishBeanFactoryInitialization
方法,这个方法里调用了getBean
方法,getBean
方法里调用了AbstractBeanFactory
的getBean
方法。
2. createBean方法
Bean的创建的入口是 AbstractAutowireCapableBeanFactory#createBean:
// 这个类的核心方法,创建一个bean实例,填充bean实例,执行后处理等 protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException { // ... tr { // 给 BeanPostProcessors 提供一个机会,允许它们在实例化 Bean 之前,决定是否返回代理对象, // 如果返回了代理对象,则跳过后续的实例化过程,直接返回该代理对象。 Object bean = resolveBeforeInstantiation(beanName, mbdToUse); // 直接返回代理对象,而不会继续执行实例化流程。 if (bean != null) { return bean; } //... //负责执行 Bean 的实例化、依赖注入等 Object beanInstance = doCreateBean(beanName, mbdToUse, args); // 日志输出,记录创建 Bean 实例的完成信息(如果日志级别为 Debug) if (logger.isDebugEnabled()) { logger.debug("Finished creating instance of bean '" + beanName + "'"); } // 返回已经创建并填充好的 Bean 实例。 return beanInstance; }
3. resolveBeforeInstantiation方法
AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation:
@Nullable protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) { Object bean = null; // 检查是否已处理过实例化前的逻辑 if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) { // 如果是合成 Bean 且没有自定义实例化后处理器,跳过处理 if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { // 确定目标类型 Class<?> targetType = determineTargetType(beanName, mbd); if (targetType != null) { // 应用实例化前的 Bean 后处理器(如 AOP 代理) bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName); // 如果有 Bean 返回,执行初始化后处理,跳过了其他几个方法 if (bean != null) { bean = applyBeanPostProcessorsAfterInitialization(bean, beanName); } } } // 标记已解析 mbd.beforeInstantiationResolved = (bean != null); } return bean; // 返回代理或实际对象,若没有代理则为 null }
resolveBeforeInstantiation 主要是用于 在 Bean 实例化之前做一些预处理工作,尤其是与AOP代理相关的处理。它的存在使得 Spring 能够在实例化之前决定是否需要为 Bean 创建代理对象,从而保证 AOP 增强能够正确地应用到 Bean 上。同时,它还能够优化性能,避免不必要的实例化过程。
applyBeanPostProcessorsBeforeInstantiation方法中调用了InstantiationAwareBeanPostProcessor实现类的postProcessBeforeInstantiation方法。
4. InstantiationAwareBeanPostProcessor 接口
部分源码如下:
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor { Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException; boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException; PropertyValues postProcessPropertyValues( PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException; }
从源码中我们可以获知:InstantiationAwareBeanPostProcessor接口除了具有父接口中的两个方法(postProcessBeforeInitialization和postProcessAfterInitialization)以外还自己额外定义了三个方法。所以该接口一共定义了5个方法。
InstantiationAwareBeanPostProcessor 是 Spring 提供的一个后置处理器接口,专门用于在 Bean 实例化过程中的不同阶段对 Bean 进行额外的操作。它扩展了 BeanPostProcessor 接口,提供了比 BeanPostProcessor 更细粒度的处理能力,尤其是在 Bean 实例化和属性填充时。
注意这两个单词:
- Instantiation:表示实例化,对象还未生成
- Initialization:表示初始化,对象已经生成
5. CommonAnnotationBeanPostProcessor
CommonAnnotationBeanPostProcessor实现了InstantiationAwareBeanPostProcessor接口,它是AnnotationConfigApplicationContext初始化时注入的6个内部bean之一。
主要处理*@Resource、@PostConstruct和@PreDestroy*注解的实现,@Resource的处理是由他自己完成,@PostConstruct和@PreDestroy这两个是由他的父类 InitDestroyAnnotationBeanPostProcessor完成
在postProcessMergedBeanDefinition方法中,其父类InitDestroyAnnotationBeanPostProcessor会寻找@PostConstruct和@PreDestroy注解,他本身会寻找@Resource注解
CommonAnnotationBeanPostProcessor @Override public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) { // 父类处理@PostConstruct和@PreDestroy注解 super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName); // 处理@Resource注解 InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null); metadata.checkConfigMembers(beanDefinition); } InitDestroyAnnotationBeanPostProcessor @Override public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) { //找出被@PostConstruct和@PreDestroy注解修饰的方法 LifecycleMetadata metadata = findLifecycleMetadata(beanType); // 去除重复,并注册到beanDefinition中 metadata.checkConfigMembers(beanDefinition); }
@PostConstruct注解的方法会在InitDestroyAnnotationBeanPostProcessor类的postProcessBeforeInitialization中进行调用处理,@PreDestroy注解的方法会在InitDestroyAnnotationBeanPostProcessor类的postProcessBeforeDestruction中进行调用
InitDestroyAnnotationBeanPostProcessor @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass()); try { metadata.invokeInitMethods(bean, beanName); } ... return bean; } @Override public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException { LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass()); try { metadata.invokeDestroyMethods(bean, beanName); } ... }
6. doCreateBean方法
AbstractAutowireCapableBeanFactory#doCreateBean方法:
1 protected Object doCreateBean(String beanName,RootBeanDefinition mbd,@Nullable Object [args) throws BeanCreationException { 2 3 // 实例化bean. 4 BeanWrapper instanceWrapper = null; 5 if (mbd.isSingleton()) { 6 instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); 7 } 8 if (instanceWrapper == null) { 9 instanceWrapper = createBeanInstance(beanName, mbd, args); 10 } 11 12 ... 13 14 Object exposedObject = bean; 15 try { 16 17 //为bean设置属性值 18 populateBean(beanName,mbd,instanceWrapper); 19 20 //初始化bean 21 exposedObject = initializeBean(beanName,exposedObject,mbd); 22 } 23 ... 24 25 return exposedObject; 26 }
doCreateBean方法中相关的就是populateBean方法和initializeBean方法,populateBean方法主要为bean设置属性值,我们重点关注初始化Bean方法initializeBean。
7. populateBean方法
AbstractAutowireCapableBeanFactory#populateBean:
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { //... // 让 InstantiationAwareBeanPostProcessor 有机会在属性填充前修改 Bean 的状态 if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; // 调用 postProcessAfterInstantiation 检查是否可以继续进行属性注入 if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { return; // 如果返回 false,跳过属性注入 } } } } //... // 如果有 InstantiationAwareBeanPostProcessors,执行属性处理 if (hasInstAwareBpps) { if (pvs == null) { pvs = mbd.getPropertyValues(); } for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; // 使用 postProcessProperties 处理 Bean 属性 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; } } } //... // 真正设置属性的方法: 如果属性值不为空,应用属性值到Bean中 if (pvs != null) { applyPropertyValues(beanName, mbd, bw, pvs); } }
通过 postProcessProperties 和 postProcessPropertyValues,允许 InstantiationAwareBeanPostProcessor 在属性注入前后修改 Bean 的属性值。这个操作是动态的,可能会根据实际情况调整属性值或跳过属性注入。
8. initializeBean方法
AbstractAutowireCapableBeanFactory#initializeBean
1 protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) { 2 if (System.getSecurityManager() != null) { 3 AccessController.doPrivileged((PrivilegedAction<Object>) () -> { 4 // 激活 Aware 方法 5 invokeAwareMethods(beanName, bean); 6 return null; 7 }, getAccessControlContext()); 8 } 9 else { 10 // 对特殊的 bean 处理:BeanNameAware、BeanClassLoaderAware、BeanFactoryAware,使得 Bean 可以访问一些容器中特定的资源 11 invokeAwareMethods(beanName, bean); 12 } 13 14 Object wrappedBean = bean; 15 if (mbd == null || !mbd.isSynthetic()) { 16 //执行BeanPostProcessor所有实现类的postProcessBeforeInitialization方法 17 wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); 18 } 19 20 try { 21 // 激活用户自定义的 init 方法 22 invokeInitMethods(beanName, wrappedBean, mbd); 23 } 24 catch (Throwable ex) { 25 throw new BeanCreationException( 26 (mbd != null ? mbd.getResourceDescription() : null), 27 beanName, "Invocation of init method failed", ex); 28 } 29 if (mbd == null || !mbd.isSynthetic()) { 30 //执行BeanPostProcessor所有实现类的postProcessAfterInitialization方法 31 wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); 32 } 33 return wrappedBean; 34 }
AbstractAutowireCapableBeanFactory#invokeAwareMethods
1 private void invokeAwareMethods(String beanName, Object bean) { 2 // 1. 检查 Bean 是否实现了 Aware 接口 3 if (bean instanceof Aware) { 4 // 2. 如果 Bean 实现了 BeanNameAware 接口 5 if (bean instanceof BeanNameAware) { 6 // 调用 setBeanName 方法,设置 Bean 的名称 7 ((BeanNameAware) bean).setBeanName(beanName); 8 } 9 // 3. 如果 Bean 实现了 BeanClassLoaderAware 接口 10 if (bean instanceof BeanClassLoaderAware) { 11 ClassLoader bcl = getBeanClassLoader(); // 获取 Bean 的类加载器 12 if (bcl != null) { 13 // 调用 setBeanClassLoader 方法,设置类加载器 14 ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl); 15 } 16 } 17 // 4. 如果 Bean 实现了 BeanFactoryAware 接口 18 if (bean instanceof BeanFactoryAware) { 19 // 调用 setBeanFactory 方法,设置 BeanFactory 20 ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this); 21 } 22 } 23 }
说明:Spring在创建Bean时进行的一部分初始化工作,确保每个Bean在被使用之前已经具备了必要的依赖和环境信息。
AbstractAutowireCapableBeanFactory#invokeInitMethods
1 protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd) 2 throws Throwable { 3 // 判断当前bean是否实现了InitializingBean接口 4 boolean isInitializingBean = (bean instanceof InitializingBean); 5 // 如果当前bean是一个InitializingBean 6 if (isInitializingBean && (mbd == null || !mbd.hasAnyExternallyManagedInitMethod("afterPropertiesSet"))) { 7 if (logger.isTraceEnabled()) { 8 logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'"); 9 } 10 if (System.getSecurityManager() != null) { 11 try { 12 AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> { 13 ((InitializingBean) bean).afterPropertiesSet(); 14 return null; 15 }, getAccessControlContext()); 16 } 17 catch (PrivilegedActionException pae) { 18 throw pae.getException(); 19 } 20 } 21 else { 22 // 真正调用当前bean的afterPropertiesSet方法 23 ((InitializingBean) bean).afterPropertiesSet(); 24 } 25 } 26 27 if (mbd != null && bean.getClass() != NullBean.class) { 28 String initMethodName = mbd.getInitMethodName(); 29 if (StringUtils.hasLength(initMethodName) && 30 !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) && 31 !mbd.hasAnyExternallyManagedInitMethod(initMethodName)) { 32 // 最后通过反射的方式执行init-method属性对应的方法 33 invokeCustomInitMethod(beanName, bean, mbd); 34 } 35 } 36 }
9. afterPropertiesSet()方法
InitializingBean只有一个方法afterPropertiesSet,见名知意,这个方法是在bean的属性值被设置以后执行。 Spring给我们提供了这么一个扩展点,可以用来做很多的事情, 比如可以修改默认设置的属性,添加补充额外的属性值或者针对关键属性做一个校验。
Spring本身也有很多的Bean实现了InitializingBean接口, 比如Spring MVC中的RequestMappingHandlerMapping就实现了InitializingBean接口,在afterPropertiesSet中完成了一些初始化工作,比如url和controller方法的映射。
说明:InitializingBean是Spring中很关键的一个扩展接口,其实它和bean中init-method属性对应的方法功能是一致的,都是初始化bean,我们可以二选一实现即可,当然同时使用也没有问题。init-method是通过反射实现的,性能相对差一点点。另外,如果调用afterPropertiesSet方法时出错,则不会调用init-method指定的方法。
四、Bean生命周期中AOP的流程
1. @EnableAspectJAutoProxy
通过@EnableAspectJAutoProxy注解向容器中注册一个AnnotationAwareAspectJAutoProxyCreator的BeanDefinition,它本身也是一个BeanPostProcessor,这个BeanDefinition会在org.springframework.context.support.AbstractApplicationContext#registerBeanPostProcessors这个方法中完成创建。
AnnotationAwareAspectJAutoProxyCreator中比较重要的几个方法都是继承自父类AbstractAutoProxyCreator
部分源码如下:
public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorAutoProxyCreator { /** * 此方法是在 Bean 实例化之前执行 */ @Override public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) { // 获取缓存的key Object cacheKey = getCacheKey(beanClass, beanName); // 如果beanName为空或者当前bean不需要代理,直接跳过 if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) { if (this.advisedBeans.containsKey(cacheKey)) { return null; // 如果已经被代理过,返回null } // 如果是基础设施类,或者满足跳过条件,则不需要代理 if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return null; // 不需要代理,返回null } } // 如果有自定义的 TargetSource,则通过 TargetSource 创建代理 TargetSource targetSource = getCustomTargetSource(beanClass, beanName); if (targetSource != null) { // 如果 beanName 不为空,将其添加到 targetSourcedBeans 中 if (StringUtils.hasLength(beanName)) { this.targetSourcedBeans.add(beanName); } // 获取与当前bean相关的拦截器和增强 Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource); // 创建代理对象 Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource); // 将代理类型缓存 this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; // 返回创建的代理对象 } return null; // 如果没有代理,返回null } /** * 此方法是在 Bean 实例化完成之后执行 */ @Override public boolean postProcessAfterInstantiation(Object bean, String beanName) { // 默认返回true,表示允许对该bean继续进行属性设置等操作 return true; } /** * 此方法是是Spring AOP 中的一个钩子方法,它在 Bean 初始化之前执行,通常用于做一些初步的修改或检查。在默认实现中,没有做任何修改,直接返回原始 Bean */ @Override public Object postProcessBeforeInitialization(Object bean, String beanName) { return bean; } /** * 此方法是在 Bean 初始化完成之后执行,通常用于创建代理(例如 AOP 代理) * 如果需要代理 Bean,会调用 wrapIfNecessary 方法来进行实际的代理创建。如果 Bean 不需要代理,直接返回原始 Bean。 */ @Override public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) { if (bean != null) { // 计算缓存的 key Object cacheKey = getCacheKey(bean.getClass(), beanName); // 如果早期代理引用被移除,则开始进行包装处理 if (this.earlyProxyReferences.remove(cacheKey) != bean) { return wrapIfNecessary(bean, beanName, cacheKey); // 进行代理包装 } } // 返回原始bean,或者是代理对象 return bean; } //... }
2. postProcessBeforeInstantiation方法执行
执行AnnotationAwareAspectJAutoProxyCreator的postProcessBeforeInstantiation方法,实际上就是父类AbstractAutoProxyCreator的postProcessBeforeInstantiation被执行
3. postProcessAfterInitialization方法执行
执行AnnotationAwareAspectJAutoProxyCreator的postProcessAfterInitialization方法,实际上也是执行父类AbstractAutoProxyCreator中的方法。
AOP代理的创建就是在这里完成的。
createBean中调用的resolveBeforeInstantiation,调用postProcessBeforeInstantiation为 Bean 创建代理对象返回不为null,则执行初始化后处理,跳过了其他几个方法
五、容器关闭
1. bean的销毁入口
如下图:
2. Bean的销毁过程触发时机
1)在Spring 中执行显式关闭上下文,关闭时候会执行实现DisposableBean接口类中的destroy() 方法
1 ConfigurableApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"spring.xml"}); 2 // 以下两种显式关闭都会调用实现了DisposableBean接口类中的destroy() 方法 3 // 1、显式关闭上下文 4 context.close(); 5 // 2、显式关闭上下文 6 context.registerShutdownHook();
2)web环境中,Tomcat关闭
在Web环境中,当Tomcat关闭
的时候就会调用到 servlet中的销毁方法
,在这个方法中就会最终也会掉用到Spring中 DisposableBeanAdapter
类的destroy()
方法,该方法就会根据前面的收集进行调用。
1 public class ContextLoaderListener extends ContextLoader implements ServletContextListener { 2 public ContextLoaderListener() { 3 } 4 5 public ContextLoaderListener(WebApplicationContext context) { 6 super(context); 7 } 8 9 public void contextInitialized(ServletContextEvent event) { 10 this.initWebApplicationContext(event.getServletContext()); 11 } 12 // servlet中的销毁方法 13 public void contextDestroyed(ServletContextEvent event) { 14 // 该方法最终会调用Spring的DisposableBeanAdapter类的destroy() 15 this.closeWebApplicationContext(event.getServletContext()); 16 ContextCleanupListener.cleanupAttributes(event.getServletContext()); 17 }
servlet中的closeWebApplicationContext
方法最终也会掉用到Spring中的DisposableBeanAdapter
类的destroy()
方法,该方法就会根据前面的收集进行调用。
3. 销毁过程解析
与Bean初始化类似,当容器关闭时,可以看到对Bean销毁方法的调用。销毁过程是这样的。顺着close()-> doClose() -> destroyBeans() -> destroySingletons() -> destroySingleton() -> destroyBean() -> bean.destroy()
,会看到最终调用Bean的销毁方法。
AbstractApplicationContext#close(),其实实现的是ConfigurableApplicationContext的close()方法
1 @Override 2 public void close() { 3 synchronized (this.startupShutdownMonitor) { 4 doClose(); 5 // If we registered a JVM shutdown hook, we don't need it anymore now: 6 // We've already explicitly closed the context. 7 if (this.shutdownHook != null) { 8 try { 9 Runtime.getRuntime().removeShutdownHook(this.shutdownHook); 10 } 11 catch (IllegalStateException ex) { 12 // ignore - VM is already shutting down 13 } 14 } 15 } 16 }
DefaultSingletonBeanRegistry#destroyBean()源码如下:
1 protected void destroyBean(String beanName, DisposableBean bean) { 2 // 忽略 3 4 // Actually destroy the bean now... 5 if (bean != null) { 6 try { 7 bean.destroy(); 8 } 9 catch (Throwable ex) { 10 logger.error("Destroy method on bean with name '" + beanName + "' threw an exception", ex); 11 } 12 } 13 14 // 忽略 15 }
这里注意哦,这个Bean的类型实际上是DisposableBeanAdapter。
3. DisposableBeanAdapter
DisposableBeanAdapter
是用来管理Spring Bean的销毁的,实际上这里运用了适配器模式。负责将各种销毁方式适配为统一的 destroy() 方法,以便 Spring 容器在关闭时一致地调用。
AbstractAutowireCapableBeanFactory#doCreateBean
1 try { 2 ... 3 4 //注册bean销毁时的类DisposableBeanAdapter:如果实现了 DisposableBean接口或者提供了destroy—method 在这里注册 5 registerDisposableBeanIfNecessary(beanName, bean, mbd); 6 } 7 catch (BeanDefinitionValidationException ex) { 8 throw new BeanCreationException( 9 mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex); 10 }
源码位置:AbstractBeanFactory#registerDisposableBeanIfNecessary()
1 protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) { 2 AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null); 3 if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) { 4 if (mbd.isSingleton()) { 5 // 注册一个DisposableBean实现,该实现将执行给定bean的所有销毁工作。 6 // 包括:DestructionAwareBeanPostProcessors,DisposableBean接口,自定义destroy方法。 7 registerDisposableBean(beanName, 8 new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc)); 9 } 10 else { 11 // A bean with a custom scope... 12 Scope scope = this.scopes.get(mbd.getScope()); 13 if (scope == null) { 14 throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'"); 15 } 16 scope.registerDestructionCallback(beanName, 17 new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc)); 18 } 19 } 20 }
再来看看destroy()
的具体方法。
DisposableBeanAdapter#destroy()源码如下:
1 @Override 2 public void destroy() { 3 if (!CollectionUtils.isEmpty(this.beanPostProcessors)) { 4 for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) { 5 processor.postProcessBeforeDestruction(this.bean, this.beanName); 6 } 7 } 8 9 if (this.invokeDisposableBean) { 10 if (logger.isDebugEnabled()) { 11 logger.debug("Invoking destroy() on bean with name '" + this.beanName + "'"); 12 } 13 try { 14 if (System.getSecurityManager() != null) { 15 AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() { 16 @Override 17 public Object run() throws Exception { 18 ((DisposableBean) bean).destroy(); 19 return null; 20 } 21 }, acc); 22 } 23 else { 24 // 调用 DisposableBean 的 destroy()方法 25 ((DisposableBean) bean).destroy(); 26 } 27 } 28 catch (Throwable ex) { 29 String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'"; 30 if (logger.isDebugEnabled()) { 31 logger.warn(msg, ex); 32 } 33 else { 34 logger.warn(msg + ": " + ex); 35 } 36 } 37 } 38 39 if (this.destroyMethod != null) { 40 // 调用 设置的destroyMethod 41 invokeCustomDestroyMethod(this.destroyMethod); 42 } 43 else if (this.destroyMethodName != null) { 44 Method methodToCall = determineDestroyMethod(); 45 if (methodToCall != null) { 46 invokeCustomDestroyMethod(methodToCall); 47 } 48 } 49 }
参考链接:
https://segmentfault.com/a/1190000020747302
https://juejin.cn/post/7075168883744718856
https://yangzhiwen911.github.io/
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)