美文网首页
3. Bean 的实例化控制 (生命周期回调)

3. Bean 的实例化控制 (生命周期回调)

作者: lj72808up | 来源:发表于2021-04-03 20:06 被阅读0次

6. bean 的实例化控制 (生命周期回调)

  1. bean 的初始化后回调

    • 如果想让 bean 在构建完毕后执行一些自定义的操作, 可以让 bean class 实现接口 InitializingBeanafterPropertiesSet() 方法.
    • 不建议使用实现 InitializingBean 接口的方法执行回调, 建议在回调函数上使用 @PostConstruct 注解, 或在 xml 中配置 init-method 属性
    <bean id="exampleInitBean" class="examples.ExampleBean" init-method="init"/>
    
  2. bean 的销毁前回调

    • 如果想让 bean 在销毁前执行一些自定义的操作, 可以让 bean class 实现接口 DisposableBeandestroy 方法
    • 不建议使用实现 DisposableBean ,接口的方法执行回调, 建议在回调函数上使用 @PreDestroy 注解, 或在 xml 中配置 destroy-method 属性
    <bean id="exampleInitBean" class="examples.ExampleBean" destroy-method="cleanup"/>
    
  3. 配置全局默认的创建销毁回调函数
    可以再 xml 的 beans 标签中增加 default-init-methoddefault-destroy-method 标签, 指定全局回调函数. 这样可以不必在每个 bean 上配置 init-methoddestroy-method

    <beans default-init-method="init">
    
        <bean id="blogService" class="com.something.DefaultBlogService">
            <property name="blogDao" ref="blogDao" />
        </bean>
    
    </beans>
    
  4. 总结, 自定义 bean 的初始化和销毁回调函数有3种方法

    1. 实现 InitializingBeanDisposableBean 接口
    2. 自定义 init()`` anddestroy()`` 函数
    3. 使用 @PostConstruct` 和@PreDestroy` 注解
  5. 优雅关闭 ApplicationContext
    web 版的 ApplicationContext 已经实现优雅关闭, 非 web 版的 ApplicationContext 可以自定义 hook 实现

    ConfigurableApplicationContext context = new ClassPathXmlApplicationContext("application1.xml");
    context.registerShutdownHook();   // AbstractApplicationContext 中实现
    
  6. 其它声明周期的回调

    • spring 还提供了很多名字带 Aware 后缀的接口, bean class 实现这些接口后, 会在不同生命周期上回调自定义的函数.
    • 需要注意的是, 这种写法已经破坏了 xml , 或 annotation 配置的 IOC 初衷, 因此, 继承接口定义 bean 的做法只适用于少数基础架构方面的类
  1. BeanPostProcessor
    spring 除了提供了单个 bean 级别的生命周期接口, 还提供了整个容器级别的生命周期接口 BeanPostProcessor, 用来对容器内所有 bean 的初始化做回调
    1. BeanPostProcessor 的方法
      BeanPostProcessor 只有2个方法

      • 初始化前回调: postProcessBeforeInitialization(Object bean, String beanName)
      • 初始化后回调: postProcessAfterInitialization(Object bean, String beanName)
    2. BeanPostProcessorInitializingBean, 各种 aware 接口的调用顺序
      这些顺序要看 beanfactory 类里面是怎么调用的, 以 AbstractAutowireCapableBeanFactory 为例

      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 {
                  //若果Bean实现了BeanNameAware、BeanClassLoaderAware、BeanFactoryAware则初始化Bean的属性值
                  invokeAwareMethods(beanName, bean);
              }
      
              Object wrappedBean = bean;
              if (mbd == null || !mbd.isSynthetic()) {
                  //applyBeanPostProcessorsBeforeInitialization 方法内部主要是
                  //用来调用后置处理器BeanPostProcessor的postProcessBeforeInitialization方法
                  wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
              }
      
              try {
                  //Bean如果继承了InitializingBean类则会调用afterPropertiesSet方法,如果设置了init-method方法,
                  //则调用init-method方法,afterPropertiesSet方法在init-method方法之前调用
                  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()) {
              //applyBeanPostProcessorsAfterInitialization 方法内部主要是,
              //用来调用后置处理器BeanPostProcessor的postProcessAfterInitialization方法
                  wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
              }
      
              return wrappedBean;
          }
      

      因此顺序是:
      aware 接口 -> BeanPostProcessor.postProcessBeforeInitialization() -> InitializingBean.afterPropertiesSet -> BeanPostProcessor.postProcessAfterInitialization()

    3. BeanPostProcessor 与 AOP 的关系
      aop 因为要返回 bean 的代理对象, 而 BeanPostProcessor 的 postProcessAfterInitialization 方法恰恰是在实例化后调用, 所以可以再这个方法内, 返回一个 bean 的代理对象, 从而实现 AOP

    4. AutowiredAnnotationBeanPostProcessor 的实现
      AutowiredAnnotationBeanPostProcessor 是 spring 内部的一个 BeanPostProcessor, 用来自动装配 bean 上的注解字段, setter 方法调用, 和任何其他的装配方法

相关文章

  • 3. Bean 的实例化控制 (生命周期回调)

    6. bean 的实例化控制 (生命周期回调) bean 的初始化后回调如果想让 bean 在构建完毕后执行一些自...

  • 2. Bean 的 scope

    6. bean 的实例化控制 (生命周期回调) bean 的初始化后回调如果想让 bean 在构建完毕后执行一些自...

  • 8、Spring-XML-生命周期

    一、概要 Spring容器负责管理Bean的生命周期 创建bean实例 设置bean的属性值 调用初始化回调方法 ...

  • Spring-XML的生命周期

    一、概要 Spring容器负责管理Bean的生命周期 创建bean实例 设置bean的属性值 调用初始化回调方法 ...

  • bean生命周期以及作用域

    bean生命周期: 简单点说就是:bean的实例化–>bean的初始化–>bean的使用–>bean的销毁 实例化...

  • Spring bean生命周期

    1、Bean实例生命周期 Bean实例生命周期的执行过程如下: 1、Spring对bean进行实例化(调用构造函数...

  • Bean生命周期

    Bean生命周期 IOC 生命周期大致顺序 1.Bean实例化 在实例化之前会调用BeanFactoryPostP...

  • 1.6 自定义 Bean

    1.6.1 生命周期回调 如果要使用生命周期回调 Bean 需要实现 InitializingBean 和 Dis...

  • 02-Spring中Bean的生命周期

    Bean的生命周期 一个简单的Bean的生命周期: 推断构造方法(确定使用哪个构造方法来实例化对象) 实例化 填充...

  • 2020-08-23 spring生命周期

    1.Spring bean的生命周期概括起来就是4个阶段:(1)实例化(Spring 容器实例化bean)(2)属...

网友评论

      本文标题:3. Bean 的实例化控制 (生命周期回调)

      本文链接:https://www.haomeiwen.com/subject/ddihkltx.html