您的位置:首页 > 编程语言 > Java开发

Spring容器高级主题

2017-11-29 17:59 351 查看
1.1 Spring容器技术内幕

1.1.1 内部工作机制

spring的AbstractApplicationContext是ApplicationContext的抽象实现类,该抽象类的refresh()方法定义了Spring容器在加载配置文件后的各项处理过程,这些处理过程清晰地刻画了Spring容器启动时所执行的各项操作。看refresh()源码:

//初始化BeanFactory
ConfigurableListableBeanFactory beanFactory = obtainFrashBeanFactory();
...
//调用工厂后处理器
invokeBeanFactoryPostProcessors();

//注册Bean后处理器
registerBeanPostProcessors();

//初始化消息源
initMessageSource();

//初始化应用上下文时间广播器
initApplicationEventMulticaster();

//初始化其他特殊的Bean:具体子类实现
onRefresh();

//注册事件监听器
registerListeners();

//初始化所有单实例的Bean,使用懒加载模式的Bean除外
finishBeanFactoryInitialization(beanFactory);

//完成刷新并发布容器新事件
finishRefresh();


(1)初始化BeanFactory:根据配置文件实例化BeanFactory,在obtainFreshBeanFactory()方法中,首先调用refreshBeanFactory()方法刷新BeanFactory,然后调用getBeanFactory()方法获取BeanFactory,这两个方法都是由具体子类实现的。在这一步里,Spring将配置文件的信息装入容器的Bean定义注册表(BeanDefinitionRegistry)中,但此时Bean还没有初始化。

(2)调用工厂后处理器:根据反射机制从BeanDefinirionRegistry中找出所有实现了BeanFacotryProcessor接口的Bean,并调用其postProcessBeanFactory()接口方法。

(3)注册Bean后处理器:根据反射机制从BeanDefinirionRegistry中找出所有实现了BeanPostProcessor接口的Bean,并将他们注册到容器Bean后处理器的注册表中。

(4)初始化消息源:初始化容器的国际化消息资源。

(5)初始化应用上下文事件广播。

(6)初始化其他特殊的Bean:这是一个钩子方法,子类可以借助这个方法执行一些特殊的操作,如AbstractRefreshableWebApplicationContext就使用该方法执行初始化ThemeSource的操作。

(7)注册事件监听器。

(8)初始化所有单实例的Bean,使用懒加载模式的Bean除外:初始化Bean后,将他们放入Spring容器的缓存池中。

(9)发布上下文刷新事件:创建上下文刷新事件,事件广播器负责将这些事件广播都没个注册的事件的监听器中。

为了描述Spring容器从加载配置文件到创建出一个完整Bean的作业流程及参与的角色,我们先来看一下Bean的生命周期:

Bean的生命周期

Bean的生命周期由多个特定的生命阶段组成,每一个生命阶段都开出了一扇门,允许外界由此门对Bean施加控制。

在Spring中,可以从两个层面定义bean的生命周期:第一个层面是Bean的作用范围;第二个层面是实例化Bean时所经历的一系列阶段。

BeanFactory中Bean的生命周期

由于Bean的生命周期所经历的阶段比较多,下面通过图形化的方式进行描述。



具体过程如下:

(1) 当调用者通过getBean(beanName)向容器请求某一个Bean时,如果容器注册了org.springframework.beans.factory.config.InstantiationAwareBeanPostProsessor接口,则在实例化Bean之前,将调用接口的postProcessBeforeInstantiation()方法。

(2) 根据配置情况调用Bean的构造函数或工厂方法实例化Bean。

(3) 如果容器注册了InstantiationAwareBeanPostProcessor接口,那么在实例化B之后,调用该接口的postProcessAfterInstantiation()方法,可在这这里对已经实例化的对象进行一些“梳妆打扮”。

(4) 如果Bean配置了属性信息,那么容器在这一步将着手将配置值设置到Bean对应的属性中,不过在设置每个属性前将先调用InstantiationAwareBeanPostProcessor接口的postProcessPropertyValues()方法。

(5) 调用Bean的属性设置方法设置属性值。

(6) 如果Bean实现了org.springframework.beans.factory.BeanNameAware接口,则将调用setBeanName()接口方法,将配置文件中该Bean对应的名称设置到Bean中。

