Spring5 - Bean的初始化和销毁的4种方式

简介: Spring5 - Bean的初始化和销毁的4种方式

20201011230207293.png



概述


针对单实例bean的话,容器启动的时候,bean的对象就创建了,而且容器销毁的时候,也会调用Bean的销毁方法

针对原型bean的话,容器启动的时候,bean是不会被创建的而是在获取bean的时候被创建,而且bean的销毁不受 IOC容器的管理.


方式一: 自行指定bean的初始化方法和bean的销毁方法

20201011230427989.png

【beans】

package com.artisan.base.lifeCycle;
public class A1 {
  public void init(){
    System.out.println("A1 init");
  }
  public void destory(){
    System.out.println("A1 destory");
  }
}
package com.artisan.base.lifeCycle;
public class A2 {
  public void init(){
    System.out.println("A2 init");
  }
  public void destory(){
    System.out.println("A2 destory");
  }
}

【配置类】

package com.artisan.base.lifeCycle;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
@Configuration
public class LCConfig {
  @Bean(initMethod = "init",destroyMethod = "destory")
  public A1 a1(){
    return  new A1();
  }
  @Scope("prototype")
  @Bean
  public A2 a2(){
    return  new A2();
  }
}


【测试】

package com.artisan.base.lifeCycle;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import java.util.concurrent.TimeUnit;
/**
 * @author 小工匠
 * @version 1.0
 * @description: TODO
 * @date 2020/10/11 22:58
 * @mark: show me the code , change the world
 */
public class LCTest {
  public static void main(String[] args) throws InterruptedException {
    AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(LCConfig.class);
    TimeUnit.SECONDS.sleep(3);
    // 容器销毁
    ac.close();
  }
}


20201011230531699.png

方式二: 通过 InitializingBean和DisposableBean 接口实现bean的初始化以及销毁方法

package com.artisan.base.lifeCycle;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
/**
 * @author 小工匠
 * @version 1.0
 * @description: TODO
 * @date 2020/10/11 23:06
 * @mark: show me the code , change the world
 */
public class A3 implements InitializingBean, DisposableBean {
  public A3() {
    System.out.println("A3 init");
  }
  @Override
  public void destroy() throws Exception {
    System.out.println("A3 destroy");
  }
  @Override
  public void afterPropertiesSet() throws Exception {
    System.out.println("A3 afterPropertiesSet");
  }
}

20201011230820889.png


执行上面的测试代码

20201011231031608.png

方式三: 通过JSR250规范 提供的注解@PostConstruct 和@ProDestory标注的方法

package com.artisan.base.lifeCycle;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
/**
 * @author 小工匠
 * @version 1.0
 * @description: TODO
 * @date 2020/10/11 23:12
 * @mark: show me the code , change the world
 */
public class A4 {
  public A4() {
    System.out.println("A4 Construct ");
  }
  @PostConstruct
  public void init(){
    System.out.println("A4 init");
  }
  @PreDestroy
  public void destory(){
    System.out.println("A4 destory");
  }
}

2020101123145081.png

测试结果

20201011231507937.png


方式四:通过Spring的BeanPostProcessor的 bean的后置处理器会拦截所有bean创建过程

public class A5 {
  public A5() {
    System.out.println("A5 Construct");
  }
  public void init(){
    System.out.println("A5 init");
  }
  public void destory(){
    System.out.println("A5 destory");
  }
}


【bean後置處理器】

package com.artisan.base.lifeCycle;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
public class A5BeanPostProcessor implements BeanPostProcessor {
  @Override
  public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    if (bean instanceof  A5){
      System.out.println("A5BeanPostProcessor...postProcessBeforeInitialization:"+beanName);
    }
    return bean;
  }
  @Override
  public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    if (bean instanceof  A5){
      System.out.println("A5BeanPostProcessor...postProcessAfterInitialization:"+beanName);
    }
    return bean;
  }
}


【config】


20201011233147978.png


【test】


20201011233230343.png

