Spring学习笔记 Bean的生命周期

更多看这里吧😁


简述

Bean的生命周期分为

创建	 contruct
初始化 	 initialize
运行     runtime
销毁     destroy

Spring主要针对初始化销毁两个时期做文章

加载Bean(单例)的代码基本流程是:

  1. 读取配置文件(XML或者@Configuration标注的类)
  2. 解析配置文件中的类,并且对每个要加载的bean执行:
    2.1 通过反射调用构造方法创建类
    2.2 对bean进行赋值
    2.3 对bean调用多个XXXPostProcessor进行后置处理

具体流程可以看:


通过@Bean注解

可以通过@Bean注解设置Bean的加载和销毁方法

  1. 编写Soil类作为Bean并同时设置加载的init方法以及销毁的destroy方法
public class Soil {

    public void init() {
        System.out.println("soil inited");
    }

    public void destroy() {
        System.out.println("soil destroy");
    }
}
  1. 编写配置类MainConfig6
    在@Bean注解中指定initMethod 和destroyMethod
@Configuration
public class MainConfig6 {

    @Bean(initMethod = "init", destroyMethod = "destroy")
    public Soil soil() {
        return new Soil();
    }
}
  1. 编写MainTest6测试并输出
public class MainTest6 {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig6.class);
        context.removeBeanDefinition("soil");
    }
}

输出:

soil inited
soil destroy

更多看这里吧😁

注意事项

  1. 注意@Bean注解的destroyMethod 方法中有个注释(init方法也有):
    表明了哪些方法可以作为destroyMethod 方法,以及别的注意事项

