还记不住Spring Bean的生命周期?看这篇你就知道方法了!
一、前言
上次我们在手把手教你解决循环依赖,一步一步地来窥探出三级缓存的奥秘中分析了Spring解决循环依赖的方式,在第6节中的doCreateBean(AbstractAutowireCapableBeanFactory类中)其实已经隐约看到了Bean的生命周期的几个阶段。
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)throws BeanCreationException {//实例化beanBeanWrapper instanceWrapper = createBeanInstance(beanName, mbd, args);boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&isSingletonCurrentlyInCreation(beanName));if (earlySingletonExposure) {//加入到三级缓存中,getEarlyBeanReference会返回单例工厂addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));}Object exposedObject = bean;//属性赋值populateBean(beanName, mbd, instanceWrapper);//初始化exposedObject = initializeBean(beanName, exposedObject, mbd);if (earlySingletonExposure) {//从二级缓存中查找Object earlySingletonReference = getSingleton(beanName, false);if (earlySingletonReference != null) {//返回二级缓存中的bean,这里就有可能是代理后的对象exposedObject = earlySingletonReference;}}//销毁前的准备,注册待销毁的BeanregisterDisposableBeanIfNecessary(beanName, bean, mbd);return exposedObject;}
doCreateBean基本描述了Bean生命周期的大致框架——实例化、属性赋值与初始化,当然Bean最后一步就是销毁。
基本阶段图
请记住这张图,也许你等会儿就不认识它了。
二、实例化与属性赋值阶段
当容器启动时,会依据配置或注解扫描指定的包,将其中的类转化为BeanDefinition,并集中在DefaultListableBeanFactory类的beanDefinitionMap变量里。
Spring中的BeanDdfinition,可以用来描述一个bean的作用域、是否懒加载、是否单例等。
容器启动完成后,当我们试图从容器获取一个Bean时,第一步就是去实例化该Bean。说白了,就是需要调用构造方法。
注意到在调用doCreateBean之前,调用了resolveBeforeInstantiation方法。
1、resolveBeforeInstantiation
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)throws BeanCreationException {//省略部分代码Object bean = resolveBeforeInstantiation(beanName, mbdToUse);if (bean != null) {return bean;}//正式进入生命周期Object beanInstance = doCreateBean(beanName, mbdToUse, args);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) {//寻找InstantiationAwareBeanPostProcessor,并执行相应方法bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName); //在返回不为null的情况下,寻找BeanPostProcessor,执行相应方法if (bean != null) {bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);}}}mbd.beforeInstantiationResolved = (bean != null);}return bean;}
当resolveBeforeInstantiation返回不为null的bean后,createBean会直接返回。也就是说,后续的实例化、属性赋值与初始化阶段都不会进行。这一步,将会给BeanPostProcessor一个返回代理而不是目前bean的机会。
resolveBeforeInstantiation核心的方法如下:
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {//获取所有BeanPostProcessor的实现类for (BeanPostProcessor bp : getBeanPostProcessors()) {//如果属于InstantiationAwareBeanPostProcessor类型,则执行postProcessBeforeInstantiation方法if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);if (result != null) {return result;}}}return null;}public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)throws BeansException {Object result = existingBean;//获取所有BeanPostProcessor的实现类for (BeanPostProcessor processor : getBeanPostProcessors()) {//挨个执行postProcessAfterInitialization方法Object current = processor.postProcessAfterInitialization(result, beanName);if (current == null) {return result;}result = current;}return result;}
2、BeanPostProcessor
BeanPostProcessor是容器提供给我们的一个扩展接口,也称Bean的后置处理器。我们可以实现该接口,用来添加业务中特有的逻辑。
BeanPostProcessor实现类也是一个普通的Bean,那么Spring是怎么保证BeanPostProcessor实现类在开发人员写的Bean之前加载的呢?
这就要回到我们最熟悉的refresh方法中
public void refresh() {// Prepare this context for refreshing.prepareRefresh();// Tell the subclass to refresh the internal bean factory.ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// Prepare the bean factory for use in this context.prepareBeanFactory(beanFactory);// Allows post-processing of the bean factory in context subclasses.postProcessBeanFactory(beanFactory);// Invoke factory processors registered as beans in the context.invokeBeanFactoryPostProcessors(beanFactory);// Register bean processors that intercept bean creation.registerBeanPostProcessors(beanFactory);// Initialize message source for this context.initMessageSource();// Initialize event multicaster for this context.initApplicationEventMulticaster();// Initialize other special beans in specific context subclasses.onRefresh();// Check for listener beans and register them.registerListeners();// Instantiate all remaining (non-lazy-init) singletons.finishBeanFactoryInitialization(beanFactory);// Last step: publish corresponding event.finishRefresh();}
其中registerBeanPostProcessors方法就会对BeanPostProcessor进行注册,在finishBeanFactoryInitialization中再完成非懒加载的单例Bean的加载。
从而BeanPostProcessor就会在业务Bean之前加载,因此可以在业务Bean实例化前进行调用。
3、instantiateBean
现在可以进入doCreateBean中,createBeanInstance包含了实例化bean并封装为BeanWrapper的逻辑,且内部提供了多种实例化的方式。
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {//将bean转化为class对象Class<?> beanClass = resolveBeanClass(mbd, beanName);//基于Supplier实例化Supplier<?> instanceSupplier = mbd.getInstanceSupplier();if (instanceSupplier != null) {return obtainFromSupplier(instanceSupplier, beanName);}//基于工厂方法实例化if (mbd.getFactoryMethodName() != null) {return instantiateUsingFactoryMethod(beanName, mbd, args);}//省略部分代码//基于有参构造函数实例化Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {return autowireConstructor(beanName, mbd, ctors, args);}//基于无参构造函数实例化return instantiateBean(beanName, mbd);}
有兴趣的同学,可以深入到这几种方式的内部,这里就不做探讨了。
4、populateBean
在实例化结束后,将进入属性赋值阶段。
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {boolean continueWithPropertyPopulation = true;if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {for (BeanPostProcessor bp : getBeanPostProcessors()) {//如果属于InstantiationAwareBeanPostProcessor类型,则调用postProcessAfterInstantiationif (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {continueWithPropertyPopulation = false;break;}}}}//一旦任意一个InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation返回false,属性注入阶段将不再进行,直接进入下一个阶段if (!continueWithPropertyPopulation) {return;}PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {MutablePropertyValues newPvs = new MutablePropertyValues(pvs);//按照名称注入if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) {autowireByName(beanName, mbd, bw, newPvs);}//按照类型注入if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {autowireByType(beanName, mbd, bw, newPvs);}pvs = newPvs;}//省略掉InstantiationAwareBeanPostProcessor其他两个扩展点及下面的依赖检查if (pvs != null) {//属性注入applyPropertyValues(beanName, mbd, bw, pvs);}}
到这里,实例化与属性赋值阶段结束,我们整理一下其中的扩展点
三、初始化阶段
从doCreateBean内的initializeBean开始
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {//1.设置Aware相关依赖if (System.getSecurityManager() != null) {AccessController.doPrivileged((PrivilegedAction<Object>) () -> {invokeAwareMethods(beanName, bean);return null;}, getAccessControlContext());}else {invokeAwareMethods(beanName, bean);}//2.调用BeanPostProcessor的前置处理Object wrappedBean = bean;if (mbd == null || !mbd.isSynthetic()) {wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);}//3.1调用InitializingBean的afterPropertiesSet方法//3.2调用自定义的init method方法try {invokeInitMethods(beanName, wrappedBean, mbd);}catch (Throwable ex) {throw new BeanCreationException((mbd != null ? mbd.getResourceDescription() : null),beanName, "Invocation of init method failed", ex);}//4.调用BeanPostProcessor的后置处理if (mbd == null || !mbd.isSynthetic()) {wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);}return wrappedBean;}
1、设置Aware相关依赖
private void invokeAwareMethods(final String beanName, final Object bean) {if (bean instanceof Aware) {//如果bean实现了BeanNameAware接口,则设置BeanNameif (bean instanceof BeanNameAware) {((BeanNameAware) bean).setBeanName(beanName);}//如果bean实现了BeanClassLoaderAware接口,则设置BeanClassLoaderif (bean instanceof BeanClassLoaderAware) {ClassLoader bcl = getBeanClassLoader();if (bcl != null) {((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);}}//如果bean实现了BeanFactoryAware接口,则设置BeanFactoryif (bean instanceof BeanFactoryAware) {((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);}}}
从这里可以看出,只要Bean实现了指定的Aware接口,Spring就会向Bean注入这些Aware相关信息。
2、调用BeanPostProcessor的前置处理
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)throws BeansException {Object result = existingBean;//获取所有BeanPostProcessor的实现类for (BeanPostProcessor processor : getBeanPostProcessors()) {//挨个调用postProcessBeforeInitialization方法Object current = processor.postProcessBeforeInitialization(result, beanName);if (current == null) {return result;}result = current;}return result;}
这一步会获取容器中所有BeanPostProcessor的实现类,挨个调用postProcessBeforeInitialization方法。在其返回不为null的情况下,后一个结果会覆盖上一个结果。
当然在处理到ApplicationContextAwareProcessor的时候,会设置以下Aware依赖。
- EnvironmentAware
- EmbeddedValueResolverAware
- ResourceLoaderAware
- ApplicationEventPublisherAware
- MessageSourceAware
- ApplicationContextAware
在处理到InitDestroyAnnotationBeanPostProcessor,会找出被@PostConstruct注解修饰的方法,并执行。
3、invokeInitMethods
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)throws Throwable {//如果实现了InitializingBean接口,则调用afterPropertiesSet方法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();}}//调用xml中声明的init-method指定的方法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);}}}
4、调用BeanPostProcessor的后置处理
和前置处理类似,只是调用postProcessAfterInitialization方法,不再赘述。
因此,初始化过程又可以被细分为
四、销毁阶段
在容器关闭的时候,会进入Bean的销毁阶段,代码从AbstractApplicationContext的close()方法开始
不急着进入close()方法,先看一下第一节代码中最末尾的方法:
protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);//如果Bean不是多例且需要在容器关闭时销毁if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {if (mbd.isSingleton()) {//给当前Bean绑定一个DisposableBeanAdapterregisterDisposableBean(beanName,new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));}else {// A bean with a custom 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, getBeanPostProcessors(), acc));}}}public void registerDisposableBean(String beanName, DisposableBean bean) {synchronized (this.disposableBeans) {this.disposableBeans.put(beanName, bean);}}
在registerDisposableBeanIfNecessary中,会对每一个需要在容器关闭时进行销毁的单例Bean,绑定对应的DisposableBeanAdapter对象。最后把这些Bean及其DisposableBeanAdapter放入进名称为disposableBeans的map中,以供后续使用。
现在我们进入AbstractApplicationContext的close()方法
一路上兜兜转转,会进入到DefaultSingletonBeanRegistry的destroySingletons方法中
public void destroySingletons() {String[] disposableBeanNames = StringUtils.toStringArray(this.disposableBeans.keySet());for (int i = disposableBeanNames.length - 1; i >= 0; i--) {destroySingleton(disposableBeanNames[i]);}//省略部分代码}
先拿到所有待销毁Bean的名称,挨个调用destroySingleton方法,一直往下走,最终会进入到DefaultSingletonBeanRegistry的destroyBean中
其中核心的一句
// Actually destroy the bean now...bean.destroy();
按照beanName从disposableBeans中获取到bean对应的DisposableBeanAdapter,调用其destroy方法
public void destroy() {//调用被@PreDestroy注解修饰的方法//具体可以跟进InitDestroyAnnotationBeanPostProcessor类if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {processor.postProcessBeforeDestruction(this.bean, this.beanName);}}//如果实现了DisposableBean接口,则调用destroy方法if (this.invokeDisposableBean) {if (System.getSecurityManager() != null) {AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {((DisposableBean) this.bean).destroy();return null;}, this.acc);} else {((DisposableBean) this.bean).destroy();}}//调用xml中自定义的destroy-method方法if (this.destroyMethod != null) {invokeCustomDestroyMethod(this.destroyMethod);} else if (this.destroyMethodName != null) {Method methodToCall = determineDestroyMethod(this.destroyMethodName);if (methodToCall != null) {invokeCustomDestroyMethod(methodToCall);}}}
到这里,Bean的销毁过程基本就结束了,我们使用一张图来概括下:
五、生命周期的全流程
我们整个阶段串联起来
六、代码验证
待观察的Bean
public class A implements BeanNameAware, BeanClassLoaderAware, BeanFactoryAware, InitializingBean, DisposableBean {private int id;public int getId() {return id;}public void setId(int id) {this.id = id;System.out.println("属性赋值");}private A() {System.out.println("实例化");}@PostConstructpublic void postConstruct() {System.out.println("@PostConstruct指定的方法");}@Overridepublic void setBeanClassLoader(ClassLoader classLoader) {System.out.println("BeanClassLoaderAware.setBeanClassLoader");}@Overridepublic void setBeanFactory(BeanFactory beanFactory) throws BeansException {System.out.println("BeanFactoryAware.setBeanFactory");}@Overridepublic void setBeanName(String name) {System.out.println("BeanNameAware.setBeanName");}@Overridepublic void afterPropertiesSet() {System.out.println("InitializingBean.afterPropertiesSet");}public void initMethod() {System.out.println("xml中init-method指定的方法");}@PreDestroypublic void preDestroy() {System.out.println("@PreDestroy指定的方法");}@Overridepublic void destroy() {System.out.println("DisposableBean.destroy");}public void destroyMethod() {System.out.println("xml中destroy-method指定的方法");}}
自定义的BeanPostProcessor
public class BeanPostProcessorImpl implements BeanPostProcessor {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {if (beanName.equals("a")) {System.out.println("BeanPostProcessor.postProcessBeforeInitialization");}return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if (beanName.equals("a")) {System.out.println("BeanPostProcessor.postProcessAfterInitialization");}return bean;}
}
自定义的InstantiationAwareBeanPostProcessorImpl
public class InstantiationAwareBeanPostProcessorImpl implements InstantiationAwareBeanPostProcessor {@Overridepublic Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {if (beanName.equals("a")) {System.out.println("InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation");}return null;}@Overridepublic boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {if (beanName.equals("a")) {System.out.println("InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation");}//如果这里返回false,那么所有Bean将不进行属性赋值return true;}
}
spring.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttps://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><context:component-scan base-package="com.yang.ym"/><bean id="a" class="com.yang.ym.testBean.A" init-method="initMethod" destroy-method="destroyMethod"><property name="id" value="1"/></bean><bean class="com.yang.ym.testBean.BeanPostProcessorImpl"/><bean class="com.yang.ym.testBean.InstantiationAwareBeanPostProcessorImpl"/>
</beans>
测试类
@Testpublic void get() {ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");A a = (A) context.getBean("a");System.out.println("关闭容器");context.close();}
输出结果:
InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation
实例化
InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation属性赋值BeanNameAware.setBeanName
BeanClassLoaderAware.setBeanClassLoader
BeanFactoryAware.setBeanFactoryBeanPostProcessor.postProcessBeforeInitialization
@PostConstruct指定的方法
InitializingBean.afterPropertiesSet
xml中init-method指定的方法
BeanPostProcessor.postProcessAfterInitialization关闭容器
@PreDestroy指定的方法
DisposableBean.destroy
xml中destroy-method指定的方法
七、总结
先记住4个大阶段,实例化、属性赋值、初始化与销毁。
在生命周期内部,可以自定义Bean后置处理器以及实现接口的形式来进行扩展
- 容器级的扩展点,InstantiationAwareBeanPostProcessor与BeanPostProcessor。
- Bean级的扩展点,Aware相关接口,InitializingBean与DisposableBean。
此外,可以使用注解或xml配置形式,指定扩展点
- @PostConstruct注解
- @PreDestroy注解
- xml中init-method
- xml中destroy-method
那么再记忆生命周期的先后顺序,就会容易很多:
getBean
- InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation
- 实例化
- InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation
- 属性赋值
- Aware接口回调
- BeanPostProcessor.postProcessBeforeInitialization
- @PostConstruct指定的方法
- InitializingBean.afterPropertiesSet
- xml中init-method指定的方法
- BeanPostProcessor.postProcessAfterInitialization
关闭容器后
- @PreDestroy指定的方法
- DisposableBean.destroy
- xml中destroy-method指定的方法
还记不住Spring Bean的生命周期?看这篇你就知道方法了!相关推荐
- 你还在问我Bean的生命周期?带你看看一个Spring Bean从诞生到逝去的九次人生转折!
前言 关于Spring生命周期的学习,前面已经写过很多篇文章去不断的探究Spring对一个Bean的创建.管理过程,在整个SpringBean的生命周期中,BeanPostProcessor是不可绕过 ...
- 再聊Spring Bean的生命周期
Spring Bean的生命周期是Spring面试热点问题.这个问题即考察对Spring的微观了解,又考察对Spring的宏观认识,想要答好并不容易!本文希望能够从源码角度入手,帮助面试者彻底搞定Sp ...
- 字节跳动面试题:“请你描述下 Spring Bean 的生命周期?”
1. 引言 "请你描述下 Spring Bean 的生命周期?",这是面试官考察 Spring 的常用问题,可见是 Spring 中很重要的知识点. 我之前在准备面试时,去网上搜过 ...
- 带你读懂Spring Bean 的生命周期,嘿,就是玩儿~
带你读懂Spring Bean 的生命周期,嘿,就是玩儿~ 一.前言 今天我们来说一说 Spring Bean 的生命周期,小伙伴们应该在面试中经常遇到,这是正常现象.因为 Spring Bean 的 ...
- 简述 Spring Bean的生命周期
"请你描述下 Spring Bean 的生命周期?",这是面试官考察 Spring 的常用问题,可见是 Spring 中很重要的知识点. 其实要记忆该过程,还是需要我们先去理解,本 ...
- Java Spring Bean的生命周期 三级缓存
Java Spring Bean的生命周期 三级缓存 SpringBean的生命周期:是从 Bean 实例化之后(即通过反射创建出对象之后),到Bean成为一个完整对象,最终存储到单例池中,这个过程被 ...
- Spring bean 实现生命周期的三种解决方案
Spring bean 实现生命周期的三种解决方案 参考文章: (1)Spring bean 实现生命周期的三种解决方案 (2)https://www.cnblogs.com/javawebsoa/a ...
- 请解释Spring Bean 的生命周期?
Spring Bean 的生命周期简单易懂.在一个bean 实例被初始化时,需要执行一系列的初始化操作以达到可用的状态.同样的,当一个bean 不在被调用时需要进行相关的析构操作,并从bean 容器中 ...
- Spring Bean的生命周期及接口回调
本篇介绍Spring框架为Spring Bean生命周期各阶段提供的回调接口,程序通过实现回调接口,可以在IOC容器实例化或销毁Bean的过程中,得到Bean的控制权,并对Bean进行预处理工作.通过 ...
- Spring Bean的生命周期(非常详细)
Spring作为当前Java最流行.最强大的轻量级框架,受到了程序员的热烈欢迎.准确的了解Spring Bean的生命周期是非常必要的.我们通常使用ApplicationContext作为Spring ...
最新文章
- python自动化测试视频百度云-Python接口自动化测试视频教程下载
- PyQt5 技术篇-窗口名、窗口图标的设置方法。
- 神策数据:从技术视角看,如何更多、更好、更快地实施A/B试验
- padavan 源码
- RTC实时时钟实验(低功耗、纽扣电池供电)
- jquery添加未来元素时,其绑定事件不起作用解决办法
- 红帽取代 Oracle,接管 OpenJDK 8 和 OpenJDK 11 | 极客头条
- 学号 20165329 《Java程序设计》第4周学习总结
- 改变swap分区大小
- JDBC的下载和安装教程
- C语言 运算符与表达式
- 机器学习之【蒙特卡罗法】
- HDU-1317 XYZZY SPEA
- bigworld源码分析(2)—— loginApp分析
- uva 557 Buger 概率
- 线性回归模型(Linear regression model)
- React 360 初体验介绍与环境搭建
- 如何计算词语的相似性(附github)
- 7.4 小团队、低成本的管理实践之路
- PHP CURL解决 此图片来自QQ微信公众平台,未经允许不可引用
热门文章
- 论文解读:《EMDLP:RNA甲基化位点预测的合奏多尺度深度学习模型》
- docker容器的导入和导出
- 微信开发者工具测试方法
- Pyhton中dataFrame型数据 values方法返回结果是数组,并将数组转化为列表的tolist方法
- Air Keyboard
- 415 http请求 hutool_HTTP请求返回415错误码定位解决方法
- php httprequest 415,http post 415错误的解决方法
- 【打卡算法】 26、删除有序数组中的重复项 算法解析
- Python学习3-层次聚类
- 台式计算机装机,DIY台式电脑装机教程之新手装机图解!手把手教你组装电脑