005-Spring Bean的生命周期与扩展处理器

Bean的生命周期回调

Spring容器中定义了如下两个接口类提供容器在初始化或销毁bean的时候调用

  • InitializingBean:bean初始化的时候调用其对应方法
  • DisposableBean:bean销毁的时候调用其对应方法

InitializingBean接口定义如下

package org.springframework.beans.factory;

public interface InitializingBean {
    void afterPropertiesSet() throws Exception;
}

在容器为 bean 设置所有必要的属性后,调用该方法。

DisposableBean接口定义如下

package org.springframework.beans.factory;

public interface DisposableBean {
    void destroy() throws Exception;
}

此接口可以让 bean 在包含它的容器被销毁时获得回调。

接下来我们来定义一个bean实现这两个接口

package com.yyoo.boot.bean;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;

public class CycleBean implements InitializingBean, DisposableBean{

    private String value;

    public CycleBean(){
        System.out.println("CycleBean无参构造");
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
        System.out.println("设置value方法");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("CycleBean初始化方法");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("CycleBean销毁方法");
    }
}

CycleBean有无参构造,有setter方法,实现了初始化和销毁接口。

定义spring-cycle.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    
    <beans>

        <bean id="cycle" class="com.yyoo.boot.bean.CycleBean">
            <property name="value" value="生命周期测试"></property>
        </bean>

    </beans>
    
</beans>

测试代码

package com.yyoo.boot.ioc;

import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Demo3 {

    @Test
    public void test(){
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-cycle.xml");
        // 注意ApplicationContext接口没有定义close方法
        context.close();
    }

}

执行结果

com.intellij.rt.junit.JUnitStarter -ideVersion5 -junit4 com.yyoo.boot.ioc.Demo3,test
14:56:52.231 [main] DEBUG org.springframework.context.support.ClassPathXmlApplicationContext - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@2812cbfa
14:56:52.450 [main] DEBUG org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loaded 1 bean definitions from class path resource [spring-cycle.xml]
14:56:52.507 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'cycle'
CycleBean无参构造
设置value方法
CycleBean初始化方法
14:56:52.603 [main] DEBUG org.springframework.context.support.ClassPathXmlApplicationContext - Closing org.springframework.context.support.ClassPathXmlApplicationContext@2812cbfa, started on Mon Jun 28 14:56:52 CST 2021
CycleBean销毁方法

Process finished with exit code 0

一如我们的预期,容器在实例化bean,并且注入依赖后执行初始化方法,在容器close时执行销毁方法。

注意:以上方式我们的bean实现了spring的两个接口,造成了我们的bean跟Spring的强依赖。是不建议这样使用的。

xml配置方式

定义CycleBean1如下

package com.yyoo.boot.bean;

public class CycleBean1{

    private String value;

    public CycleBean1(){
        System.out.println("CycleBean1无参构造");
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
        System.out.println("CycleBean1设置value方法");
    }

    public void init() throws Exception {
        System.out.println("CycleBean1初始化方法");
    }

    public void destroy() throws Exception {
        System.out.println("CycleBean1销毁方法");
    }
}

注意:我们没有实现上面的两个接口,只定义了init和destroy两个方法

配置xml

        <bean id="cycle1" class="com.yyoo.boot.bean.CycleBean1" init-method="init" destroy-method="destroy">
            <property name="value" value="xml配置"></property>
        </bean>

执行demo

16:36:11.184 [main] DEBUG org.springframework.context.support.ClassPathXmlApplicationContext - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@2812cbfa
16:36:11.475 [main] DEBUG org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loaded 1 bean definitions from class path resource [spring-cycle.xml]
16:36:11.557 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'cycle1'
CycleBean1无参构造
CycleBean1设置value方法
CycleBean1初始化方法
16:36:11.664 [main] DEBUG org.springframework.context.support.ClassPathXmlApplicationContext - Closing org.springframework.context.support.ClassPathXmlApplicationContext@2812cbfa, started on Mon Jun 28 16:36:11 CST 2021
CycleBean1销毁方法

