Spring注解版的学习
Spring注解版的学习(2)-bean的生命周期
一直看视频学习,2倍速看,然后看完打算打一下代码,啥也不记得…还是记录一下学习的内容吧,希望能帮到大家,我的博客比较浅显,但不一定易懂,主要是为了大家能够指点指点我,其次再是帮到大家(狗头保命)
这一节看到一篇博客,把我想写的都写出来了,也是看视频学习的,应该是看得同一个视频了,写的比我好,但是还是写一下 加深印象。
Bean的生命周期是什么
Bean的生命周期是指
Bean创建-------->Bean初始化-------->Bean销毁这个过程
一路学习下来,学习一个新的知识点很多时候都会学他的生命周期,了解生命周期、运行流程才能更好的理解知识以及定制化自己符合业务的组件、代码吧,虽然我啥也不会…cv大法好
这里需要注意的是,bean的生命周期中的初始化是在bean构造、赋值后
字面上个人感觉有点奇怪,初始化不应该在之前吗...所以觉得这里需要注意
初始化方法是指构造后调用的方法
销毁方法是指销毁前调用的方法
指定初始化方法和销毁方法
xml文件的配置方式中,我们可以在<bean>标签中添加init-method
以及destory-method这两个属性,指定初始化和销毁的方法。
注解版指定初始化方法和销毁方法
1.@Bean的initMethod以及destoryMethod这两个属性
2.实现InitializingBean(定义初始化逻辑)与DisposableBean(定义销毁逻辑)
3.使用JSR250(在Bean对象的类文件中标注)中的
@PostConstruct和@PreDestory
@PostConstruct:标注在初始化方法上
@PreDestory标注在销毁方法上
4.BeanPostProcessor-bean的后置处理器(接口)
自定义一个类去实现这个接口 为ioc容器的所有bean设置初始化和销毁方法
当然你可以根据需求排除
1.@Bean的initMethod以及destoryMethod这两个属性
@Bean(initMethod = "init",destroyMethod = "destroy")
public Teacher myTeacher(){
return new Teacher();
}
配置类注入bean的时候根据这两个属性设置这个类里面的哪个成员方法是
初始化方法哪个是销毁方法
-----------------------下面是Teacher类-------------------
public class Teacher {
public Teacher() {
System.out.println("构造方法");
}
public void init() {
System.out.println("init");
}
public void destroy() {
System.out.println("destroy");
}
}
这里是测试结果,可以得出构造方法–>init初始化–>destroy销毁方法的顺序
并且这是单例的结果,bean是多例的话,容器不会帮你销毁,所以不会调用
destroy销毁方法
构造方法
init
/*
这里中间还有spring容器本身的那些组件我删掉了看着比较方便
*/
myConfigBeanLife
myTeacher
destroy
2.实现InitializingBean(定义初始化逻辑)与DisposableBean(定义销毁逻辑)
让Bean实现InitializingBean和DisposableBean接口,重写他们的方法来实现初始化和销毁方法
--------------------------------创建school类-----------------------------------------------
public class School implements InitializingBean, DisposableBean {
public School() {
System.out.println("构造方法");
}
@Override
public void destroy() throws Exception {
System.out.println("destroy");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("afterPropertiesSet");
}
}
这是测试结果说明afterPropertiesSet方法是初始化方法destroy是销毁方法
跟上面的基本没区别
构造方法
afterPropertiesSet
/*
这里中间还有spring容器本身的那些组件我删掉了看着比较方便
*/
myConfigBeanLife
mySchool
destroy
3.使用JSR250(在Bean对象的类文件中标注@PostConstruct和@PreDestory
@PostConstruct:标注在初始化方法上
@PreDestory标注在销毁方法上
----------------------------这是Person类-------------------------------------------
public class Person {
private String name;
private int age;
public Person() {
System.out.println("构造方法+person");
}
@PostConstruct
public void init(){
System.out.println("init+person");
}
@PreDestroy
public void destroy(){
System.out.println("destroy+person");
}
}
-----------------------------这里是测试结果---------------------------------------------
这里就不删那些自带的bean了,中间多出来的跟这些测试没啥关系,只是容器自动注入的一些bean,我测试方法是打印容器里面所有bean
构造方法+person
init+person
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
myConfigBeanLife
myPerson
destroy+person
跟前面基本是一毛一样
4.BeanPostProcessor-bean的后置处理器(接口)
自定义组件实现这个接口,然后重写方法,但是这个重写的方法并不是前面那些
初始化和销毁方法,他们的使用顺序 后面有讲
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object o, String s) throws BeansException {
System.out.println(s+"postProcessBeforeInitialization 后置处理器"+o);
return o;
}
@Override
public Object postProcessAfterInitialization(Object o, String s) throws BeansException {
System.out.println(s+"postProcessAfterInitialization 后置处理器"+o);
return o;
}
}
------------------------------------------测试结果----------------------------------------------
这里三个bean都注入看看
org.springframework.context.event.internalEventListenerProcessor 后置处理器初始化前前前前前前前前前前操作的那个方法org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerProcessor后置处理器初始化后后后后后后后后操作的那个方法
/*容器本身创建时会注入的bean也会在初始化前后运行这些个方法*/
/*下面是前面写的那三个有初始化方法的bean 虽然初始化方法和销毁方法实现方式
是不一样的 但是结果都是一样的*/
构造方法+person
myPerson 后置处理器初始化前前前前前前前前前前操作的那个方法myPerson
init+person
myPerson后置处理器初始化后后后后后后后后操作的那个方法myPerson
构造方法
myTeacher 后置处理器初始化前前前前前前前前前前操作的那个方法myTeacher
init
myTeacher后置处理器初始化后后后后后后后后操作的那个方法myTeacher
构造方法
mySchool 后置处理器初始化前前前前前前前前前前操作的那个方法mySchool
afterPropertiesSet
mySchool后置处理器初始化后后后后后后后后操作的那个方法mySchool
myConfigBeanLife
myBeanPostProcessor
personController
personServiceImpl
myPerson
myTeacher
mySchool
destroy
destroy
destroy+person
结论是!!
首先要记住有这几个概念是不一样的:
1.bean的构造 是指bean的属性之类的赋值等等操作
2.初始化…就是在构造好的bean上面做文章,根据你的需求去修改
3.销毁…没啥好说的最重要的是上面两点的区分
所以执行顺序是:
1.构造–>
2.后置处理器postProcessBeforeInitialization---->
3.bean的初始化!!跟构造区分开来---->
4.后置处理器的postProcessAfterInitialization—>
5.销毁:单实例—在容器关闭的时候销毁(多实例时候容器部管理bean的销毁)
总结2:前面三种方式是说初始化和销毁方法的定制、然后后置处理器是区分与他们三种的,在初始化方法前后的
BeanPostProcessor源码解析…其实就是说一下他的方法栈执行顺序
try {
this.populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
exposedObject = this.initializeBean(beanName, exposedObject, mbd);
}
1.this.populateBean(beanName, mbd, instanceWrapper);就是构造bean的方法
2.exposedObject = this.initializeBean(beanName, exposedObject, mbd);
这里就是初始化bean的方法
所以流程分为两步
1.构造bean 然后2.初始化bean 但是初始化里面有更详细的操作
if (mbd == null || !mbd.isSynthetic()) {
/**********这里是后置处理器的初始化前调用的方法*********/
wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
}
try {
/*****************这里是调用初始化方法******************/
this.invokeInitMethods(beanName, wrappedBean, mbd);
} catch (Throwable var6) {
throw new BeanCreationException(mbd != null ? mbd.getResourceDescription() : null, beanName, "Invocation of init method failed", var6);
}
if (mbd == null || !mbd.isSynthetic()) {
/****************这里是后置处理器的初始化后调用的方法******************/
wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
所以可以看出来执行流程
1.构造
2.初始化{
后置处理器前部分
初始化
后置处理器后部分
}
最后还是一如既往的…有什么不对的球球指正一下 提点一下 别让我这个小白一直白下去 球球了