前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring5.0源码深度解析之SpringBean的生命周期

Spring5.0源码深度解析之SpringBean的生命周期

作者头像
须臾之余
发布2019-07-31 17:19:58
6680
发布2019-07-31 17:19:58
举报
文章被收录于专栏:须臾之余须臾之余

一:单例与多例对象是如何初始化

单例默认情况下是在容器被加载的时候就会初始化 多例是在每次获取Bean对象的时候初始化

代码验证:

代码语言:javascript
复制
@Component
public class UserEntity {
    public UserEntity() {
        System.out.println(">>>>UserEntity无参数构造函数执行...");
    }
代码语言:javascript
复制
@Configuration
@ComponentScan("com.mayikt.entity")
public class MyConfig {
}

>>>>UserEntity无参数构造函数执行...

当加上@Scope("prototype"),没有输出结果

代码语言:javascript
复制
@Component
@Scope("prototype")
public class UserEntity {
    public UserEntity() {
        System.out.println(">>>>UserEntity无参数构造函数执行...");
    }

说明单例默认是在容器被加载的时候初始化,多例是在每次获取Bean对象的时候初始化。

二:Bean对象的初始化与销毁过程01

Bean初始化:指的就是对象已经创建,里面的所有set方法都已经执行完毕了。

举个例子:

代码语言:javascript
复制
@Configuration
@ComponentScan("com.mayikt.entity")
public class MyConfig {