(7) 如果Bean实现了org.springframework.beans.factorys.BeanFactoryAware接口,则将调用setBeanFactory()接口方法,将BeanFactory容器实例设置到Bean中。

(8) 如果BeanFactory装配了org.springframework.beans.factory.config.BeanPostProcessor后处理器,则将调用BeanPostProcessor的Object postProcessBeforeInitialization(Object bean, String beanName)接口方法对Bean进行加工操作。其中,入参bean是当前正在处理的Bean,而beanName是当前Bean的配置名,返回的对象为加工处理后的Bean。用户可以使用该方法对某些Bean进行特殊处理,甚至改变Bean行为。BeanPostProcessor在Spring框架中占有着重要地位,为容器提供对Bean进行后续加工处理的切入点,在Spring容器所提供的各种“神奇功能”(如AOP、动态代理等)都通过BeanPostProcessor实施。

(9) 如果Bean实现了InitializingBean接口,则将调用接口的afterPropertiesSer()方法。

(10) 如果在“<”bean”>”中通过init-method属性定义了初始化方法,则将执行这个方法。

(11) BeanPostProcessor后处理器顶一个两个方法:其一是postProcessBefore Initialization(),在第8步调用;其二是Object postProcessAfterInitialization(Object bean, String beanName),这个方法在此时调用,容器再次获得对Bean的加工处理机会。

(12) 如果在”<”bean”>”中指定Bean的作用范围为scope=”prototype”,则将Bean返回给调用者,调用者负责Bean后续生命的管理,Spring不在管理这个Bean的生命周期。如果将作用范围设置为scope=”singleton”,则将Bean放入Spring Ioc容器的缓存池中,并将Bean引用放回给调用者,Spring继续对这些Bean进行后续的生命管理。

(13) 对于scope=”singleton”的Bean(默认情况),当容器关闭时,将触发Spring对Bean后续生命周期的管理工作。如果Bean实现了DisposableBean接口,则将调用接口的destory()方法,可以自此编写释放资源,记录日志等操作。

(14) 对于scope=”singleton”的Bean,如果通过”<”bean”>”的destory-method属性指定了Bean的销毁方法,那么Spring将执行Bean的这个方法,完成Bean资源的释放等操作。

Bean的完整生命周期从Spring容器着手实例化Bean开始,直到最终销毁Bean。其中经历了许多关键点,每个关键点都涉及特定的方法调用,可以将这些方法大致划分为4类。

Bean自身的方法:如果用Bean构造函数实例化Bean、调用Setter设置Bean的属性值及通过”<”bean”>”的init-method和destroy-method所指定的方法。

Bean级生命周期接口方法:如BeanNameAware、BeanFactroyAware、InitializingBean和DisposableBean,这些接口方法由Bean类直接实现。

容器级生命周期接口方法:在上图中,带“★”的步骤是由InstantiationAwareBeanPostProcessor和BeanPostProcessor这两个接口实现的,一般称他们的实现类为“后处理器”。后处理器接口一般不由Bean本身实现,他们独立于Bean,实现类以容器附加装置的形式注册到Spring容器中,并通过接口反射为Spring 容器扫描识别。当Spring容器创建任何Bean的时候,这些后处理器都会发生作用,所以这些后处理器的影响是全局性的。当然,用户可以通过合理的编写后处理器,让其仅对感兴趣的Bean进行加工处理。

工厂后处理器的接口方法:包括AspectJWeavingEnabler、CustomAutowireConfigurer、ConfigurationClassPostProcessor等方法。工厂后处理器也是容器级的,在应用上下文装配配置文件后立即调用。

Bean级生命周期接口和容器级生命接口是个性和共性辩证统一思想的体现,前者解决Bean个性化处理的问题,后者解决容器中某些Bean共性化处理的问题。

下面通过具体的实例,更好的理解Bean的生命周期。

package com.smart;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;

public class Car implements BeanFactoryAware, BeanNameAware, InitializingBean, DisposableBean {
private String brand;
private String color;
private int maxSpeed;
private String name;
private BeanFactory beanFactory;
private String beanName;

public Car() {
System.out.println("调用Car()构造函数。");
}

public String getBrand() {
return brand;
}

public void setBrand(String brand) {
System.out.println("调用setBrand()设置属性。");
this.brand = brand;
}

public String getColor() {
return color;
}

public String toString() {
return "brand:" + brand + "/color:" + color + "/maxSpeed:"+ maxSpeed;
}

public void setColor(String color) {
this.color = color;
}

public int getMaxSpeed() {
return maxSpeed;
}

public void setMaxSpeed(int maxSpeed) {
this.maxSpeed = maxSpeed;
}

public void introduce(){
System.out.println("introduce:"+this.toString());
}

// BeanFactoryAware接口方法
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("调用BeanFactoryAware.setBeanFactory()。");
this.beanFactory = beanFactory;
}

