前言
Spring作为当前最流行的框架,受到广泛的关注和使用。它具有组件化的结构,在使用时可以根据应用的不同使用不同的模块而不必加载所有的组件。同时,spring具有很强的扩展性,在使用时根据业务扩展自己的执行方法。
加载bean的过程
spring加载的过程定义在AbstractApplicationContext的refresh方法中,我们先来看一下 这个方法的结构
public void refresh() throws BeansException, IllegalStateException {
Object var1 = this.startupShutdownMonitor;
//启动监控标识,并且同步此对象,防止同一时间有多个
//线程加载
synchronized(this.startupShutdownMonitor) {
//初始化一些上下文参数
this.prepareRefresh();
//创建一个BeanFactory,进去后只有两个方法this.refreshBeanFactory();
//return this.getBeanFactory();
//具体的实现在它的父类AbstractRefreshableApplicationContext中
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
//为 此beanFactory初始化一些组件,比如:ClassLoadder等等
this.prepareBeanFactory(beanFactory);
try {
//获取容器级别的后处理器,允许上下文的子类中对
//beanFactory进行后处理,在应用上下文内部beanFactory
//初始化之后可以修改beanFactory,此时所有的BeanDefinittions都
//已经被加载,但未被实例化,具体的实现在AbstractRefreshableWebApplicationContext
this.postProcessBeanFactory(beanFactory);
/**在装配完成配置后执行这些后处理器,这里涉及到一些接口
我们在开发时可以实现这些接口扩展功能,例如:
InstantiationAwareBeanPostProcessor包含两个方法
一个是在实例化前调用,一个在实例化后,初始化前调用
可以用来做特殊作用,例如代理等等
DestructionAwareBeanPostProcessor在销毁前调用
*/
this.invokeBeanFactoryPostProcessors(beanFactory);
/**
把所有的bean的后处理器排序,在bean实例化后调用
*/
this.registerBeanPostProcessors(beanFactory);
//初始化国际化信息资源
this.initMessageSource();
//初始化事件多播组件,Event触发时由Multicaster
//通知ApplicationListener
this.initApplicationEventMulticaster();
//空方法由子类扩展,可以在实例化bean之前
//做一些ApplicationContext相关的操作
this.onRefresh();
//注册事件监听器
this.registerListeners();
//单例模式的bean实例 化,初始化等等完成
this.finishBeanFactoryInitialization(beanFactory);
//applicationContext刷新完成后的处理,
//例如生命周期监听器的回调,广播通知等
this.finishRefresh();
} catch (BeansException var9) {
if(this.logger.isWarnEnabled()) {
this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
}
//如果加载失败,则清理环境相关的信息
this.destroyBeans();
//把applicationContext的active设置成false
this.cancelRefresh(var9);
throw var9;
} finally {
//清理一些缓存
this.resetCommonCaches();
}
}
}
protected final void refreshBeanFactory() throws BeansException {
//如果存在就销毁重建
if(this.hasBeanFactory()) {
this.destroyBeans();
this.closeBeanFactory();
}
try {
//创建一个DefaultListableBeanFactory作为Bean的
//管理工厂类
DefaultListableBeanFactory ex = this.createBeanFactory();
ex.setSerializationId(this.getId());
//加载自定义的beanFactory
this.customizeBeanFactory(ex);
//加载beanDefinition,关系这个类加载的东西比较多
//可以单分析
this.loadBeanDefinitions(ex);
Object var2 = this.beanFactoryMonitor;
synchronized(this.beanFactoryMonitor) {
this.beanFactory = ex;//把beanFactory的引用
//给Context
}
} catch (IOException var5) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + this.getDisplayName(), var5);
}
}
其余的子方法,在此不再列出,感兴趣的可以直接阅读源码。上述方法执行完后,即容器初始化完成,可以执行程序的业务调用了,在完成业务处理后,就可以销毁容器。
bean的生命周期
spring就是一个大的bean容器,管理各种不同的bean及之间的关系,在初始化bean的时候,spring也预留一些接口类,方便spring加载管理bean之前或之后额外处理bean的其它业务。
图片来自:https://www.cnblogs.com/zrtqsk/p/3735273.html
可以看到在bean加载的过程中,使用了很多扩展接口的方法调用,大致可以分为以下几类:
- 容器级后处理器接口,包括:CustomAutowireConfigurer、AspectJWeavingEnabler、ConfigurationClassPostProcessor(BeanFactoryPostProcessor)和InstantiationAwareBeanPostProcessor(BeanPostProcessor),这些都是在应用上下文装配之后调用的,BeanFactoryPostProcessor的主要作用是在容器实例化任何bean之前读取bean的定义(配置元数据)并且可以修改它,可以定义多个,通过order来确定执行顺序。BeanPostProcessor主要是spring完成bean实例化配置以及其他初始化前后可以添加一些自己的处理逻辑,同样也可以定义多个并通过order来确定执行顺序
- bean级的接口,包括:BeanFactoryAware、BeanNameAware、InitializingBean和DiposableBean这些接口方法都是在实例化对象后调用的。FactoryBean实现了这些接口
- bean自身的方法,包括bean自身的方法和<bean>标签中定义的init-method和desctroy-method方法。
生命周期测试
1.新增一个对象,实现bean级的接口
public class Customer implements BeanFactoryAware, BeanNameAware,
InitializingBean, DisposableBean {
private Long customerId;
private String customerName;
private String desc;
private BeanFactory beanFactory;
private String beanName;
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
System.out.println("【BeanFactoryAware】的setBeanFactory方法执行");
}
@Override
public void setBeanName(String s) {
this.beanName =s;
System.out.println("【BeanNameAware】的setBeanName方法执行");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("【InitializingBean】的afterPropertiesSet方法执行");
}
@Override
public void destroy() throws Exception {
System.out.println("【DisposableBean】的destroy方法执行");
}
public void initCustomer() throws Exception {
System.out.println("【Init-method】的initCustomer方法执行");
}
public void destroyCustomer() throws Exception {
System.out.println("【destroy-method】的destroyCustomer方法执行");
}
public Long getCustomerId() {
return customerId;
}
public void setCustomerId(Long customerId) {
this.customerId = customerId;
}
public String getCustomerName() {
return customerName;
}
public void setCustomerName(String customerName) {
this.customerName = customerName;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public String info(){
return this.getCustomerId()+"/"
+this.getCustomerName()+"/"+this.getDesc();
}
}
2.容器接口BootBeanFactoryPostProcessor,可以在这里修改bean的属性值
public class BootBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
public BootBeanFactoryPostProcessor(){
super();
System.out.println("【BootBeanFactoryPostProcessor】的构造函数执行");
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory
configurableListableBeanFactory) throws BeansException {
BeanDefinition bd = configurableListableBeanFactory.getBeanDefinition("customer");
PropertyValue []pvs = bd.getPropertyValues().getPropertyValues();
String aa = "";
for(PropertyValue pv:pvs) {
aa += pv.getName()+"="+pv.getValue();
}
System.out.println("【BootBeanFactoryPostProcessor】修改前的属性"+aa);
bd.getPropertyValues().addPropertyValue(new PropertyValue("desc","这是在BootBeanFactoryPostProcessor设置的属性描述"));
System.out.println("【BootBeanFactoryPostProcessor】的postProcessBeanFactory执行");
}
}
3.初始化对象前后执行
public class BootBeanPostProcessor implements BeanPostProcessor {
public BootBeanPostProcessor(){
super();
System.out.println("【BootBeanPostProcessor】的构造函数执行");
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if(bean instanceof Customer) {
System.out.println(("【BootBeanPostProcessor】postProcessBeforeInitialization"+((Customer)bean).info()));
}
System.out.println("【BootBeanPostProcessor】的postProcessBeforeInitialization初始化对象前执行");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if(bean instanceof Customer) {
System.out.println(("【BootBeanPostProcessor】postProcessAfterInitialization"+((Customer)bean).info()));
}
System.out.println("【BootBeanPostProcessor】的postProcessAfterInitialization执行");
return bean;
}
}
4.实例化前后执行
public class BootInstantiationAwareBeanPostProcessorAdapter extends InstantiationAwareBeanPostProcessorAdapter {
public BootInstantiationAwareBeanPostProcessorAdapter(){
super();
System.out.println("【BootInstantiationAwareBeanPostProcessorAdapter】的构造函数执行");
}
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
System.out.println("【BootInstantiationAwareBeanPostProcessorAdapter】的postProcessProperties设置属性时执行");
if(bean instanceof Customer) {
System.out.println(("【BootInstantiationAwareBeanPostProcessorAdapter】postProcessProperties】"+((Customer)bean).info()));
}
return super.postProcessProperties(pvs, bean, beanName);
}
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
System.out.println("【BootInstantiationAwareBeanPostProcessorAdapter】的postProcessBeforeInitialization实例化前执行,此时的beanClass="+beanClass);
//可以在此处改变此类对象,比如使用代理类
return super.postProcessBeforeInstantiation(beanClass,beanName);
}
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
System.out.println("【BootInstantiationAwareBeanPostProcessorAdapter】的postProcessAfterInitialization实例化后执行,此时的bean="+bean);
return super.postProcessAfterInstantiation(bean,beanName);
}
}
5.配置实例对象的xml文件
<?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"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
<bean id="customer" class="com.xps.sc.springbootdemo.domain.Customer"
init-method="initCustomer"
destroy-method="destroyCustomer" p:customerName="赵老四" p:customerId="10093"
p:desc="这个是初始描述" />
<bean id="bootInstantiationAwareBeanPostProcessorAdapter"
class="com.xps.sc.springbootdemo.domain.BootInstantiationAwareBeanPostProcessorAdapter">
</bean>
<bean id="bootBeanPostProcessor" class="com.xps.sc.springbootdemo.domain.BootBeanPostProcessor">
</bean>
<bean id="bootBeanFactoryPostProcessor" class="com.xps.sc.springbootdemo.domain.BootBeanFactoryPostProcessor">
</bean>
</beans>
6.测试
public class BeanLifeCycleTest {
public static void main(String[] args) {
System.out.println("开始初始化容器");
ApplicationContext factory = new ClassPathXmlApplicationContext("test-beans.xml");
System.out.println("容器初始化成功");
Customer customer = factory.getBean("customer",Customer.class);
System.out.println(customer.info());
System.out.println("开始关闭容器!");
((ClassPathXmlApplicationContext)factory).registerShutdownHook();
}
}
7.测试结果
开始初始化容器
【BootBeanFactoryPostProcessor】的构造函数执行
【BootBeanFactoryPostProcessor】修改前的属性customerId=10093customerName=赵老四desc=这个是初始描述
【BootBeanFactoryPostProcessor】的postProcessBeanFactory执行
【BootInstantiationAwareBeanPostProcessorAdapter】的构造函数执行
【BootBeanPostProcessor】的构造函数执行
【BootInstantiationAwareBeanPostProcessorAdapter】的postProcessBeforeInitialization实例化前执行,此时的beanClass=class com.xps.sc.springbootdemo.domain.Customer
【BootInstantiationAwareBeanPostProcessorAdapter】的postProcessAfterInitialization实例化后执行,此时的bean=com.xps.sc.springbootdemo.domain.Customer@2f8f5f62
【BootInstantiationAwareBeanPostProcessorAdapter】的postProcessProperties设置属性时执行
【BootInstantiationAwareBeanPostProcessorAdapter】postProcessProperties】null/null/null
【BeanNameAware】的setBeanName方法执行
【BeanFactoryAware】的setBeanFactory方法执行
【BootBeanPostProcessor】postProcessBeforeInitialization10093/赵老四/这是在BootBeanFactoryPostProcessor设置的属性描述
【BootBeanPostProcessor】的postProcessBeforeInitialization初始化对象前执行
【InitializingBean】的afterPropertiesSet方法执行
【Init-method】的initCustomer方法执行
【BootBeanPostProcessor】postProcessAfterInitialization10093/赵老四/这是在BootBeanFactoryPostProcessor设置的属性描述
【BootBeanPostProcessor】的postProcessAfterInitialization执行
容器初始化成功
10093/赵老四/这是在BootBeanFactoryPostProcessor设置的属性描述
开始关闭容器!
【DisposableBean】的destroy方法执行
【destroy-method】的destroyCustomer方法执行
Process finished with exit code 0
小结
spring bean加载的过程主要就是执行AbstractApplicationContext类中的refresh方法,首先对初始化进行同步处理 防止同时有多线程处理加载,然后就是对上下文进行初始化,例如:初始化closed和active属性,上下文环境初始化和事件容器set的初始化。然后,就是通过obtainFreshBeanFactory获取一个beanFactory,其实在这一步不仅仅只是实现化bean工厂,它首先重新刷新了beanFactory,如果存在就销毁重建一个DefaultListableBeanFactory,并且使用loadBeanDefinitions(beanFactory)拿到资源文件resource,再通过AbstractBeanDefinitionReader中的loadBeanDefinitions方法加载resource中的内容并解析,最后通过BeanDefinitionReaderUtils这个工具类把解析后的beanDefinition保存到beanFactory中,到这里xml中的bean就加载完成了。接下来就是prepareBeanFactory(beanFactory)方法,主要是对实例化完成的beanFacotry进行相关的设置处理,然后就是postProcessBeanFactory(beanFactory)和invokeBeanFactoryPostProcessors(beanFactory)主要用于处理各种processor,查看是否有指定的后处理器BeanFactoryPostProcessor,如果有则获取bean实例并执行相关的方法。再就是registerBeanPostProcessors(beanFactory)它也是处理processor的,只不过这个方法不是立即执行,而是在实例化bean的时候调用processor中的方法,这里处理的都是BeanPostProcessor,然后就是处理国际化initMessageSource(),initApplicationEventMulticaster()初始化事件广播器类型为SimpleApplicationEventMulticaster并注册到beanFactory中,registerListeners()注册应用的监听器,通过查询BeanFacotry中是否存在ApplicationListener类型的bean,将ApplicationListener.class类型的Bean的名称添加到事件广播器中,在事件触发的时候可回调监听器中的方法,再着就是finishBeanFactoryInitialization(beanFactory)完成BeanFactory的初始化。最后就是使用finishRefresh()清理一些缓存,触发相关的一些事件。
参考:https://blog.csdn.net/u011043551/article/details/79675363
beanFactory和FactoryBean
beanFactory
在查找源码时,会发现有一个BeanFactory,另外还有一个FactoryBean。虽然名字相似,但其实有很大的区别的。
首先,我们来看一下BeanFactory接口中的方法
public interface BeanFactory {
String FACTORY_BEAN_PREFIX = "&";
Object getBean(String var1) throws BeansException;
<T> T getBean(String var1, Class<T> var2) throws BeansException;
Object getBean(String var1, Object... var2) throws BeansException;
<T> T getBean(Class<T> var1) throws BeansException;
<T> T getBean(Class<T> var1, Object... var2) throws BeansException;
<T> ObjectProvider<T> getBeanProvider(Class<T> var1);
<T> ObjectProvider<T> getBeanProvider(ResolvableType var1);
boolean containsBean(String var1);
boolean isSingleton(String var1) throws NoSuchBeanDefinitionException;
boolean isPrototype(String var1) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String var1, ResolvableType var2) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String var1, Class<?> var2) throws NoSuchBeanDefinitionException;
@Nullable
Class<?> getType(String var1) throws NoSuchBeanDefinitionException;
String[] getAliases(String var1);
}
从名字可以看出,它就是一个对象工厂类,没什么特殊的,是IOC容器应遵守接口的最基本定义,也就是IOC最底层的编程规范,它只是一个接口,Spring给出了很多的实现,所有的bean都是交由beanFactroy进行管理的,主要职责包括:实例化对象,缓存并定位对象的位置,配置应用程序中的对象及维护对象之前的依赖关系,例如:DefaultListableBeanFactory、XmlBeanFactory、ApplicationContext(也是由beanFactory派生出来的,除beanFactory所有的功能外,还包括资源加载、国际化处理、载入多上下文等等)
FactoryBean
它是以bean结尾,表明它是一个bean,但不同于普通的bean,它实现了FactoryBean<T>,根据该bean的ID在beanFactory中获取的实际上是FactoryBean.getObject返回的对象,并不是FactoryBean本身。如果想获取它本身可以在ID前面加上“&”。一般情况下,spring是通过反射机制用<bean class="">中class指定的类实例化对应的bean的,但在某些情况下,实例化bean的过程比较复杂,如果按传统配置的方式,则要配置很多的信息,开发起来不方便,此时采用编码的方式或许更简单一些,所以spring提供了一个FactoryBean<T>的接口,使用者可以通过实现此接口定制实例化bean的逻辑。例如:可以实现一个FactoryBean<T> 用来代理一个对象,在使用此对象的方法时做拦截,输出日志或其它作用。类似ProxyFactoryBean的功能(AOP的实现)。再例如,一个对象的属性比较多,我想在配置此对象的时候通过逗号分割处理然后赋值到对应的属性上去,此时就可以实现该接口。
public interface FactoryBean<T> {
@Nullable
T getObject() throws Exception;
@Nullable
Class<?> getObjectType();
default boolean isSingleton() {
return true;
}
}
例如,需要配置一个客户信息
public class CustomerFactoryBean implements FactoryBean<Customer> {
private String customerInfo;
@Override
public boolean isSingleton() {
return true;
}
@Override
public Class<?> getObjectType() {
return Customer.class;
}
@Override
public Customer getObject() throws Exception {
Customer customer = new Customer();
if(this.customerInfo != null) {
String infos[] = this.customerInfo.split(",");
if(infos.length==0) {
return customer;
}
customer.setCustomerId(Long.getLong(infos[0]));
if(infos.length >=3) {
customer.setCustomerName(infos[1]);
customer.setDesc(infos[2]);
} else if(infos.length >=2){
customer.setCustomerName(infos[1]);
}
}
return customer;
}
public String getCustomerInfo() {
return customerInfo;
}
public void setCustomerInfo(String customerInfo) {
this.customerInfo = customerInfo;
}
}
此时就可以配置客户信息为:
<bean id="customer1" class="com.xps.sc.springbootdemo.domain.CustomerFactoryBean"
p:customerInfo="10093,赵老四,这个是初始描述"/>
相比于原来的配置,当属性很多时简化的比较明显
<bean id="customer" class="com.xps.sc.springbootdemo.domain.Customer"
init-method="initCustomer" destroy-method="destroyCustomer"
p:customerName="赵老四" p:customerId="10093" p:desc="这个是初始描述" />
小结
beanFactory就是一个普通的工厂接口,在spring的doGetBean方法使用时,将创建对象的步骤封装到beanFactory中,交给自定义的scope来选择是否需要创建对象来灵活的实现scope。而FactoryBean着重在于自定义创建对象的过程,然后由beanFactory通过FactoryBean的getObject获取目标对象,如果FactoryBean的isSingleton为true,则spring会利用单例缓存 通过FactoryBean创建的对象。简单来说,通过FactoryBean可以控制对象的创建,而beanFactory借助自定义的scope控制对象的创建时机。
Scope作用域
spring中的bean有五种作用域,分别为:singleton、prototype、request、session和globalSession。不同的作用域对应不同的对象创建方式。
- singleton,单例对象,全局只有一个实例,用于无状态对象(默认)
- prototype每次调用都新产生一个实例,用于有状态对象
其它的三个都是在web中产生的
- request,每次请求产生一个bean,在同一次请求中多次获取的bean是相同的
- session,每个用户产生一个bean,不同的用户之前不会有影响
- globalSession作用与session差不多,只是使用porlet的时候使用。
总结
这一节主要是重新回顾一下spring bean的加载流程,这里面还是有很多的方法实现的,对理解spring的运行及使用时如何扩展功能有很大的帮助。