简单说一下 BeanPostProcessor的执行时机


20201011233619830.png


看看invokeInitMethods


20201011233820971.png


相关文章
|
1月前
|
XML 安全 Java
|
17天前
|
存储 Java Spring
【Spring】获取Bean对象需要哪些注解
@Conntroller,@Service,@Repository,@Component,@Configuration,关于Bean对象的五个常用注解
|
17天前
|
存储 Java 应用服务中间件
【Spring】IoC和DI,控制反转,Bean对象的获取方式
IoC,DI,控制反转容器,Bean的基本常识,类注解@Controller,获取Bean对象的常用三种方式
|
22天前
|
XML Java 数据格式
Spring容器Bean之XML配置方式
通过对以上内容的掌握,开发人员可以灵活地使用Spring的XML配置方式来管理应用程序的Bean,提高代码的模块化和可维护性。
57 6
|
24天前
|
XML Java 数据格式
🌱 深入Spring的心脏:Bean配置的艺术与实践 🌟
本文深入探讨了Spring框架中Bean配置的奥秘,从基本概念到XML配置文件的使用,再到静态工厂方式实例化Bean的详细步骤,通过实际代码示例帮助读者更好地理解和应用Spring的Bean配置。希望对你的Spring开发之旅有所助益。
91 3
|
2月前
|
缓存 Java Spring
实战指南:四种调整 Spring Bean 初始化顺序的方案
本文探讨了如何调整 Spring Boot 中 Bean 的初始化顺序,以满足业务需求。文章通过四种方案进行了详细分析: 1. **方案一 (@Order)**:通过 `@Order` 注解设置 Bean 的初始化顺序,但发现 `@PostConstruct` 会影响顺序。 2. **方案二 (SmartInitializingSingleton)**:在所有单例 Bean 初始化后执行额外的初始化工作,但无法精确控制特定 Bean 的顺序。 3. **方案三 (@DependsOn)**:通过 `@DependsOn` 注解指定 Bean 之间的依赖关系,成功实现顺序控制,但耦合性较高。
实战指南:四种调整 Spring Bean 初始化顺序的方案
|
1月前
|
安全 Java 开发者
Spring容器中的bean是线程安全的吗?
Spring容器中的bean默认为单例模式,多线程环境下若操作共享成员变量,易引发线程安全问题。Spring未对单例bean做线程安全处理,需开发者自行解决。通常,Spring bean(如Controller、Service、Dao)无状态变化,故多为线程安全。若涉及线程安全问题,可通过编码或设置bean作用域为prototype解决。
36 1
|
3月前
|
XML Java 数据格式
Spring从入门到入土(bean的一些子标签及注解的使用)
本文详细介绍了Spring框架中Bean的创建和使用,包括使用XML配置文件中的标签和注解来创建和管理Bean,以及如何通过构造器、Setter方法和属性注入来配置Bean。
89 9
Spring从入门到入土(bean的一些子标签及注解的使用)
|
3月前
|
Java 测试技术 Windows
咦!Spring容器里为什么没有我需要的Bean?
【10月更文挑战第11天】项目经理给小菜分配了一个紧急需求,小菜迅速搭建了一个SpringBoot项目并完成了开发。然而,启动测试时发现接口404,原因是控制器包不在默认扫描路径下。通过配置`@ComponentScan`的`basePackages`字段,解决了问题。总结:`@SpringBootApplication`默认只扫描当前包下的组件,需要扫描其他包时需配置`@ComponentScan`。
|
3月前
|
Java 开发者 Spring
Spring bean的生命周期详解!
本文详细解析Spring Bean的生命周期及其核心概念,并深入源码分析。Spring Bean是Spring框架的核心,由容器管理其生命周期。从实例化到销毁,共经历十个阶段,包括属性赋值、接口回调、初始化及销毁等。通过剖析`BeanFactory`、`ApplicationContext`等关键接口与类,帮助你深入了解Spring Bean的管理机制。希望本文能助你更好地掌握Spring Bean生命周期。
168 1