// BeanNameAware接口方法
public void setBeanName(String beanName) {
System.out.println("调用BeanNameAware.setBeanName()。");
this.beanName = beanName;
}

// InitializingBean接口方法
public void afterPropertiesSet() throws Exception {
System.out.println("调用InitializingBean.afterPropertiesSet()。");
}

// DisposableBean接口方法
public void destroy() throws Exception {
System.out.println("调用DisposableBean.destory()。");
}

// 通过<bean>的init-method属性指定的初始化方法
public void myInit() {
System.out.println("调用myInit(),将maxSpeed设置为240。");
this.maxSpeed = 240;
}

// 通过<bean>的destory-method属c void myDestory() {
System.out.println("调用myDestroy()。");
}

}

package com.smart.beanFactory;

import com.smart.Car;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

public class MyBeanPostProcessor implements BeanPostProcessor {
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
if(beanName.equals("car")) {
Car car = (Car) bean;
if(car.getColor() == null) {
System.out.println("调用BeanPostProcessor.postProcessBeforeInitialization()," +
"color为空,设置为默认颜色");
car.setColor("黑色");
}
}
return bean;
}

public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
if(beanName.equals("car")) {
Car car = (Car) bean;
if(car.getMaxSpeed() >= 200) {
System.out.println("调用BeanPostProcessor.postProcessAfterInitialization()," +
"将maxSpeed调整为200。");
car.setMaxSpeed(200);
}
}
return bean;
}
}

package com.smart.beanFactory;

import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;

import java.beans.PropertyDescriptor;

public class MyInstantiationAwareBeanPostProcessor extends
InstantiationAwareBeanPostProcessorAdapter {

//①接口方法,在实例化Bean前调用
public Object postProcessBeforeInstantiation(Class beanClass, String beanName) {
//①-1 仅对容器中的car bean处理
if("car".equals(beanName)) {
System.out.println("InstantiationAware BeanPostProcessor. " +
"postProcessBeforeInstantition");
}
return null;
}

//② 接口方法:在实例化Bean后调用
public boolean postProcessAfterInstantiation(Object bean, String beanName) {
//②-1 仅对容器中的car bean处理
if("car".equals(beanName)) {
System.out.println("InstantiationAware BeanPostProcessor. " +
"postProcessAfterInstantiation");
}
return true;
}

//③ 接口方法: 在设置某个属性时调用
public PropertyValues postProcessPropertyValues(PropertyValues pvs,
PropertyDescriptor[] pds,
Object bean, String beanName) {
//③-1 仅对容器中的car bean处理
if("car".equals(beanName)) {
System.out.println("InstantiationAware BeanPostProcessor. " +
"postProcessPropertyValues");
}
return pvs;
}
}

<?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-4.0.xsd"> <bean id="car" class="com.smart.Car"
init-method="myInit"
destroy-method="myDestory"
p:brand="红旗CA72"
p:maxSpeed="200"/>

<!--
<bean id="customAutowireConfigurer"
class="org.springframework.beans.factory.annotation.CustomAutowireConfigurer">
<property name="customQualifierTypes">
<set>
<value>test.FineQualifier</value>
</set>
</property>
</bean>
-->
<!-- bean id="car" class="com.smart.beanfactory.Car"
init-method="myInit"
destroy-method="myDestory"
p:brand="红旗CA72"/ -->

</beans>

package com.smart.beanFactory;

