你未必出类拔萃,但一定与众不同
SpringBean的生命周期
文章目录
Spring IoC的本质就是为了管理Bean
生命周期
-
Bean 容器找到配置⽂件中 Spring Bean 的定义。
-
Bean 容器利⽤反射创建⼀个Bean的实例。
-
如果涉及到⼀些属性值 利⽤ set() ⽅法设置⼀些属性值。
-
如果Bean 实现了接口BeanNameAware的setBeanName方法,那么就会调用这个方法。
-
如果Bean实现了接口BeanFactoryAware的setBeanFactory方法,那么就会调用这个方法。
-
如果Bean实现了接口AppicationContextAware的setAppicationContext方法,且这个Spring IoC容器必须是一个AppicationContext接口的实现类,那么就会调用这个方法,否则不调用
-
如果Bean 实现了接口BeanPostProcessor的postProcessBeforeInitialization方法那么就会调用这个方法。
-
如果Bean实现了接口BeanFactoryPostProcessor的afterPropertiesSet方法,那么就会调用这个方法
-
如果Bean自定义了初始化方法,它就会调用已定义的初始化方法
-
如果Bean实现了接口BeanPostProcessor的postProcessAfterInitialization方法,完成了这些调用,这个时候Bean就完成了初始化,那么Bean就生存在了Spring IoC的容器中。
当服务器正常关闭或者其他关闭Spring IoC容器的事件,就会完成对Bean的销毁
-
如果Bean实现了接口DisPosableBean的destory方法,那么就会调用它。
-
如果定义了自定义的销毁方法,那么就会调用它。
现在我们来看看一个简易的bean的实现 了解一个大概实例化初始化流程
先写一个实体类
去实现BeanFactoryAware, BeanNameAware, InitializingBean, DisposableBean这些接口
public class Student implements BeanFactoryAware, BeanNameAware,
InitializingBean, DisposableBean {
private String studentName;
private String studentAddress;
private String studentPhone;
private BeanFactory beanFactory;
private String beanName;
public String getStudentName() {
return studentName;
}
public void setStudentName(String studentName) {
System.out.println("---注入属性 studentName-----");
this.studentName = studentName;
}
public String getStudentAddress() {
return studentAddress;
}
public void setStudentAddress(String studentAddress) {
System.out.println("---注入属性 StudentAddress-----");
this.studentAddress = studentAddress;
}
public String getStudentPhone() {
return studentPhone;
}
public void setStudentPhone(String studentPhone) {
System.out.println("---注入属性 studentPhone-----");
this.studentPhone = studentPhone;
}
// 这是BeanFactoryAware接口方法
@Override
public void setBeanFactory(BeanFactory arg0) throws BeansException {
System.out.println("----BeanFactoryAware接口----调用BeanFactoryAware.setBeanFactory()");
this.beanFactory = arg0;
}
// 这是BeanNameAware接口方法
@Override
public void setBeanName(String arg0) {
System.out.println("----BeanNameAware接口----调用BeanNameAware.setBeanName()");
this.beanName = arg0;
}
// 这是InitializingBean接口方法
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("----InitializingBean接口----调用InitializingBean.afterPropertiesSet()");
}
// 这是DiposibleBean接口方法
@Override
public void destroy() throws Exception {
System.out.println("----DiposibleBean接口----调用DiposibleBean.destory()");
}
// 通过<bean>的init-method属性指定的初始化方法
public void myInit() {
System.out.println("---init-method---调用<bean>的init-method属性指定的初始化方法");
}
// 通过<bean>的destroy-method属性指定的初始化方法
public void myDestroy() {
System.out.println("---destroy-method---调用<bean>的destroy-method属性指定的初始化方法");
}
}
编写spring配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="beanPostProcessor" class="com.wyyy.run.test.MyBeanPostProcessor">
</bean>
<bean id="instantiationAwareBeanPostProcessor" class="com.wyyy.run.test.MyInstantiationAwareBeanPostProcessor">
</bean>
<bean id="beanFactoryPostProcessor" class="com.wyyy.run.test.MyBeanFactoryPostProcessor">
</bean>
<bean id="student" class="com.wyyy.run.test.Student" init-method="myInit"
destroy-method="myDestroy" scope="singleton" p:studentName="张三" p:studentAddress="广州"
p:studentPhone= "15900000000" />
</beans>
如果Bean 实现了接口BeanNameAware的setBeanName方法,那么就会调用这个方法。
如果Bean实现了接口BeanFactoryAware的setBeanFactory方法,那么就会调用这个方法。
这里我们的bean就实现了这个两个接口,因此会调用这个方法,还在实例化之前
BeanPostProcessor 前置处理器
BeanPostProcessor是Spring IOC容器给我们提供的一个扩展接口
public interface BeanPostProcessor {
//bean初始化方法调用前被调用
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
//bean初始化方法调用后被调用
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
我们现在自定义一个MyBeanPostProcessor去实现这个接口 监测这个接口方法的初始化顺序
public class MyBeanPostProcessor implements BeanPostProcessor {
public MyBeanPostProcessor() {
super();
System.out.println("BeanPostProcessor构造器");
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
System.out.println("postProcessAfterInitialization");
return bean;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
System.out.println("postProcessBeforeInitialization");
return bean;
}
}
BeanFactoryPostProcessor
BeanFactoryPostProcessor是在spring容器加载了bean的定义文件之后,在bean实例化之前执行的
实现该接口,可以在spring的bean创建之前,修改bean的定义属性。也就是说,Spring允许BeanFactoryPostProcessor在容器实例化任何其它bean之前读取配置元数据,并可以进行修改,例如可以把bean的scope从singleton改为prototype,也可以把property的值给修改掉。可以同时配置多个BeanFactoryPostProcessor,并通过设置’order’属性来控制各个BeanFactoryPostProcessor的执行次序。
@FunctionalInterface
public interface BeanFactoryPostProcessor {
void postProcessBeanFactory(ConfigurableListableBeanFactory var1) throws BeansException;
}
ConfigurableListableBeanFactory作为参数可以获取到bean的一些定义信息
我们自定义一个MyBeanFactoryPostProcessor
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
public MyBeanFactoryPostProcessor() {
super();
System.out.println("BeanFactoryPostProcessor构造器");
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory var1)
throws BeansException {
System.out.println("postProcessBeanFactory");
BeanDefinition bd = var1.getBeanDefinition("student");
bd.getPropertyValues().addPropertyValue("studentPhone", "110");
}
}
BeanDefinition
Spring容器启动的过程中,会将Bean解析成Spring内部的BeanDefinition结构
一个 BeanDefinition 描述了一个 Bean 实例,实例包含属性值、构造方法参数值以及更多实现信息。
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
//单例和原型
String SCOPE_SINGLETON = "singleton";
String SCOPE_PROTOTYPE = "prototype";
//标识 Bean 的类别,分别对应 用户定义的 Bean、来源于配置文件的 Bean、Spring 内部的 Bean
int ROLE_APPLICATION = 0;
int ROLE_SUPPORT = 1;
int ROLE_INFRASTRUCTURE = 2;
//Bean 的父类名称
void setParentName(@Nullable String var1);
......
}
BeanDefinition 描述了一个 Bean 的定义,实际上就是对象在容器中的抽象。通过这个 BeanDefinition 定义的数据结构,容器能够方便地对 Bean 进行管理。对于单例的 Bean,在第一次 getBean 的时候读取 BeanDefinition 获取定义,然后再创建和初始化 Bean,并缓存起来。对于原型的 Bean,在每一次 getBean 的时候都需要使用 BeanDefinition 的数据进行创建和初始化,不会缓存 Bean。
BeanDefinition 在 Spring 内部使用,外部开发者一般感知不到 BeanDefinition 的存在。我们使用时只需要关注通过 xml、注解怎样定义了一个 Bean,然后使用即可。而这中间的解析、创建、初始化都通过 BeanDefinition 来承载。
InstantiationAwareBeanPostProcessor
InstantiationAwareBeanPostProcessor代表了Spring的另外一段生命周期:实例化。先区别一下Spring Bean的实例化和初始化两个阶段的主要作用:
1、实例化的过程是一个创建Bean的过程,即调用Bean的构造函数,单例的Bean放入单例池中
2、初始化的过程是一个赋值的过程,即调用Bean的setter,设置Bean的属性
Instantiation表示实例化:实例化的意思在对象还未生成
Initialization表示初始化:初始化的意思在对象已经生成
自定义一个MyInstantiationAwareBeanPostProcessor类继承InstantiationAwareBeanPostProcessor重写两个方法
public class MyInstantiationAwareBeanPostProcessor extends
InstantiationAwareBeanPostProcessorAdapter {
public MyInstantiationAwareBeanPostProcessor() {
super();
System.out.println("这是InstantiationAwareBeanPostProcessorAdapter实现类构造器!!");
}
/**
* 接口方法、实例化Bean之前调用
* @param beanClass
* @param beanName
* @return
* @throws BeansException
*/
@Override
public Object postProcessBeforeInstantiation(Class beanClass,
String beanName) throws BeansException {
System.out.println("InstantiationAwareBeanPostProcessor调用postProcessBeforeInstantiation方法");
return null;
}
/**
* 接口方法、实例化Bean之后调用
* @param bean
* @param beanName
* @return
* @throws BeansException
*/
@Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
System.out.println("InstantiationAwareBeanPostProcessor调用postProcessAfterInitialization方法");
return bean;
}
}
写个主函数进行测试
public static void main(String[] args) {
System.out.println("初始化容器");
ApplicationContext factory = new ClassPathXmlApplicationContext("spring-config.xml");
System.out.println("容器初始化成功");
Student student = factory.getBean("student",Student.class);
System.out.println(student);
}
打印结果
初始化容器
BeanFactoryPostProcessor构造器
postProcessBeanFactory
BeanPostProcessor构造器
这是InstantiationAwareBeanPostProcessorAdapter实现类构造器!!
InstantiationAwareBeanPostProcessor调用postProcessBeforeInstantiation方法
---注入属性 StudentAddress-----
---注入属性 studentName-----
---注入属性 studentPhone-----
----BeanNameAware接口----调用BeanNameAware.setBeanName()
----BeanFactoryAware接口----调用BeanFactoryAware.setBeanFactory()
postProcessBeforeInitialization
----InitializingBean接口----调用InitializingBean.afterPropertiesSet()
---init-method---调用<bean>的init-method属性指定的初始化方法
postProcessAfterInitialization
InstantiationAwareBeanPostProcessor调用postProcessAfterInitialization方法
容器初始化成功
com.wyyy.run.test.Student@489115ef