一、前言

上次我们在手把手教你解决循环依赖,一步一步地来窥探出三级缓存的奥秘中分析了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

  1. InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation
  2. 实例化
  3. InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation
  4. 属性赋值
  5. Aware接口回调
  6. BeanPostProcessor.postProcessBeforeInitialization
  7. @PostConstruct指定的方法
  8. InitializingBean.afterPropertiesSet
  9. xml中init-method指定的方法
  10. BeanPostProcessor.postProcessAfterInitialization

关闭容器后

  1. @PreDestroy指定的方法
  2. DisposableBean.destroy
  3. xml中destroy-method指定的方法

还记不住Spring Bean的生命周期?看这篇你就知道方法了!相关推荐

  1. 你还在问我Bean的生命周期?带你看看一个Spring Bean从诞生到逝去的九次人生转折!

    前言 关于Spring生命周期的学习,前面已经写过很多篇文章去不断的探究Spring对一个Bean的创建.管理过程,在整个SpringBean的生命周期中,BeanPostProcessor是不可绕过 ...

  2. 再聊Spring Bean的生命周期

    Spring Bean的生命周期是Spring面试热点问题.这个问题即考察对Spring的微观了解,又考察对Spring的宏观认识,想要答好并不容易!本文希望能够从源码角度入手,帮助面试者彻底搞定Sp ...

  3. 字节跳动面试题:“请你描述下 Spring Bean 的生命周期?”

    1. 引言 "请你描述下 Spring Bean 的生命周期?",这是面试官考察 Spring 的常用问题,可见是 Spring 中很重要的知识点. 我之前在准备面试时,去网上搜过 ...

  4. 带你读懂Spring Bean 的生命周期,嘿,就是玩儿~

    带你读懂Spring Bean 的生命周期,嘿,就是玩儿~ 一.前言 今天我们来说一说 Spring Bean 的生命周期,小伙伴们应该在面试中经常遇到,这是正常现象.因为 Spring Bean 的 ...

  5. 简述 Spring Bean的生命周期

    "请你描述下 Spring Bean 的生命周期?",这是面试官考察 Spring 的常用问题,可见是 Spring 中很重要的知识点. 其实要记忆该过程,还是需要我们先去理解,本 ...

  6. Java Spring Bean的生命周期 三级缓存

    Java Spring Bean的生命周期 三级缓存 SpringBean的生命周期:是从 Bean 实例化之后(即通过反射创建出对象之后),到Bean成为一个完整对象,最终存储到单例池中,这个过程被 ...

  7. Spring bean 实现生命周期的三种解决方案

    Spring bean 实现生命周期的三种解决方案 参考文章: (1)Spring bean 实现生命周期的三种解决方案 (2)https://www.cnblogs.com/javawebsoa/a ...

  8. 请解释Spring Bean 的生命周期?

    Spring Bean 的生命周期简单易懂.在一个bean 实例被初始化时,需要执行一系列的初始化操作以达到可用的状态.同样的,当一个bean 不在被调用时需要进行相关的析构操作,并从bean 容器中 ...

  9. Spring Bean的生命周期及接口回调

    本篇介绍Spring框架为Spring Bean生命周期各阶段提供的回调接口,程序通过实现回调接口,可以在IOC容器实例化或销毁Bean的过程中,得到Bean的控制权,并对Bean进行预处理工作.通过 ...

  10. Spring Bean的生命周期(非常详细)

    Spring作为当前Java最流行.最强大的轻量级框架,受到了程序员的热烈欢迎.准确的了解Spring Bean的生命周期是非常必要的.我们通常使用ApplicationContext作为Spring ...

最新文章

  1. python自动化测试视频百度云-Python接口自动化测试视频教程下载
  2. PyQt5 技术篇-窗口名、窗口图标的设置方法。
  3. 神策数据:从技术视角看,如何更多、更好、更快地实施A/B试验
  4. padavan 源码
  5. RTC实时时钟实验(低功耗、纽扣电池供电)
  6. jquery添加未来元素时,其绑定事件不起作用解决办法
  7. 红帽取代 Oracle,接管 OpenJDK 8 和 OpenJDK 11 | 极客头条
  8. 学号 20165329 《Java程序设计》第4周学习总结
  9. 改变swap分区大小
  10. JDBC的下载和安装教程
  11. C语言 运算符与表达式
  12. 机器学习之【蒙特卡罗法】
  13. HDU-1317 XYZZY SPEA
  14. bigworld源码分析(2)—— loginApp分析
  15. uva 557 Buger 概率
  16. 线性回归模型(Linear regression model)
  17. React 360 初体验介绍与环境搭建
  18. 如何计算词语的相似性(附github)
  19. 7.4 小团队、低成本的管理实践之路
  20. PHP CURL解决 此图片来自QQ微信公众平台,未经允许不可引用

热门文章

  1. 论文解读:《EMDLP:RNA甲基化位点预测的合奏多尺度深度学习模型》
  2. docker容器的导入和导出
  3. 微信开发者工具测试方法
  4. Pyhton中dataFrame型数据 values方法返回结果是数组,并将数组转化为列表的tolist方法
  5. Air Keyboard
  6. 415 http请求 hutool_HTTP请求返回415错误码定位解决方法
  7. php httprequest 415,http post 415错误的解决方法
  8. 【打卡算法】 26、删除有序数组中的重复项 算法解析
  9. Python学习3-层次聚类
  10. 台式计算机装机,DIY台式电脑装机教程之新手装机图解!手把手教你组装电脑