乐趣区

关于spring:Spring-Bean的生命周期

忽然感觉问答体很适宜解释一些问题,本篇文章咱们接着采纳问答故事体的形式来讲下面这个问题,这是我之前面试的时候,被问道的。这次来彻底的探讨一下这个问题。

Bean 生命周期概念的引入

某一天小陈感觉在这个公司有点厌倦了, 筹备悄悄的跑路,于是一边下班,一边筹备面试题,一边下班,这天他看到了这样一个面试题 Spring Bean 的生命周期,有点了解不动,他想到了他的领导,那个技术栈特地宽的领导,于是就找到了领导问: 领导我对一个 Spring Bean 生命周期这个概念有点不太了解,您有工夫的话能够给我讲讲吗?

领导说: 等下,我正在解决一个问题,一会儿,我去找你去。过了十五分钟后,领导就来到了小陈的工位,说道:当初咱们来过 Spring Bean 的生命周期这个概念吧!筹备好了吗?小陈点了拍板。

领导说道: 首先咱们要弄清楚生命周期的含意,生命周期的英文是 Life Cycle,简略的说就是 Spring 给咱们提供的一些扩大接口,如果 bean 实现了这些这些接口,利用在启动的过程中会回调这些接口的办法。在 Spring 中一个 bean 的毕生通常就是先创立其对象,而后填充其属性,如果这个 Bean 实现了 Spring 提供的扩大接口,那么在 IOC 容器加载的时候会顺次回调这些办法。这些扩大接口的对应办法的回调程序如下:

画完图后领导问道: 这外面哪个单词你熟一些啊, 拿出来讲一下。

小陈心里想领导的这个 PPT 画的怎么这么纯熟,还是接着答复道:我如同只见过 ApplicationContext, 我刚学 Spring 框架的时候,用这个 ApplicatonContext 来获取加载进 IOC 容器的对象,像上面这样:

public static void main(String[] args) {ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringBeanConfig.class);
        applicationContext.getBean(StudentService.class);
}

领导点了拍板,接着说道: 大多数入门都是从这样的例子开始的,说道这里看着下面的代码你想到了设计模式的哪个模式?

小陈答复道: 这让我想起了简略工厂模式,我给一个标识,由 ApplicationContext 给我加载对应的对象。

领导点了拍板: ApplicationContext 继承自 BeanFactory, 下面确实是应用了简略工厂模式。下面接口中带有 Aware 的, 都继承自 Aware 接口。子类将对于父类来说提供的性能更为丰盛。setBeanName 会从换入实现 BeanNameAware 接口的 Bean Id 和 Bean 名称,也就是说容器在初始化 Bean 和填充完 Bean 的属性之后,会回顺次回调 BeanNameAware、ApplicationContextAware、BeanPostProcessor 的 postProcessBeforeInitialization、InitializingBean 的 afterPropertiesSet 办法,Bean 的 init-method 办法、BeanPostProcessor 的 postProcessAfterInitialization 的办法。这里要留神 BeanNameAware、ApplicationContextAware 只会回调顺次,每个 Bean 实现初始化之后都会回调 BeanPostProcessor 的两个办法。到这里其实就完结了。上面咱们写个代码来演示一下下面的程序:

public class BeanLifeCycleDemo implements BeanNameAware, BeanFactoryAware, ApplicationContextAware, InitializingBean,BeanPostProcessor{

    private MuttonSoupService muttonSoupService;

    public BeanLifeCycleDemo( ) {System.out.println("1. 构造函数初始化 bean");
    }

    @Autowired
    public void setMuttonSoupService(MuttonSoupService muttonSoupService) {System.out.println("2. 先填充属性 -");
        this.muttonSoupService = muttonSoupService;
    }

    public void sayHelloWorld(){System.out.println("hello world");
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {System.out.println("----4-- 接着是 BeanFactoryAware");
    }

    @Override
    public void setBeanName(String name) {System.out.println("3---- name+" + name);
    }

    @Override
    public void afterPropertiesSet() throws Exception {System.out.println("----7 afterPropertiesSet");
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {System.out.println("------5 applicationContextAware");
    }


    public void initMethod(){System.out.println("6 init-method");
    }

    /**
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println("---- postProcessBeforeInitialization"+beanName);
        return bean;
    }

    /**
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println("---- postProcessAfterInitialization");
        return bean;
    }

}
@Configuration
public class SpringBeanConfig {@Bean(initMethod = "initMethod")
    public BeanLifeCycleDemo beanLifeCycleDemo(){return new BeanLifeCycleDemo();
    }
}
@SpringBootTest
class SsmApplicationTests {

    @Autowired
    private BeanLifeCycleDemo beanLifeStyleDemo;
    
    // 间接运行测试即可
    @Test
    public void test(){}
}    

输入后果:

小陈看到了这个后果, 心里有点开心,领导翻车了,于是说道:领导你这个程序跟下面图的程序不一样欸。我还有一个问题,这个 Bean 是永生的吗?

领导淡淡的说道:我是成心演示给你看的, 留神这个 BeanPostProcessor,这个接口对应的 Bean 须要事后加载进入能力实现下面的成果。Spring Bean 的加载程序如下图 (上面这张图是网上找的) 所示:

所以咱们在写一个 BeanPostProcessor 的 bean 就能实现下面的程序了。至于 Bean 生命的完结, 其实我是成心考验你的。其实也就是一个接口和一个属性而已. 接口是 DisposableBean,属性在 @Bean 中有个 destroyMethod。这两个属性也有代替注解,init-method=@PostConstruct, @PreDestroy=destroyMethod。联合下面的图咱们能够大抵理解了 Spring IOC 容器加载 Bean 的流程,所谓的生命周期在某种程度上能够看成在加载 Bean 的过程的回调。

小陈说道: 谢谢领导,我感觉我对这个概念了解的更通透了,绝对于生命周期,我更喜爱你回调的说法呢。

参考资料

  • Spring – Bean Life Cycle https://howtodoinjava.com/spr…
  • Spring 用到哪些设计模式 https://199604.com/2188
  • BeanPostProcessor —— 连贯 Spring IOC 和 AOP 的桥梁 https://zhuanlan.zhihu.com/p/…
退出移动版