【Spring】Bean的生命周期回调函数和Bean的循环依赖

目录

1、Bean的生命周期

2、Bean的生命周期回调函数 

2.1、初始化的生命周期回调

2.2、销毁的生命周期回调

3、Bean的循环依赖

1、Bean的生命周期

        spring的bean的生命周期主要是创建bean的过程,一个bean的生命周期主要是4个步骤:实例化,属性注入,初始化,销毁

再详细一点可以拆分为:

(1)配置bean,通过@Component @Bean等方式都可以。

(2)加载Spring容器

(3)实例化,例如:(BeanService beanService = new BeanService())

(4)解析依赖注入(解析@Autowired @Value等自动注入注解)

(5)初始化(调用初始化回调方法,由程序员来配置)

(6)最终放入一个Map集合,Map<beanName, bean对象>

(7)spring容器.getBean("beanName")---->Map<beanName, bean对象>

(8)spring容器关闭 bean就会销毁(调用销毁回调方法,由程序员来配置)

2、Bean的生命周期回调函数 

2.1、初始化的生命周期回调

初始化(调用初始化回调方法,由程序员来配置),有三种方式来配置初始化回调方法

示例:

//自定义类LtService
public class LtService implements InitializingBean {

    // 基于接口实现初始化回调方法,重写了InitializingBean接口中的afterPropertiesSet()方法
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("接口:初始化");//接口实现初始化回调方法
    }

    // 基于注解实现初始化回调方法
    @PostConstruct
    public void init() throws Exception {
        System.out.println("注解@PostConstruct:初始化");//注解@PostConstruct实现初始化回调方法
    }

    // 基于initMethod属性实现初始化回调方法
    public void init2() throws Exception {
        System.out.println("initMethod属性:初始化");//initMethod属性实现初始化回调方法
    }
}


//测试类LifeCallbackTest
@SpringBootTest(classes = LifeCallbackTest.class)
public class LifeCallbackTest {

    //通过@Bean的方式把LtService配置成bean
    @Bean(initMethod = "init2")
    public LtService ltService(){
        return new LtService();
    }

    @Test
    public void test(@Autowired LtService ltService){
        System.out.println(ltService.getClass());
    }
}

从上面的结果可以看出他们的顺序是:先注解,再接口,最后initMethod属性

小补充:

2.2、销毁的生命周期回调

1.在springboot中当jvm进程结束后会自动调用容器.close0),自动销毁bean

2.在spring中,需要手动调用容器.close()来销毁bean

销毁(调用销毁回调方法,由程序员来配置),有三种方式来配置销毁回调方法

示例:

//自定义类LtService
//public class LtService implements InitializingBean , DisposableBean {
public class LtService implements DisposableBean {

    // 基于接口实现销毁回调方法,重写了DisposableBean接口中的destroy()方法
    @Override
    public void destroy() throws Exception {
        System.out.println("接口:销毁");//接口实现销毁回调方法
    }

    // 基于注解实现销毁回调方法
    @PreDestroy
    public void destroy2() throws Exception {
        System.out.println("注解@PreDestroy:销毁");//注解@PreDestroy实现销毁回调方法
    }

    // 基于destroyMethod属性实现销毁回调方法
    @PostConstruct
    public void destroy3() throws Exception {
        System.out.println("destroyMethod属性:初始化");//destroyMethod属性实现销毁回调方法
    }
}


//测试类
@SpringBootTest(classes = LifeCallbackTest.class)
public class LifeCallbackTest {

    //@Bean(initMethod = "init2", destroyMethod = "destroy3")
    @Bean(destroyMethod = "destroy3")
    public LtService ltService(){
        return new LtService();
    }

    @Test
    public void test(@Autowired LtService ltService){
        System.out.println(ltService.getClass());
    }
}

从上面的结果可以看出他们的顺序是:先注解,再接口,最后destroyMethod属性

3、Bean的循环依赖

        循环依赖其实就是循环引用,也就是两个或则两个以上的bean互相持有对方,最终形成闭环。比如A依赖于B,B依赖于A。如下图:

        注意,这里不是函数的循环调用,是对象的相互依赖关系。循环调用其实就是一个死循环,除非有终结条件。

        Spring已经帮我们解决了循环依赖这个问题,这涉及到Spring底层源码的概念(Spring怎么解决的循环依赖)。但是,在SpringBoot中会报错,因为SpringBoot认为是一种不合理的设计

循环依赖在SpringBoot中会报错的解决方式:

1、在配置文件中放开循环依赖的限制

#放开循环依赖的限制
spring.main.allow-circular-references=true

2、代码设计层面:

a.把依赖的方法,直接写在本类中

b.添加一个中间类, 中间类去依赖A\B,然后让中间类去阻止他们的依赖方法

3、延迟注入

a.添加需要依赖的构造函数参数

b.添加@Lazy注解

@Lazy
public BeanA(BeanB beanb){
    this.beanb = beanb;
}

@Lazy
public Bean(BeanA beana){
    this.beana = beana;
}

推荐: 

【Spring】IOC/DI中常用的注解@Lazy、@Scope与@Conditional-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/m0_65277261/article/details/138277932?spm=1001.2014.3001.5501【Spring】IOC/DI中常用的注解@Order与@DependsOn-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/m0_65277261/article/details/138167160?spm=1001.2014.3001.5501【Spring】依赖注入(DI)时常用的注解@Autowired和@Value_配置类 使用@autowired 类型注入-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/m0_65277261/article/details/137784706?spm=1001.2014.3001.5501

猜你喜欢

转载自blog.csdn.net/m0_65277261/article/details/138503989