通过java编程的方式@Bean注解上也有对应的属性实现,这里我们就不多说了

注解方式

创建CycleBean2

package com.yyoo.boot.bean;

import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
@Component
public class CycleBean2 {

    private String value;

    public CycleBean2(){
        System.out.println("CycleBean2无参构造");
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
        System.out.println("CycleBean2设置value方法");
    }

    @PostConstruct
    public void init() throws Exception {
        System.out.println("CycleBean2初始化方法");
    }

    @PreDestroy
    public void destroy() throws Exception {
        System.out.println("CycleBean2销毁方法");
    }
}

spring-annotation.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/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">

    <context:annotation-config />
    <context:component-scan base-package="com.yyoo.boot.**"/>

</beans>

执行Demo4

package com.yyoo.boot.ioc;

import com.yyoo.boot.bean.CycleBean2;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Demo4 {

    @Test
    public void test(){
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-annotation.xml");
        CycleBean2 bean = context.getBean(CycleBean2.class);
        System.out.println(bean);
        // 注意ApplicationContext接口没有定义close方法
        context.close();
    }

}

执行结果

17:24:59.598 [main] DEBUG org.springframework.context.support.ClassPathXmlApplicationContext - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@59a6e353
17:25:00.228 [main] DEBUG org.springframework.context.annotation.ClassPathBeanDefinitionScanner - Identified candidate component class: file [C:\work\project\mytest\springboot\target\classes\com\yyoo\boot\Appliction.class]
17:25:00.233 [main] DEBUG org.springframework.context.annotation.ClassPathBeanDefinitionScanner - Identified candidate component class: file [C:\work\project\mytest\springboot\target\classes\com\yyoo\boot\bean\CycleBean2.class]
17:25:00.261 [main] DEBUG org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loaded 7 bean definitions from class path resource [spring-annotation.xml]
17:25:00.306 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor'
17:25:01.481 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'propertySourcesPlaceholderConfigurer'
17:25:01.496 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerProcessor'
17:25:01.498 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'forceAutoProxyCreatorToUseClassProxying'
17:25:01.499 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.boot.sql.init.dependency.DatabaseInitializationDependencyConfigurer$DependsOnDatabaseInitializationPostProcessor'
17:25:01.500 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerFactory'
17:25:01.536 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor'
17:25:01.540 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalCommonAnnotationProcessor'
17:25:01.552 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor'
17:25:01.553 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.boot.context.internalConfigurationPropertiesBinder'
17:25:01.553 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.boot.context.internalConfigurationPropertiesBinderFactory'
17:25:01.558 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.aop.config.internalAutoProxyCreator'
17:25:01.670 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'appliction'
17:25:01.679 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'cycleBean2'
CycleBean2无参构造
CycleBean2初始化方法
17:25:01.691 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.AutoConfigurationPackages'
17:25:01.692 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration'
17:25:01.697 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration'
17:25:01.702 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'taskExecutorBuilder'
17:25:01.714 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'spring.task.execution-org.springframework.boot.autoconfigure.task.TaskExecutionProperties'
17:25:01.720 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.boot.context.properties.BoundConfigurationProperties'
17:25:01.768 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Autowiring by type from bean name 'taskExecutorBuilder' via factory method to bean named 'spring.task.execution-org.springframework.boot.autoconfigure.task.TaskExecutionProperties'
17:25:01.779 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.boot.context.properties.EnableConfigurationPropertiesRegistrar.methodValidationExcludeFilter'
17:25:01.782 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.aop.AopAutoConfiguration$ClassProxyingConfiguration'
17:25:01.787 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.aop.AopAutoConfiguration'
17:25:01.788 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.availability.ApplicationAvailabilityAutoConfiguration'
17:25:01.790 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'applicationAvailability'
17:25:01.798 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$Jackson2ObjectMapperBuilderCustomizerConfiguration'
17:25:01.799 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'standardJacksonObjectMapperBuilderCustomizer'
17:25:01.803 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'spring.jackson-org.springframework.boot.autoconfigure.jackson.JacksonProperties'
17:25:01.819 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Autowiring by type from bean name 'standardJacksonObjectMapperBuilderCustomizer' via factory method to bean named 'org.springframework.context.support.ClassPathXmlApplicationContext@59a6e353'
17:25:01.819 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Autowiring by type from bean name 'standardJacksonObjectMapperBuilderCustomizer' via factory method to bean named 'spring.jackson-org.springframework.boot.autoconfigure.jackson.JacksonProperties'
17:25:01.820 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$JacksonObjectMapperBuilderConfiguration'
17:25:01.821 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$ParameterNamesModuleConfiguration'
17:25:01.822 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'parameterNamesModule'
17:25:01.859 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$JacksonObjectMapperConfiguration'
17:25:01.859 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'jacksonObjectMapper'
17:25:01.878 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Autowiring by type from bean name 'jacksonObjectMapperBuilder' via factory method to bean named 'org.springframework.context.support.ClassPathXmlApplicationContext@59a6e353'
17:25:01.878 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Autowiring by type from bean name 'jacksonObjectMapperBuilder' via factory method to bean named 'standardJacksonObjectMapperBuilderCustomizer'
17:25:01.890 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'jsonComponentModule'
17:25:01.890 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration'
17:25:01.915 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Autowiring by type from bean name 'jacksonObjectMapper' via factory method to bean named 'jacksonObjectMapperBuilder'
17:25:02.416 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration'
17:25:02.417 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration'
17:25:02.417 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'lifecycleProcessor'
17:25:02.418 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'spring.lifecycle-org.springframework.boot.autoconfigure.context.LifecycleProperties'
17:25:02.419 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Autowiring by type from bean name 'lifecycleProcessor' via factory method to bean named 'spring.lifecycle-org.springframework.boot.autoconfigure.context.LifecycleProperties'
17:25:02.421 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration$StringHttpMessageConverterConfiguration'
17:25:02.421 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'stringHttpMessageConverter'
17:25:02.422 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Autowiring by type from bean name 'stringHttpMessageConverter' via factory method to bean named 'environment'
17:25:02.457 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.http.JacksonHttpMessageConvertersConfiguration$MappingJackson2HttpMessageConverterConfiguration'
17:25:02.458 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'mappingJackson2HttpMessageConverter'
17:25:02.459 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Autowiring by type from bean name 'mappingJackson2HttpMessageConverter' via factory method to bean named 'jacksonObjectMapper'
17:25:02.462 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.http.JacksonHttpMessageConvertersConfiguration'
17:25:02.462 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration'
17:25:02.463 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'messageConverters'
17:25:02.537 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration'
17:25:02.545 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'spring.info-org.springframework.boot.autoconfigure.info.ProjectInfoProperties'
17:25:02.549 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Autowiring by type from bean name 'org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration' via constructor to bean named 'spring.info-org.springframework.boot.autoconfigure.info.ProjectInfoProperties'
17:25:02.551 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.sql.init.SqlInitializationAutoConfiguration'
17:25:02.551 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'spring.sql.init-org.springframework.boot.autoconfigure.sql.init.SqlInitializationProperties'
17:25:02.555 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration'
17:25:02.557 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'scheduledBeanLazyInitializationExcludeFilter'
17:25:02.558 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'taskSchedulerBuilder'
17:25:02.560 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'spring.task.scheduling-org.springframework.boot.autoconfigure.task.TaskSchedulingProperties'
17:25:02.564 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Autowiring by type from bean name 'taskSchedulerBuilder' via factory method to bean named 'spring.task.scheduling-org.springframework.boot.autoconfigure.task.TaskSchedulingProperties'
17:25:02.565 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration'
com.yyoo.boot.bean.CycleBean2@f667fe
17:25:02.593 [main] DEBUG org.springframework.context.support.ClassPathXmlApplicationContext - Closing org.springframework.context.support.ClassPathXmlApplicationContext@59a6e353, started on Mon Jun 28 17:24:59 CST 2021
CycleBean2销毁方法

3种方法中,最无侵入式的是xml配置的方式,但我们目前使用最多的是注解的方式。具体的情况自己选择把。

默认init和destroy方法

如下配置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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    
    <beans default-init-method="defaultInit" default-destroy-method="defaultDestroy">

        <bean id="cycle1" class="com.yyoo.boot.bean.CycleBean1" init-method="init" destroy-method="destroy">
            <property name="value" value="xml配置"></property>
        </bean>

    </beans>
    
</beans>

<beans/>标签的default-init-method和default-destroy-method属性可分别设置bean对应的默认init方法和destroy方法(当然对应的bean需要有对应的方法存在)。如果bean的init和destroy方法名称跟默认定义的名称不一致,那么可以在<bean>标签中使用init-method和destroy-method属性来单独设置。

同时使用3种方式定义init和destroy

上面我们提到,有如下3种方式可以定义

  • 实现InitializingBean和 DisposableBean回调接口
  • 自定义init()和destroy()方法在xml中配置
  • 为对应的方法添加@PostConstruct和@PreDestroy 注释。

如果一个bean同时使用了这三种方法,那么他的执行顺序如何?

  1. 如果其对应的init和destroy方法名称是一样的,那么对应的方法只会执行一次。
  2. 如果对应的方法名称都不一样,那么它们按如下顺序执行