import com.smart.Car;
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 BeanLifeCycle {
private static void LifeCycleInBeanFactory() {
//下面两句装载配置文件并启动容器
Resource res = new ClassPathResource("com/smart/beanfactory/beans.xml");
//启动容器
BeanFactory bf = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader((DefaultListableBeanFactory) bf);
reader.loadBeanDefinitions(res);

// 向容器中注册MyBeanPostProcessor后处理器
((ConfigurableBeanFactory)bf).addBeanPostProcessor(new MyBeanPostProcessor());
// 向容器中注册MyInstantiationAwareBeanPostProcessor后处理器
((ConfigurableBeanFactory)bf).addBeanPostProcessor(new MyInstantiationAwareBeanPostProcessor());

//第一次从容器中获取car,将触发实例化Ben,这将引发Bean生命周期方法的使用
Car car1 = (Car) bf.getBean("car");
car1.introduce();
car1.setColor("红色");

//第二次从容其中获取car,直接从容器中获取
Car car2 = (Car) bf.getBean("car");

//查看car1和car2是否指向同一引用
System.out.println("car1 == car2:" + (car1 == car2));

//关闭容器
((ConfigurableBeanFactory) bf).destroySingletons();
}

public static void main(String[] args) {
LifeCycleInBeanFactory();
}
}


运行结果:

InstantiationAware BeanPostProcessor. postProcessBeforeInstantition

调用Car()构造函数。

InstantiationAware BeanPostProcessor. postProcessAfterInstantiation

InstantiationAware BeanPostProcessor. postProcessPropertyValues

调用setBrand()设置属性。

调用BeanNameAware.setBeanName()。

调用BeanFactoryAware.setBeanFactory()。

调用BeanPostProcessor.postProcessBeforeInitialization(),color为空,设置为默认颜色

调用InitializingBean.afterPropertiesSet()。

调用myInit(),将maxSpeed设置为240。

调用BeanPostProcessor.postProcessAfterInitialization(),将maxSpeed调整为200。

introduce:brand:红旗CA72/color:黑色/maxSpeed:200

car1 == car2:true

调用DisposableBean.destory()。

调用myDestroy()。

Bean从创建到销毁的生命历程,这些过程都可以在上面的流程中找到对应的步骤。Spring协调多个组件共同完成这个复杂的作业流程。下面我们用流程图表示Bean从加载配置文件到销毁的一个完整的过程。



ResourceLoader从存储介质中加载Spring配置信息,并使用Resource表示这个配置文件资源。

BeanDefinitionReader读取Resource所指向的配置文件资源,然后解析配置文件,文件中的每一个”<”bean”>”都被解析成为一个BeanDefinition对象,并保存到BeanDefinitionRegistry中。

容器扫描BeanDefinitionRegistry中的BeanDefinition,并使用java反射机制自动识别出Bean工厂后处理器(实现了BeanFactoryPostProcessor接口的Bean),然后调用这些Bean工厂后处理器,对BeanDefinitionRegistry中的BeanDefinition进行加工处理。主要完成以下两项工作:

(1)对使用占位符的<(bean)>元素标签进行解析,得到最终的配置值。这意味着对一些半成品式的BeanDefinition对象进行加工处理并得到成品的BeanDefinition对象。

(2) 对BeanDefinitionRegistry中的BeanDefinition进行扫描,通过java反射找出

所有属性编辑器的Bean(实现java.beans.PropertyEditor的Bean),并自动将他们注册到Spring容器的属性注册表中(BeanDefinitionRegistry)。

Spring容器从BeanDefinitionRegistry中取出加工后的BeanDefinition,并调用InstantiationStrategy着手Bean实例化工作。

在实例化Bean时,Spring容器使用BeanWapper对bean进行封装。BeanWapper提供了很多以java反射机制操作的Bean的方法,他将结合Bean的BeanDefinnition以及容器中的属性编辑器,完成Bean的属性注入工作。

利用容器中注册的Bean后处理器(实现BeanPostProcessor接口的Bean)对已完成属性设置工作的Bean进行后续加工,直接装配出一个准备就绪的Bean。

在查看Spring源码的时候 ,有两条清晰可见的脉络:

(1) 接口层描述了容器的重要组件及组件间的协作关系。

(2) 继承体系逐渐实现组件的各项功能。

Spring组件按照其所担任的角色可以划分为两类:

(1) 物料组件:Resource、BeanDefinition、PropertyEditor以及最终的Bean等。他们是加工流程中被加工,被消费的组件。就像流水线上被加工的物料一样。

(2) 设备组件:ResourceLoader、BeanDefinitionReader、BeanFactoryPostProcessor、InstantiationStrategy以及BeanWapper等。他们就像流水线上不同环节的加工设备,对物料组件进行加工处理。

后续我们将逐个对这些组件进行介绍。关于Resource、ResourceLoader请见Spring核心框架
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: