zoukankan      html  css  js  c++  java
  • 【Spring】Bean的LifeCycle(生命周期)

    菜瓜:水稻,上次说Bean的LifeCycle,还没讲完

    水稻:啥?说人话?

    菜瓜:spring,bean,生命周期

    水稻:。。。那你真的是很棒棒哦!。。。bean生命周期的话,从BeanFactory、ApplicationContext和FactoryBean开始说起

    • 我们知道(你不一定知道)BeanFactory是Spring访问Bean容器的根接口,源码的注释: “The root interface for accessing a Spring bean container.”
    • 而ApplicationContext继承自BeanFactory,也就是说它具有BeanFactory的属性和方法,并进一步完善(继承其他的接口)
    • FactoryBean跟前两个关系就不怎么大了,它是spring提供给用户创建bean的口子,有一些bean创建过程复杂,或者依赖第三方包等(Mybatis-Spring中),可交给用户自己创建

    菜瓜:嗯。。陷入沉思。。(欲言又止)

    水稻:讲理论不给代码就是耍流氓

    • package com.vip.qc.postprocessor;
      
      import org.springframework.beans.factory.FactoryBean;
      import org.springframework.stereotype.Component;
      
      /**
       * @author QuCheng on 2020/6/15.
       */
      @Component("fb")
      public class FactoryBeanT implements FactoryBean<FactoryBeanT.CustomBean> {
      
          public FactoryBeanT() {
              System.out.println("实现FactoryBean接口的类自身被放在IOC一级缓存的容器里面,getObject的对象是在另一个缓存对象中");
          }
      
          @Override
          public CustomBean getObject() {
              return new CustomBean();
          }
      
          @Override
          public Class<?> getObjectType() {
              return CustomBean.class;
          }
      
          static class CustomBean {
              public CustomBean() {
                  System.out.println("自定义bean");
              }
          }
      }
      
      测试方法
      @Test
      public void testTransa() {
          BeanFactory context = new AnnotationConfigApplicationContext(ComponentScanD.class);
          System.out.println("factoryBean : " + context.getBean("fb"));
          System.out.println("&factoryBean : " + context.getBean("&fb"));
      }

      测试结果

        实现FactoryBean接口的类自身被放在IOC一级缓存的容器里面,getObject的对象是在另一个缓存对象中
        自定义bean
        factoryBean : com.vip.qc.postprocessor.FactoryBeanT$CustomBean@214b199c
        &factoryBean : com.vip.qc.postprocessor.FactoryBeanT@20d3d15a

    菜瓜:懂了,BeanFactory是Spring的核心--容器,ApplicationContext则是包裹容器的上下文,丰富容器的功能(资源加载,事件驱动等)。FactoryBean也是Spring扩展性的体现

    水稻:WC,你这个总结提到了精髓。就是扩展性:如果BeanFactory是核心思想,那么其他的上下文,后置处理器,还是Aware接口等等,都是为了实现扩展

    菜瓜:铺垫说完了,开始生命周期呗

    水稻:这次咱们反过来先看源码,再看实验,再总结

    • BeanFactory源码注释 - 定义了实现的生命周期
    •  * @author Rod Johnson
       * @author Juergen Hoeller
       * @author Chris Beams
       * @since 13 April 2001
       * @see BeanNameAware#setBeanName
       * @see BeanClassLoaderAware#setBeanClassLoader
       * @see BeanFactoryAware#setBeanFactory
       * @see org.springframework.context.ResourceLoaderAware#setResourceLoader
       * @see org.springframework.context.ApplicationEventPublisherAware#setApplicationEventPublisher
       * @see org.springframework.context.MessageSourceAware#setMessageSource
       * @see org.springframework.context.ApplicationContextAware#setApplicationContext
       * @see org.springframework.web.context.ServletContextAware#setServletContext
       * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization
       * @see InitializingBean#afterPropertiesSet
       * @see org.springframework.beans.factory.support.RootBeanDefinition#getInitMethodName
       * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization
       * @see DisposableBean#destroy
       * @see org.springframework.beans.factory.support.RootBeanDefinition#getDestroyMethodName
       */
      public interface BeanFactory {
    • BeanFactory源码实现类
    • public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory
      
      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 {
                  // BeanNameAware BeanFactoryAware ...
                  invokeAwareMethods(beanName, bean);
              }
      
              Object wrappedBean = bean;
              if (mbd == null || !mbd.isSynthetic()) {
                  // BeanPostProcessor Before  @PostConstruct
                  wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
              }
      
              try {
                  // initMethod InitializingBean接口
                  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()) {
                  // BeanPostProcessor after
                  wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
              }
      
              return wrappedBean;
          }
    • 实验代码
    • package com.vip.qc.postprocessor;
      
      import org.springframework.beans.BeansException;
      import org.springframework.beans.factory.config.BeanDefinition;
      import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
      import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
      import org.springframework.stereotype.Component;
      
      /**
       * @author QuCheng on 2020/6/14.
       */
      @Component
      public class BeanFactoryPostProcessorT implements BeanFactoryPostProcessor {
      
          public static final String BEAN_NAME = "initializingBeanT";
      
          @Override
          public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
              BeanDefinition initializingBeanT = beanFactory.getBeanDefinition(BEAN_NAME);
              System.out.println("BeanFactoryPostProcessor bean " + initializingBeanT.getBeanClassName());
          }
      }
      
      
      
      package com.vip.qc.postprocessor;
      
      import org.springframework.beans.BeansException;
      import org.springframework.beans.factory.config.BeanPostProcessor;
      import org.springframework.stereotype.Component;
      
      /**
       * @author QuCheng on 2020/6/14.
       */
      @Component
      public class BeanPostProcessorT implements BeanPostProcessor {
      
          public static final String BEAN_NAMET = "initializingBeanT";
      
          @Override
          public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
              if (BEAN_NAMET.equals(beanName)) {
                  InitializingBeanT processorT = ((InitializingBeanT) bean);
                  System.out.println("BeanPostProcessor BeforeInitialization " + processorT);
              }
              return bean;
          }
      
          @Override
          public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
              if (BEAN_NAMET.equals(beanName)){
                  InitializingBeanT processorT = ((InitializingBeanT) bean);
                  System.out.println("BeanPostProcessor AfterInitialization " + processorT);
              }
              return bean;
          }
      
      }
      
      
      package com.vip.qc.postprocessor;
      
      import org.springframework.beans.factory.BeanNameAware;
      import org.springframework.beans.factory.DisposableBean;
      import org.springframework.beans.factory.InitializingBean;
      import org.springframework.stereotype.Component;
      
      import javax.annotation.PostConstruct;
      import javax.annotation.PreDestroy;
      
      /**
       * @author QuCheng on 2020/6/14.
       */
      @Component
      public class InitializingBeanT implements BeanNameAware, InitializingBean, DisposableBean {
      
          public InitializingBeanT() {
              System.out.println("init无参构造 execute");
          }
      
          @PostConstruct
          public void postConstruct() {
              System.out.println("@PostConstruct  execute");
          }
      
          @PreDestroy
          public void preDestroy() {
              System.out.println("@PreDestroy  execute");
          }
      
          @Override
          public void afterPropertiesSet() {
              System.out.println("InitializingBean afterPropertiesSet --> " + this.toString());
          }
      
          @Override
          public void setBeanName(String name) {
              System.out.println("BeanNameAware : " + name);
          }
      
          @Override
          public void destroy() {
              System.out.println("destroy");
          }
      }
      
      
      测试代码
          @Test
          public void testLifeCycle() {
              AbstractApplicationContext applicationContext = new AnnotationConfigApplicationContext(ComponentScanD.class);
              applicationContext.close();// 这里不关闭容器的话,注销bean的方法会看不到打印
          }

      测试结果

        BeanFactoryPostProcessor bean com.vip.qc.postprocessor.InitializingBeanT
        init无参构造 execute
        BeanNameAware : initializingBeanT
        BeanPostProcessor BeforeInitialization com.vip.qc.postprocessor.InitializingBeanT@15bb6bea
        @PostConstruct execute
        InitializingBean afterPropertiesSet --> com.vip.qc.postprocessor.InitializingBeanT@15bb6bea
        BeanPostProcessor AfterInitialization com.vip.qc.postprocessor.InitializingBeanT@15bb6bea
        @PreDestroy execute
        destroy

    菜瓜:实现什么的不重要,接口才是爸爸呀,BeanFactory定义好了生命周期,下面的实现也只是实现罢了

    水稻:哈哈,你说的对,一流的公司卖标准

    菜瓜:这里怎么没看到循环依赖的处理啊

    水稻:是的。这里的源码我只截取了bean初始化完成之后的接口调用。循环依赖的处理在它前面。来来来,继续刚

    菜瓜:刚不了刚不了,你一下子搞这么多玩意给我看,我哪看得完

    水稻:您歇着,下次您什么时候想了解我再给您说

    总结

    • BeanFactory已经定义了整个的生命周期,子类只是负责实现,demo演示也只是为了证实。我们更应该关注更上层的东西 
    • ApplicationContext是对容器更精细化的包装,提供了更完善的功能
    • FactoryBean是Spring扩展性的提现,可供用户自己定义创建bean。扩展性提炼的很好
  • 相关阅读:
    js数组
    关于编程,程序员的一些语录
    css心得
    js函数
    一些电脑基础知识
    gnome3安装
    C学习小记
    ubuntu重装系统后
    elinks文字浏览器
    快捷方式
  • 原文地址:https://www.cnblogs.com/nightOfStreet/p/13117806.html
Copyright © 2011-2022 走看看