init方法

  1. 带有@PostConstruct注释的方法
  2. afterPropertiesSet()由InitializingBean回调接口定义
  3. 自定义配置init()方法

destroy方法

  1. @PreDestroy带有注释的方法
  2. destroy()由DisposableBean回调接口定义
  3. 自定义配置destroy()方法

启动和关闭回调(了解)

任何 Spring 管理的对象都可以实现该Lifecycle接口。然后,当 ApplicationContext自身接收到启动和停止信号时(例如,对于运行时的停止/重启场景),它会将这些调用级联到Lifecycle该上下文中定义的所有实现。它通过委托给 LifecycleProcessor 来做到这一点

Lifecycle

public interface Lifecycle {

    void start();

    void stop();

    boolean isRunning();
}

LifecycleProcessor

public interface LifecycleProcessor extends Lifecycle {

    void onRefresh();

    void onClose();
}

LifecycleProcessor本身是Lifecycle 接口的扩展。它还添加了另外两种方法来对正在刷新和关闭的上下文做出反应.DefaultLifecycleProcessor是其的一个默认实现。

Phased

public interface Phased {

    int getPhase();
}

getPhase()方法返回Integer.MIN_VALUE将是最先启动和最后一个停止的对象。Integer.MAX_VALUE表示对象应该最后启动并首先停止(可能是因为它依赖于其他正在运行的进程)。

SmartLifecycle

public interface SmartLifecycle extends Lifecycle, Phased {

    boolean isAutoStartup();

    void stop(Runnable callback);
}

在非 Web 应用程序中优雅地关闭 Spring IoC 容器

仅适用于非 Web 应用程序。Spring 的基于 Web 的 ApplicationContext实现已经有了适当的代码,可以在相关的 Web 应用程序关闭时优雅地关闭 Spring IoC 容器。
非web应用程序优雅关闭需要调用ConfigurableApplicationContext的registerShutdownHook()方法

package com.yyoo.boot.ioc;

import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Demo3 {

    @Test
    public void test(){
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-cycle.xml");
        // 添加一个关闭的钩子(hook)
        context.registerShutdownHook();
        // 应用程序的正常使用比如调用getBean等

        // 打印验证程序尚未执行完成不会回调hook
        System.out.println("应用程序执行中");

        // 当主函数执行结束,hook回调关闭,调用bean相关的destroy方法
    }

}

结果