    /**
     * initMethod:指定初始化方法执行
     * destroyMethod:指定销毁方法
     * @return
     */
    @Bean(initMethod = "initMethod",destroyMethod = "destroyMethod")
    public UserEntity userEntity(){
        return new UserEntity();
    }
}
代码语言:javascript
复制
@Component
public class UserEntity {
    public UserEntity() {
        System.out.println(">>>>UserEntity无参数构造函数执行...");
    }
    /**
     * 思考:initMethod是在无参构造函数之前执行还是后执行..
     */
    private void initMethod() {
        System.out.println(">>>>UserEntity initMethod 执行...");
    }
    private void destroyMethod() {
        System.out.println(">>>>UserEntity destroyMethod 执行...");
    }
}
代码语言:javascript
复制
public static void main(String[] args) {
    /**
     * IOC容器初始化单例对象都是循环遍历调用getBean方法
     */
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
    applicationContext.close();

返回结果

>>>>UserEntity无参数构造函数执行... >>>>UserEntity initMethod 执行... >>>>UserEntity destroyMethod 执行...

构造函数:Bean的创建,Map集合存储对象 initMethod:表示对象已经创建成功之后执行 destroyMethod:表示对象被销毁之后执行,clean

分析下源码

代码语言:javascript
复制
applicationContext.close();
代码语言:javascript
复制
public void close() {
   synchronized (this.startupShutdownMonitor) {
      doClose();
      // If we registered a JVM shutdown hook, we don't need it anymore now:
      // We've already explicitly closed the context.
      if (this.shutdownHook != null) {
         try {
            Runtime.getRuntime().removeShutdownHook(this.shutdownHook);
         }
         catch (IllegalStateException ex) {
            // ignore - VM is already shutting down
         }
      }
   }
}
代码语言:javascript
复制
protected void doClose() {
   if (this.active.get() && this.closed.compareAndSet(false, true)) {
      if (logger.isInfoEnabled()) {
         logger.info("Closing " + this);
      }

      LiveBeansView.unregisterApplicationContext(this);

      try {
         // Publish shutdown event.
         publishEvent(new ContextClosedEvent(this));
      }
      catch (Throwable ex) {
         logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent", ex);
      }

      // Stop all Lifecycle beans, to avoid delays during individual destruction.
      try {
         getLifecycleProcessor().onClose();
      }
      catch (Throwable ex) {
         logger.warn("Exception thrown from LifecycleProcessor on context close", ex);
      }

      // Destroy all cached singletons in the context's BeanFactory.
      destroyBeans();

      // Close the state of this context itself.
      closeBeanFactory();

      // Let subclasses do some final clean-up if they wish...
      onClose();

      this.active.set(false);
   }
}
代码语言:javascript
复制
protected void destroyBeans() {
   getBeanFactory().destroySingletons();
}
代码语言:javascript
复制
public void destroySingletons() {
    super.destroySingletons();
    this.manualSingletonNames.clear();
    this.clearByTypeCache();
}
代码语言:javascript
复制
private void clearByTypeCache() {
    this.allBeanNamesByType.clear();
    this.singletonBeanNamesByType.clear();
}

上面执行了clear操作,再回到前面

这里给用户自定义关闭操作:模板方法设计模式

代码语言:javascript
复制
protected void onClose() {
   // For subclasses: do nothing by default.
}

再把活跃状态设置为false。

三:Bean对象的初始化与销毁过程02

实现InitializingBean,DisposableBean两个接口

代码语言:javascript
复制
@Component
public class MemberEntity implements InitializingBean,DisposableBean{
    //     implements InitializingBean, DisposableBean
    public MemberEntity() {
        System.out.println("无参构造函数执行..");
    }
    // afterPropertiesSet initMet hod
    // 1.对象创建 对象属性赋值 set方法全部走完
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("MemberEntity >>>afterPropertiesSet");
    }
    @Override
    public void destroy() throws Exception {
        System.out.println("MemberEntity >>> destroy");
    }
}

输出结果:

无参构造函数执行.. MemberEntity >>>afterPropertiesSet MemberEntity >>> destroy

使用Java封装的注解方式@PostConstruct, @PreDestroy

代码语言:javascript
复制
@Component
public class MemberEntity{
    //     implements InitializingBean, DisposableBean
    public MemberEntity() {
        System.out.println("无参构造函数执行..");
    }
    // afterPropertiesSet initMet hod
    // 1.对象创建 对象属性赋值 set方法全部走完
    @PostConstruct
    public void afterPropertiesSet() throws Exception {
        System.out.println("MemberEntity >>>afterPropertiesSet");
    }
    @PreDestroy
    public void destroy() throws Exception {
        System.out.println("MemberEntity >>> destroy");
    }
}

输出结果

无参构造函数执行.. MemberEntity >>>afterPropertiesSet MemberEntity >>> destroy

四:现在我们开始分析SpringBean的生命周期

SpringBean生命周期有个很好的理念

就是后置处理器:BeanPostProcessor

BeanPostProcessor引入:

代码语言:javascript
复制
@Component
public class MyApplicationContext implements ApplicationContextAware {
    private ApplicationContext applicationContext;
    /**
     * spring底层中为什么能够实现ApplicationContextAware接口 就能够拿到ApplicationContext
     * @param applicationContext
     * @throws BeansException
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        MemberEntity memberEntity = applicationContext.getBean("memberEntity", MemberEntity.class);
        System.out.println("memberEntity:" + memberEntity);
    }
}
代码语言:javascript
复制
@Configuration
@ComponentScan("com.mayikt.entity")
@Import(MyApplicationContext.class)//这里注入到spring容器中
public class MyConfig {}

输出结果:对象初始化,赋值完毕,就可以通过setApplicationContext拿到bean对象

memberEntity:com.mayikt.entity.MemberEntity@11e21d0e

思考问题:spring底层中为什么能够实现ApplicationContextAware接口 就能够拿到ApplicationContext

靠的就是:BeanPostProcessor

下面开始分析:BeanPostProcessor后置处理器(非常重要!!!)

代码语言:javascript
复制
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
代码语言:javascript
复制
public void refresh() throws BeansException, IllegalStateException {
   synchronized (this.startupShutdownMonitor) {
    ....
      try {
      ....
         // Instantiate all remaining (non-lazy-init) singletons.
         finishBeanFactoryInitialization(beanFactory);//这里
      }
....
}
代码语言:javascript
复制
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
 ....
   // Instantiate all remaining (non-lazy-init) singletons.
   beanFactory.preInstantiateSingletons();//这里
}
代码语言:javascript
复制
public void preInstantiateSingletons() throws BeansException {
    List<String> beanNames = new ArrayList(this.beanDefinitionNames);
    Iterator var2 = beanNames.iterator();

    while(true) {
        while(true) {
            String beanName;
            RootBeanDefinition bd;
            do {
                do {
                    do {
                        if (!var2.hasNext()) {
                            var2 = beanNames.iterator();

                            while(var2.hasNext()) {
                                beanName = (String)var2.next();
                                Object singletonInstance = this.getSingleton(beanName);
                                if (singletonInstance instanceof SmartInitializingSingleton) {
                                    SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton)singletonInstance;
                                    if (System.getSecurityManager() != null) {
                                        AccessController.doPrivileged(() -> {
                                            smartSingleton.afterSingletonsInstantiated();
                                            return null;
                                        }, this.getAccessControlContext());
                                    } else {
                                        smartSingleton.afterSingletonsInstantiated();
                                    }
                                }
                            }

                            return;
                        }

                        beanName = (String)var2.next();
                        bd = this.getMergedLocalBeanDefinition(beanName);
                    } while(bd.isAbstract());
                } while(!bd.isSingleton());
            } while(bd.isLazyInit());

            if (this.isFactoryBean(beanName)) {
                FactoryBean<?> factory = (FactoryBean)this.getBean("&" + beanName);
                boolean isEagerInit;
                if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                    isEagerInit = (Boolean)AccessController.doPrivileged(() -> {
                        return ((SmartFactoryBean)factory).isEagerInit();
                    }, this.getAccessControlContext());
                } else {
                    isEagerInit = factory instanceof SmartFactoryBean && ((SmartFactoryBean)factory).isEagerInit();
                }

                if (isEagerInit) {
                    this.getBean(beanName);
                }
            } else {
                this.getBean(beanName);
            }
        }
    }
}
代码语言:javascript
复制
public Object getBean(String name) throws BeansException {
    return this.doGetBean(name, (Class)null, (Object[])null, false);
}
代码语言:javascript
复制
Object sharedInstance = this.getSingleton(beanName);//查找缓存中有没有

判断是单例:

代码语言:javascript
复制
this.populateBean(beanName, mbd, instanceWrapper);//循环给属性赋值
exposedObject = this.initializeBean(beanName, exposedObject, mbd);
代码语言:javascript
复制
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
    if (System.getSecurityManager() != null) {
        AccessController.doPrivileged(() -> {
            this.invokeAwareMethods(beanName, bean);
            return null;
        }, this.getAccessControlContext());
    } else {
        this.invokeAwareMethods(beanName, bean);
    }

    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
    }

    try {
        this.invokeInitMethods(beanName, wrappedBean, mbd);//执行自定义的init方法
    } catch (Throwable var6) {
        throw new BeanCreationException(mbd != null ? mbd.getResourceDescription() : null, beanName, "Invocation of init method failed", var6);
    }

    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }

    return wrappedBean;
}
代码语言:javascript
复制
private void invokeAwareMethods(String beanName, Object bean) {
    if (bean instanceof Aware) {
        if (bean instanceof BeanNameAware) {    //判断类型并设置beanName
            ((BeanNameAware)bean).setBeanName(beanName);
        }

        if (bean instanceof BeanClassLoaderAware) {
            ClassLoader bcl = this.getBeanClassLoader();
            if (bcl != null) {
                ((BeanClassLoaderAware)bean).setBeanClassLoader(bcl);
            }
        }

        if (bean instanceof BeanFactoryAware) {
            ((BeanFactoryAware)bean).setBeanFactory(this);
        }
    }
}

我们就明白了:IOC容器初始化单例对象都是循环遍历调用getBean方法。

下面我们手写看下springBean的生命周期

代码语言:javascript
复制
@Component
public class PayEntity implements BeanNameAware, BeanFactoryAware, InitializingBean, ApplicationContextAware {
    public PayEntity() {
        System.out.println("1.对象的实例化完成..");
    }

    @Override
    public void setBeanName(String name) {
        System.out.println("2.对象beanName:" + name);
    }
    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("3.beanFactory:" + beanFactory);
    }
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("4.获取到applicationContext对象");
    }
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("5.bean init方法执行..");
    }

输出结果

代码语言:javascript
复制
1.对象的实例化完成..
2.对象beanName:payEntity
3.beanFactory:org.springframework.beans.factory.support.DefaultListableBeanFactory@55f3ddb1: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.event.internalEventListenerProcessor,org.springframework.context.event.internalEventListenerFactory,myConfig,payEntity]; root of factory hierarchy
4.获取到applicationContext对象
5.bean init方法执行..

BeanPostProcessor的作用

代码语言:javascript
复制
if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);//init之前处理操作
    }
    try {
        this.invokeInitMethods(beanName, wrappedBean, mbd);//init执行逻辑
    } catch (Throwable var6) {
        throw new BeanCreationException(mbd != null ? mbd.getResourceDescription() : null, beanName, "Invocation of init method failed", var6);
    }

    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);//init之后处理操作
    }

    return wrappedBean;
}

我们自己写个类实现BeanPostProcessor

代码语言:javascript
复制
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
    //BeanPostProcessor 后置处理器 对我们bean的对象实现增强
    @Override
    // 执行自定义init方法之前处理
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("执行init方法之前处理 : " + beanName);
        return bean;
    }

    @Override
    // 执行自定义init方法之后处理
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("执行init方法之后处理 :" + beanName);
        return bean;
    }
    //BeanPostProcessor  后置处理
    // Aware    实现
}

结果

代码语言:javascript
复制
执行init方法之前处理 : org.springframework.context.event.internalEventListenerProcessor
执行init方法之后处理 :org.springframework.context.event.internalEventListenerProcessor
执行init方法之前处理 : org.springframework.context.event.internalEventListenerFactory
执行init方法之后处理 :org.springframework.context.event.internalEventListenerFactory
执行init方法之前处理 : myConfig
执行init方法之后处理 :myConfig
1.对象的实例化完成..
2.对象beanName:payEntity
3.beanFactory:org.springframework.beans.factory.support.DefaultListableBeanFactory@55f3ddb1: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.event.internalEventListenerProcessor,org.springframework.context.event.internalEventListenerFactory,myConfig,payEntity,com.mayikt.processor.MyBeanPostProcessor]; root of factory hierarchy
4.获取到applicationContext对象
执行init方法之前处理 : payEntity
5.bean init方法执行..
执行init方法之后处理 :payEntity

ApplicationAware接口原理

实现ApplicationAware接口怎么就可以setApplicationContext呢?

代码语言:javascript
复制
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    System.out.println("4.获取到applicationContext对象");
}

去后置处理器找

代码语言:javascript
复制
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    return bean;
}
代码语言:javascript
复制
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
   return bean;
}

发现postProcessAfterInitialization没有做什么,再去前置找:

代码语言:javascript
复制
private void invokeAwareInterfaces(Object bean) {
   if (bean instanceof Aware) {
      if (bean instanceof EnvironmentAware) {
         ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
      }
      if (bean instanceof EmbeddedValueResolverAware) {
         ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
      }
      if (bean instanceof ResourceLoaderAware) {
         ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
      }
      if (bean instanceof ApplicationEventPublisherAware) {
         ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
      }
      if (bean instanceof MessageSourceAware) {
         ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
      }
      if (bean instanceof ApplicationContextAware) {//判断ApplicationContextAware类型,赋值
         ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
      }
   }
}

所以我们知道ApplicationContextAware是通过前置实现的。

SpringBean的生命周期总结

源码分析流程:

1、执行refresh()刷新方法 2、finishBeanFactoryInitialization(beanFactory); 3、beanFactory.preInstantiateSingletons(); 4、getBean(beanName)->doGetBean()->createBean()->doCreateBean()->createBeanInstance()初始化对象(默认情况下使用Java反射机制初始化对象,也可以通过CGLIB) 5、initializeBean() 6、invokeAwareMethods()判断是否有Aware接口依赖信息 7、applyBeanPostProcessorsBeforeInitialization()执行前置处理 8、invokeInitMethods()执行init()方法 8、applyBeanPostProcessorsAfterInitialization()执行后置处理

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一:单例与多例对象是如何初始化
  • 二:Bean对象的初始化与销毁过程01
  • 三:Bean对象的初始化与销毁过程02
    • 实现InitializingBean,DisposableBean两个接口
      • 使用Java封装的注解方式@PostConstruct, @PreDestroy
      • 四:现在我们开始分析SpringBean的生命周期
        • 就是后置处理器:BeanPostProcessor
          • BeanPostProcessor的作用
          • ApplicationAware接口原理
          • SpringBean的生命周期总结
          相关产品与服务
          容器服务
          腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档