目录
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()方法@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("接口:初始化");//接口实现初始化回调方法}// 基于注解实现初始化回调方法@PostConstructpublic 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();}@Testpublic 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()方法@Overridepublic void destroy() throws Exception {System.out.println("接口:销毁");//接口实现销毁回调方法}// 基于注解实现销毁回调方法@PreDestroypublic void destroy2() throws Exception {System.out.println("注解@PreDestroy:销毁");//注解@PreDestroy实现销毁回调方法}// 基于destroyMethod属性实现销毁回调方法@PostConstructpublic 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();}@Testpublic 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博客https://blog.csdn.net/m0_65277261/article/details/138277932?spm=1001.2014.3001.5501【Spring】IOC/DI中常用的注解@Order与@DependsOn-CSDN博客https://blog.csdn.net/m0_65277261/article/details/138167160?spm=1001.2014.3001.5501【Spring】依赖注入(DI)时常用的注解@Autowired和@Value_配置类 使用@autowired 类型注入-CSDN博客https://blog.csdn.net/m0_65277261/article/details/137784706?spm=1001.2014.3001.5501