11:03:09.240 [main] DEBUG org.springframework.context.support.ClassPathXmlApplicationContext - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@2812cbfa
11:03:09.625 [main] DEBUG org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loaded 1 bean definitions from class path resource [spring-cycle.xml]
11:03:09.704 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'cycle1'
CycleBean1无参构造
CycleBean1设置value方法
CycleBean1初始化方法
应用程序执行中
11:03:09.852 [SpringContextShutdownHook] DEBUG org.springframework.context.support.ClassPathXmlApplicationContext - Closing org.springframework.context.support.ClassPathXmlApplicationContext@2812cbfa, started on Wed Jun 30 11:03:09 CST 2021
CycleBean1销毁方法

扩展处理器

BeanPostProcessor

我们可以定义一个或多个 bean,实现 BeanPostProcessor 接口,该接口有两个方法,一个是在 bean 初始化方法之前执行,一个方法在bean初始化方法之后执行。实现 BeanPostProcessor 接口时我们一般也会同步实现 Ordered 接口,Ordered 接口提供了我们定义的 bean 的实例化顺序。

编写自定义BeanPostProcessor

package com.yyoo.boot.processor;

import com.yyoo.boot.bean.CycleBean1;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.Ordered;

public class MyProcessor implements BeanPostProcessor, Ordered {

    /**
     * Ordered接口定义的方法 <br/>
     * 用于定义当前处理器的加载顺序
     * @return
     */
    @Override
    public int getOrder() {
        return 0;
    }

    /**
     * 在bean初始化方法之前执行
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("前处理器,BeanName:"+beanName + ";Bean:"+bean);
        if(bean instanceof CycleBean1){
            ((CycleBean1)bean).setValue("新值");
        }
        return bean;
    }

    /**
     * 在容器初始化方法之后执行
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("后处理器,BeanName:"+beanName + ";Bean:"+bean);
        return bean;
    }
}

编写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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    
    <beans default-init-method="defaultInit" default-destroy-method="defaultDestroy">

        <bean id="cycle1" class="com.yyoo.boot.bean.CycleBean1" init-method="init" destroy-method="destroy">
            <property name="value" value="xml配置"></property>
        </bean>
		
		<!-- 
			自定义的Processor在此声明为bean即可,相对init方法,对相应的bean没有嵌入代码或注释
			但其粒度比较大,所有的bean都会执行
		 -->
        <bean class="com.yyoo.boot.processor.MyProcessor"></bean>
    </beans>
    
</beans>

Demo程序

package com.yyoo.boot.ioc;

import com.yyoo.boot.bean.CycleBean1;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Demo5 {

    @Test
    public void test(){

        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-cycle.xml");
        // 添加一个关闭的钩子(hook)
        context.registerShutdownHook();
        // 应用程序的正常使用比如调用getBean等

        // 打印验证程序尚未执行完成不会回调hook
        System.out.println("应用程序执行中");
        CycleBean1 bean = context.getBean(CycleBean1.class);
        System.out.println("获取的Bean:" + bean);

        // 当主函数执行结束,hook回调关闭,调用bean相关的destroy方法

    }

}

执行结果

14:15:01.751 [main] DEBUG org.springframework.context.support.ClassPathXmlApplicationContext - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@2812cbfa
14:15:02.059 [main] DEBUG org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loaded 2 bean definitions from class path resource [spring-cycle.xml]
14:15:02.134 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'com.yyoo.boot.processor.MyProcessor#0'
14:15:02.179 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'cycle1'
CycleBean1无参构造
CycleBean1设置value方法
前处理器,BeanName:cycle1;Bean:CycleBean1{value='xml配置'}
CycleBean1设置value方法
CycleBean1初始化方法
后处理器,BeanName:cycle1;Bean:CycleBean1{value='新值'}
应用程序执行中
获取的Bean:CycleBean1{value='新值'}
14:15:02.276 [SpringContextShutdownHook] DEBUG org.springframework.context.support.ClassPathXmlApplicationContext - Closing org.springframework.context.support.ClassPathXmlApplicationContext@2812cbfa, started on Thu Jul 01 14:15:01 CST 2021
CycleBean1销毁方法

以上是我们自定义的processor,Spring也自带有,比如AutowiredAnnotationBeanPostProcessor,用于自动装配带注解的字段、setter方法或任意有注解的方法。

其他processor

BeanFactoryPostProcessor等

各种Aware

Aware单词翻译过来就是感知、意识。比如我们在web应用中可能会用到ApplicationContext,但我们的程序中无法获取,那么通过ApplicationContextAware接口进行编码即可获取。

ApplicationContextAware接口的定义

public interface ApplicationContextAware {

    void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}

在自定义bean中获取ApplicationContext实例

package com.yyoo.boot.processor;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

public class MyAware implements ApplicationContextAware {

    private ApplicationContext applicationContext;

    /**
     * 接口定义的set方法
     *  在容器执行的时候,会自动注入applicationContext实例
     *  方法实现中我们将注入的实例赋值给了我们的成员变量
     * @param applicationContext
     * @throws BeansException
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    /**
     * 自定义的get方法
     * @return
     */
    public ApplicationContext getApplicationContext(){
        return this.applicationContext;
    }

}

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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    
    <beans>
        <bean id="myAware" class="com.yyoo.boot.processor.MyAware"></bean>
    </beans>
    