/**
* The optional name of a method to call on the bean instance upon closing the
* application context, for example a {@code close()} method on a JDBC
* {@code DataSource} implementation, or a Hibernate {@code SessionFactory} object.
* The method must have no arguments but may throw any exception.
*

As a convenience to the user, the container will attempt to infer a destroy
* method against an object returned from the {@code @Bean} method. For example, given
* an {@code @Bean} method returning an Apache Commons DBCP {@code BasicDataSource},
* the container will notice the {@code close()} method available on that object and
* automatically register it as the {@code destroyMethod}. This ‘destroy method
* inference’ is currently limited to detecting only public, no-arg methods named
* ‘close’ or ‘shutdown’. The method may be declared at any level of the inheritance
* hierarchy and will be detected regardless of the return type of the {@code @Bean}
* method (i.e., detection occurs reflectively against the bean instance itself at
* creation time).
*

To disable destroy method inference for a particular {@code @Bean}, specify an
* empty string as the value, e.g. {@code @Bean(destroyMethod=“”)}. Note that the
* {@link org.springframework.beans.factory.DisposableBean} and the
* {@link java.io.Closeable}/{@link java.lang.AutoCloseable} interfaces will
* nevertheless get detected and the corresponding destroy/close method invoked.
*

Note: Only invoked on beans whose lifecycle is under the full control of the
* factory, which is always the case for singletons but not guaranteed for any
* other scope.
* @see org.springframework.context.ConfigurableApplicationContext#close()

  1. 注意如果bean的scope设置多例(prototype),将不会调用Init和destroy方法
@Configuration
public class MainConfig6 {

    @Bean(initMethod = "init", destroyMethod = "destroy")
    @Scope(value = "prototype")
    public Soil soil() {
        return new Soil();
    }
}

输出:

小结

所以Bean的生命周期:

Spring的IOC容器只会接管单例bean,而不会接管多例Bean的生命周期。


通过InitializingBean, DisposableBean接口

  1. 编写Docker类并实现InitializingBean, DisposableBean两个接口

public class Docker implements InitializingBean, DisposableBean {

    public void afterPropertiesSet() throws Exception {
        System.out.println("docker inited");
    }

    public void destroy() throws Exception {
        System.out.println("docker destroy");
    }
}
  1. 配置类MainConfig6中将Docker类的实例加入IOC容器
@Configuration
public class MainConfig6 {

    @Bean
    public Docker docker() {
        return new Docker();
    }
}
  1. 运行MainTest6并测试
public class MainTest6 {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig6.class);
        context.removeBeanDefinition("docker");
    }
}

Docker类的创建和销毁的钩子函数成功被调用

docker inited
docker destroy

通过@PostConstruct和@PreDestroy注解

这两个不是Spring的注解哦

  1. 编写Dog类
public class Dog {

    @PostConstruct
    public void init() {
        System.out.println("Dog inited");
    }

    @PreDestroy
    public void destroy() {
        System.out.println("Dog destroy");
    }
}

  1. 设置配置类

@Configuration
public class MainConfig6 {

    @Bean
    public Dog dog() {
        return new Dog();
    }
}
  1. 运行测试类查看输出
public class MainTest6 {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig6.class);
        context.removeBeanDefinition("dog");
    }
}
Dog inited
Dog destroy

通过BeanPostProcessor接口

这个接口在bean初始化前(postProcessBeforeInitialization)和初始化后(postProcessAfterInitialization)调用的,并且对所有bean生效。
Spring中大量使用了BeanPostProcessor,比如AOP通过它对初始化完的bean进行增强实现了代理

  1. 编写类BeanPostProcessor的子类MyBeanPostProcessor
public class MyBeanPostProcessor implements BeanPostProcessor {

    public Object postProcessBeforeInitialization(Object bean, String s) throws BeansException {
        System.out.println("postProcessBeforeInitialization ->" + bean);
        return bean;
    }

    public Object postProcessAfterInitialization(Object bean, String s) throws BeansException {
        System.out.println("postProcessAfterInitialization ->" + bean);
        return bean;
    }
}
  1. 编写配置类MainConfig6
@Configuration
public class MainConfig6 {

    @Bean
    public MyBeanPostProcessor myBeanPostProcessor() {
        return new MyBeanPostProcessor();
    }

    @Bean
    public Dog dog() {
        return new Dog();
    }

    @Bean
    public Docker docker() {
        return new Docker();
    }

    @Bean(initMethod = "init", destroyMethod = "destroy")
    public Soil soil() {
        return new Soil();
    }
}

3.运行测试类MainTest6并查看输出结果

postProcessBeforeInitialization ->org.springframework.context.event.EventListenerMethodProcessor@782663d3
postProcessAfterInitialization ->org.springframework.context.event.EventListenerMethodProcessor@782663d3
postProcessBeforeInitialization ->org.springframework.context.event.DefaultEventListenerFactory@64485a47
postProcessAfterInitialization ->org.springframework.context.event.DefaultEventListenerFactory@64485a47
postProcessBeforeInitialization ->my.spring.test6.Dog@4524411f
Dog inited
postProcessAfterInitialization ->my.spring.test6.Dog@4524411f
postProcessBeforeInitialization ->my.spring.test6.Docker@1786f9d5
docker inited
postProcessAfterInitialization ->my.spring.test6.Docker@1786f9d5
postProcessBeforeInitialization ->my.spring.test6.Soil@704d6e83
soil inited
postProcessAfterInitialization ->my.spring.test6.Soil@704d6e83

观察到dog类的输出(5 - 7 行)

postProcessBeforeInitialization ->my.spring.test6.Dog@4524411f
Dog inited
postProcessAfterInitialization ->my.spring.test6.Dog@4524411f

Dog类

public class Dog {
	
	// 初始化
    @PostConstruct
    public void init() {
        System.out.println("Dog inited");
    }

    @PreDestroy
    public void destroy() {
        System.out.println("Dog destroy");
    }
}

可知:BeanPostProcessor的处理时机是在bean的初始化前后;
初始化前调用postProcessBeforeInitialization方法;初始化之后调用
postProcessAfterInitialization方法。

更多看这里吧😁

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值