1. Bean生命周期
黄色:容器级生命周期接口方法
红色:Bean级生命周期接口方法
蓝色:Bean自身的方法
具体过程如下:
1.通过调用getBean()向容器请求某个Bean时,如果容器注册了InstantiationAwareBeanPostProcessor接口,将调用postProcessBeforeInstantiation().此时可以获得Bean的类型即Bean的Class信息,可以通过beanName过滤某些Bean
default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
return null;
}
2.根据配置信息采用构造方法或者工厂方法实例化Bean
3.如果容器注册了InstantiationAwareBeanPostProcessor接口,将调用postProcessAfterInstantiation().此时Bean被实例化,但是没有被初始化,属性填充没有发生,第一次获得操作Bean的权限
default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
return true;
}
4. 如果Bean配置了属性并且容器注册了InstantiationAwareBeanPostProcessor接口,在容器将配置值设置到属性中之前,将调用postProcessPropertyValue(),此时Bean已经被实例,但是没有被初始化,Field此时为默认值即属性未被填充, 获得了第二次操作Bean的机会,此时不要企图修改在xml中配置的属性值,如果修改会发生覆盖,可以修改未在配置文件中配置的属性
default PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
return pvs;
}
5.调用属性设置方法,将配置值设置到属性中
6.如果Bean实现了BeanNameAware接口,则调用setBeanName()将配置文件中对应的名称设置到Bean中
7.如果Bean实现了BeanFactoryAware接口,则调用setBeanFactory()将BeanFactory设置到Bean中,此处可以采用该BeanFactory操作容器中其他的Bean或者向容器中注册bean
8.如果BeanFactory装配了BeanPostProcessor则调用postProcessBeforeInitialization()对Bean进行处理
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
其中bean为当前请求的bean,beanName为当前bean的配置名称,返回对象是当前处理后请求的bean。第三次获得bean的操作权,此时可以修改bean的默认行为。
9.如果bean实现了InitializingBean接口,则调用afterPropertiesSet()
10.如果bean配置init-method方法则执行该方法,此时也可以修改bean的行为
11.如果BeanFactory装配了BeanPostProcessor则调用postProcessAfterInitialization()对Bean进行处理,第五次获得bena的操纵权
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
12.如果bean配置scope=prototype则将bean直接返回给调用者,调用者自己管理bean的生命周期,如果scope=singleton,spring将bean放入IOC容器的缓存池中,并将bean的引用返回给调用者,spring继续对Bean进行后续的生命周期管理
13.如果bean实现了DisposableBean接口且scope=singleton,当容器关闭时将调用destory(),可以在此处编写释放资源,记录日志等操作
14.scope=singleton且配置destory-method,那么spring将执行destory-method指定的方法,完成相关的操作,此处完成bean资源的释放等
BeanPostProcessor在Spring中占据重要的位置,为容器提供了对Bean进行后续加工处理的切入点,Spring容器提供的AOP,动态代理等,都是通过BeanPostProcessor实现的
2 生命周期分类
2.1 Bean自身方法
构造函数,调用setter设置属性信息,init-method&destory-method所指定的方法
2.2 Bean级生命周期接口方法
Bean实现了spring提供的有关Bean生命周期的接口eg:BeanNameAwaer,BeanFactoryAwaer,InitializingBean,DisposableBean
2.3 容器级生命周期接口方法
Bean实现了spring提供的有关Bean生命周期的接口eg:InstantiationAwareBeanPostProcessor,BeanPostProcessors,一般称它们为后处理器,后处理器接口一般不由bean本身实现,它们对立于bean,实现了类似容器附加装置的形式注册到容器中,并通过接口反射为spring容器扫描识别。Spring容器在创建任何Bean的时候,后处理器都会起作用,后处理器是全局性的,可以通过beanname判断过滤出感兴趣的Bean进行处理
2.4 工厂后处理器接口方法
包括AspectJWeavingEnabler,CustomAutowireConfigurer,ConfigurationClassPostProcess等。工厂后处理器也是容器级的,在应用上下文装载配置文件后立即调用
3 验证生命周期
3.1 定义bean生命周期以及Bean自身的方法
package bean.lifecycle.entries;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
public class User implements BeanNameAware, BeanFactoryAware, InitializingBean, DisposableBean {
private BeanFactory beanFactory;
private String beanName;
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("BeanFactoryAware:setBeanFactory --> 注入beanFactory属性");
}
@Override
public void setBeanName(String beanName) {
System.out.println("BeanNameAware:setBeanName --> 注入address属性");
}
@Override
public void destroy() throws Exception {
System.out.println("DisposableBean:destroy");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("InitializingBean:afterPropertiesSet");
}
private String name;
private String address;
public User() {
System.out.println("调用构造函数或者工厂方法创建Bean实例");
}
public String getName() {
return name;
}
public void setName(String name) {
System.out.println("注入Name属性");
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
System.out.println("注入address属性");
this.address = address;
}
@Override
public String toString() {
return "User Name: " + this.name + ", User Address: " + this.address;
}
//自定义init方法,如果bean配置init-method就执,第四次获得Bean的操作权,行否则不执行
public void inti() {
System.out.println("调用自定义的init方法,在次数也可以修改bean的行为");
}
//自定义destory方法,如果bean配置了destroy-method就执行否则不执行
public void destory() {
System.out.println("调用容器销毁Bean的方法后,调用自定义的destory方法,在次数也可以修改bean的行为");
}
}
3.2 定义容器级Bean生命周期方法
package bean.lifecycle.entries;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
public class UserBeanPostProcessor implements BeanPostProcessor {
// 和Bean的初始化相关
// 第三次获得Bean的操作权,此处可以修改bean的行为
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("UserBeanPostProcessor:postProcessBeforeInitialization -- > 在Bean被初始化之前调用");
return bean;
}
// 和Bean的初始化相关
// 第五次获得Bean的操作权,此处可以修改bean的行为
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("UserBeanPostProcessor:postProcessBeforeInitialization -- > 在Bean被初始化之后调用");
return bean;
}
}
package bean.lifecycle.entries;
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
import java.beans.PropertyDescriptor;
//扩展InstantiationAwareBeanPostProcessor适配器InstantiationAwareBeanPostProcessorAdapter提供实现
public class UserInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter {
// 和bean的实例化相关,在bean实例化之前执行
// 可以根据beanName进行过滤操作
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
System.out.println("InstantiationAwareBeanPostProcessor:postProcessBeforeInstantiation --> 在Beanb被例化之前执行");
return super.postProcessBeforeInstantiation(beanClass, beanName);
}
// 和bean的实例化相关,在bean实例化之后执行,此时Bean已经被实例化
// 但是没有被初始化,Field此时为默认值即属性未被填充
// 获得了第一次操作Bean的机会
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
System.out.println("InstantiationAwareBeanPostProcessor:postProcessAfterInstantiation --> 在Bean被实例化之后执行");
return super.postProcessAfterInstantiation(bean, beanName);
}
// 和Bean设置属性,在bean设置属性前执行,此时Bean已经被实例化
// 但是没有被初始化,Field此时为默认值即属性未被填充
// 获得了第二次操作Bean的机会,此时不要企图修改在xml中配置的属性值,如果修改会发生覆盖
// 可以修改未在配置文件中配置的属性
@Override
public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
System.out.println("InstantiationAwareBeanPostProcessor:postProcessPropertyValues --> 在Bean设置属性前执行");
return super.postProcessPropertyValues(pvs, pds, bean, beanName);
}
}
3.3 bean配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="user" class="bean.lifecycle.entries.User" init-method="inti"
destroy-method="destory">
<property name="address" value="aajiajiaji"></property>
</bean>
</beans>
3.4 向容器中注册后处理器
package bean.lifecycle;
import bean.lifecycle.entries.User;
import bean.lifecycle.entries.UserBeanPostProcessor;
import bean.lifecycle.entries.UserInstantiationAwareBeanPostProcessor;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
public class Main {
public static void main(String[] args) {
Resource resource = new ClassPathResource("/bean/lifecycle/config/bean.xml");
BeanFactory bf = new DefaultListableBeanFactory();
XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader((DefaultListableBeanFactory)bf);
xmlBeanDefinitionReader.loadBeanDefinitions(resource);
//向容器中注册BeanPostProcessor后处理器
((ConfigurableBeanFactory) bf).addBeanPostProcessor(new UserBeanPostProcessor());
//向容器中注册InstantiationAwareBeanPostProcessor后处理器
((ConfigurableBeanFactory) bf).addBeanPostProcessor(new UserInstantiationAwareBeanPostProcessor());
//触发生命周期
User user = (User) bf.getBean("user");
System.out.println(user.toString());
((DefaultListableBeanFactory) bf).destroySingletons();
}
}
3.5 输出结果
InstantiationAwareBeanPostProcessor:postProcessBeforeInstantiation --> 在Beanb被例化之前执行
调用构造函数或者工厂方法创建Bean实例
InstantiationAwareBeanPostProcessor:postProcessAfterInstantiation --> 在Bean被实例化之后执行
InstantiationAwareBeanPostProcessor:postProcessPropertyValues --> 在Bean设置属性前执行
注入address属性
BeanNameAware:setBeanName --> 注入address属性
BeanFactoryAware:setBeanFactory --> 注入beanFactory属性
UserBeanPostProcessor:postProcessBeforeInitialization -- > 在Bean被初始化之前调用
InitializingBean:afterPropertiesSet
调用自定义的init方法,在次数也可以修改bean的行为
UserBeanPostProcessor:postProcessBeforeInitialization -- > 在Bean被初始化之后调用
User Name: null, User Address: aajiajiaji
DisposableBean:destroy
调用容器销毁Bean的方法后,调用自定义的destory方法,在此处也可以修改bean的行为
4 bean生命周期总结
实现了Spring的Bean生命周期接口对Bean进行了额外的控制,使Bean具有更细致的生命周期阶段,这使Bean和Spring框架紧紧的绑定在一起。可以采用配置的方式解耦即通过init-method&destory-method指定bean的初始化和销毁方法。采用这种方式和实现InitialzingBean和DisposableBean接口的效果是一样的。此外Spring还提供Bean后置处理器InitDestoryAnnotationBeanPostProcessor,它负责对标注了@PostConstruct,@PreDestory的Bean进行处理,在Bean初始化后以及销毁前执行相应的逻辑。
对于BeanFactoryAware让Bean感知BeanFactory,BeanNameAware获得配置文件中对应的配置名称。一般情况下用户不用关心这两个接口。如果Bean希望获取容器中其他Bean,可以通过配置的方式(属性注入,构造注入)引用这些Bean。如果Bean希望在运行期间获得配置文件中的Bean名称可以将将名称作为属性注入。
后处理器(eg:BeanPostProcessor)它不要求业务Bean继承,可以向插件一样注册到Spring容器中,提供额外的功能,Spring充分利用了后处理器/后置处理器对Bean进行了加工处理。
5 ApplicationContext中Bean的生命周期
Bean在ApplicationContext中生命周期和BeanFactory中的生命周期类似,但是也有区别,主要有如下几点:
1.如果Bean实现了ApplicationContextAware接口则会调用setApplicationContext()接口方法,该接口方法属于Bean级生命周期的方法,让Bean感知应用上下文,获得操作上下文的权利
public interface ApplicationContextAware extends Aware {
/**
* Set the ApplicationContext that this object runs in.
* Normally this call will be used to initialize the object.
* <p>Invoked after population of normal bean properties but before an init callback such
* as {@link org.springframework.beans.factory.InitializingBean#afterPropertiesSet()}
* or a custom init-method. Invoked after {@link ResourceLoaderAware#setResourceLoader},
* {@link ApplicationEventPublisherAware#setApplicationEventPublisher} and
* {@link MessageSourceAware}, if applicable.
* @param applicationContext the ApplicationContext object to be used by this object
* @throws ApplicationContextException in case of context initialization errors
* @throws BeansException if thrown by application context methods
* @see org.springframework.beans.factory.BeanInitializationException
*/
void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}
2.如果在配置文件中声明了工厂后处理器接口BeanFactoryPostProcessor的实现类,
在应用上下文装配配置文件之后,初始化Bean实例之前
将调用这些
BeanFactoryPostProcessor对配置文件进行处理。
此处可以采用该BeanFactory操作容器中其他的Bean或者向容器中注册新的Bean
。此时可以通过BeanFactory获得BeanDefinitoin对象,采用BeanDefinitoin可以为某个Bean添加额外的信息(eg:配置新属性)如果在配置文件中配置了多个工厂后处理器,建议这些工厂后处理器实现?Ordered接口,确保Spring以确定的顺序调用这些工厂后处理器。
工厂后处理器是容器级别的Bean生命周期接口。仅在应用上下文初始化时调用一次,目的是完成一些配置文件的处理工作。
ApplicationContext中的bean会利用java反射机制自动识别配置文件中定义的后处理器(eg:BeanPostProcessor,InstantiationAwareBeanPostProcessor)和工厂后处理器(eg:BeanFactoryPostProcessor)并自动将其注册到应用上下文中。
BeanFactory中的Bean需要编码的方式注册这些后处理器(eg:addBeanPostProcessor())
6 BeanFactoryPostProcessor
允许修改ApplicationContext中定义的Bean的属性。 BeanFactoryPostProcessor可能与bean定义交互并修改,但永远不会实例化bean。 这样做可能会导致bean过早实例化,违反容器并导致意想不到的副作用。
/**
* Allows for custom modification of an application context's bean definitions,
* adapting the bean property values of the context's underlying bean factory.
*
* <p>Application contexts can auto-detect BeanFactoryPostProcessor beans in
* their bean definitions and apply them before any other beans get created.
*
* <p>Useful for custom config files targeted at system administrators that
* override bean properties configured in the application context.
*
* <p>See PropertyResourceConfigurer and its concrete implementations
* for out-of-the-box solutions that address such configuration needs.
*
* <p>A BeanFactoryPostProcessor may interact with and modify bean
* definitions, but never bean instances. Doing so may cause premature bean
* instantiation, violating the container and causing unintended side-effects.
* If bean instance interaction is required, consider implementing
* {@link BeanPostProcessor} instead.
*
* @author Juergen Hoeller
* @since 06.07.2003
* @see BeanPostProcessor
* @see PropertyResourceConfigurer
*/
@FunctionalInterface
public interface BeanFactoryPostProcessor {
/**
* Modify the application context's internal bean factory after its standard
* initialization. All bean definitions will have been loaded, but no beans
* will have been instantiated yet. This allows for overriding or adding
* properties even to eager-initializing beans.
* @param beanFactory the bean factory used by the application context
* @throws org.springframework.beans.BeansException in case of errors
*/
//标准初始化后,修改应用程序上下文的内部bean工厂。 所有的bean定义都将被加载,但没有bean会被实例化。 这允许重写或添加属性
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
7 示例
7.1 实现工厂后处理接口
public class UserBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
//获得配置文件中存在的Bean的定义
BeanDefinition bd = beanFactory.getBeanDefinition(“配置文件存在的Bean”);
bd.getPropertyValues().addPropertyValue(“属性名称”,”属性值”);
}
}
ApplicationContext在启动时,首先将配置文件中每个<bean>节点生成一个BeanDefinition对象,该对象是Bean中容器中的内部表示,当配置文件中所有的<bean>节点都被解析称BeanDefinition时,容器调用工厂后处理器方法,此时我们可以调整bean的配置信息
7.2 配置工厂后处理器
工厂后处理器和后处理器的配置和普通bean的配置一样