</beans>

Demo主程序

package com.yyoo.boot.ioc;

import com.yyoo.boot.bean.CycleBean1;
import com.yyoo.boot.processor.MyAware;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Demo6 {

    @Test
    public void test(){

        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-aware.xml");
        // 添加一个关闭的钩子(hook)
        context.registerShutdownHook();
        // 应用程序的正常使用比如调用getBean等

        MyAware bean = context.getBean(MyAware.class);
        System.out.println("主程序创建的context:"+context);
        System.out.println("获取的context:" + bean.getApplicationContext());


    }

}

执行结果

15:26:33.816 [main] DEBUG org.springframework.context.support.ClassPathXmlApplicationContext - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@2812cbfa
15:26:34.149 [main] DEBUG org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loaded 1 bean definitions from class path resource [spring-aware.xml]
15:26:34.219 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'myAware'
主程序创建的context:org.springframework.context.support.ClassPathXmlApplicationContext@2812cbfa, started on Thu Jul 01 15:26:33 CST 2021
获取的context:org.springframework.context.support.ClassPathXmlApplicationContext@2812cbfa, started on Thu Jul 01 15:26:33 CST 2021
15:26:34.304 [SpringContextShutdownHook] DEBUG org.springframework.context.support.ClassPathXmlApplicationContext - Closing org.springframework.context.support.ClassPathXmlApplicationContext@2812cbfa, started on Thu Jul 01 15:26:33 CST 2021

可以看到我们通过Aware获取的applicationContext实例和我们主程序创建的是一个实例,在web应用程序中我们不用自己创建ApplicationContext实例,但又需要该实例时,通过Aware获取是最佳办法。

其他Aware

  • ApplicationEventPublisherAware
  • BeanClassLoaderAware
  • BeanFactoryAware
  • BeanNameAware
  • LoadTimeWeaverAware
  • MessageSourceAware
  • NotificationPublisherAware
  • ResourceLoaderAware
  • ServletConfigAware
  • ServletContextAware

以上Aware在实现上与ApplicationContextAware一样,我们的MyAware其实可以实现多个Aware用一个类来实现以上所有的Aware,如果你希望把他们放在一起的话。

xml使用Properties配置

<bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
    <property name="locations" value="classpath:com/something/jdbc.properties"/>
</bean>

<bean id="dataSource" destroy-method="close"
        class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="${jdbc.driverClassName}"/>
    <property name="url" value="${jdbc.url}"/>
    <property name="username" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>
</bean>

上一篇:004-Spring Ioc 依赖详解
下一篇:006-Spring IoC 基于注解配置

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值