容器功能的扩展
ApplicationContext用于扩展BeanFactory中现有的功能。究竟多出了哪些功能,进一步探索。写法上:
BeanFactory bf = new XmlBeanFactory(new ClassPathResource("beanFactoryTest.xml"));
ApplicationContext bf = new ClassPahtApplicationContext("beanFactoryTest.xml");
还是以ClassPahtApplicationContext作为切入点:
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
this(new String[] {configLocation}, true, null);
}
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
ClassPahtApplicationContext可以对数据进行解析并进行加载,而对于解析及功能实现都是在refresh()中实现
setConfigLocations(String... locations):设置配置路径
用于解析给定的路径数组,如果数组中包含特殊符号如$(var),那么resolvePath中会搜索匹配的变量并替换
refresh();扩展功能
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
}
}
1_ prepareRefresh()初始化的准备工作,例如对系统属性或者环境变量进行准备及验证。
2_ obtainFreshBeanFactory 初始化BeanFactory,并进行XML文件读取
ClassPathXmlApplicationContext包含着BeanFactory所提供的一切特征,在这一步中将会复用BeanFactory中的配置文件读取解析及其它功能,这一步之后,ClassPathXmlApplicationContext实际上就包含了BeanFactory所提供的功能,也就是可以进行Bean的提取等基础操作了
3_ prepareBeanFactory() 对BeanFactory进行各种功能填充
@Qualifier与@Autowired正式在这一步骤中提供的支持
4_ postProcessBeanFactory() 子类覆盖方法做额外处理
postProcessBeanFactory是一个空函数,需要自己重写子类,覆盖方法来方便在业务上进行扩展
5_ invokeBeanFactoryPostProcessors(beanFactory) 激活各种BeanFactory处理器
6_ registerBeanPostProcessors(beanFactory) 注册拦截bean创建的bean处理器,这里只是注册,真正的调用在getBean的时候。
7_ initMessageSource() 为上下文初始化Message源,即对不同语言的消息体进行国际化处理。
8_ initApplicationEventMulticaster() 初始化应用消息广播器,并犯法如“applicationEventMuliticaster”bean中。
9_ onRefresh()留个子类初始化其他的bean
10_ registerListeners() 在所有注册的bean中查找listener bean,注册到消息广播器中
11_ finishBeanFactoryInitialization(beanFactory) 初始化剩下的单实例(非惰性的)。
12_ finishRefresh()完成刷新功能,通知生命周期处理器lifecycleProcessor刷新过程,同时发出ContextRefreshEvent通知别人。
1__ prepareRefrsh 主要做些准备工作,例如对系统属性和环境变量的初始化及验证
里边两个主要的方法initPropertySources(),validateRequiredProperties()。
initPropertySources,用户根据自己的需要重写initPropertySources()方法,并在方法进行个性化的属性处理及设置
validateRequiredProperties,对属性验证。如:工程需要某个设置(VAR)从系统环境变量中获取,如果用户没配这个变量,那么系统不能工作。这一要求在spring就可以自定义一个类集成ClassPathXmlApplicationContext,在initPropertySources()里用getEnviroment().setRequiredProperties("VAR")设置这个属性,那么在验证的就是验证这个属性,没有就会报错。当然也要在使用的时候替换掉原有的ClassPathXmlApplicationContext:ApplicationContext bf = new MyApplicationPathApplicationContext("test.xml");
2__ obtainFreshBeanFactory
加载BeanFactory,经过这个函数后,ApplicationContext就有了BeanFactory的全部功能。这个方法里的步骤:
1.创建DefaultListableBeanFactory
前面用的BeanFactory bf = new XmlBeanFactory("text.xml")中的XmlBeanFactory继承自DefaultListenBeanFactory,并提供了XmlBeanDefinitionReader属性,也就是说DefaultListenBeanFactory是容器的基础。必须首先实例化。
2.是定序列化ID
3.定制BeanFactory
customizeBeanFactory(beanFactory)
4.加载BeanDefinition
5.使用全局变量记录BeanFactory类实例。因为DefaultListenBeanFactory类型的变量beanFacotory是函数内的局部变量,所有要用全局变量来记录解析结果。
3_ customizeBeanFactory(beanFactory)
这里已经开始了对BeanFactory的扩展,在基本容器的基础上,增加了是否允许覆盖是否允许扩展的设置并提供了@Qualifier和@Autowired的支持。允许覆盖允许扩展只是判断了是否为空,为空就进行设置,但是在此之前哪个地方来设置它并没有看见,还是在子类的customizeBeanFactory覆盖方法中进行设置。接下来就是加载BeanDefinition,需要XmlBeanDefinitionReader来读取xml,这里首先初始化它,调用loadBeanDefinitions方法,和前面说的Beanfactory的加载一模一样。
这里还有很多细节。(书的135页)
3__ prepareBeanFactory() 功能扩展
1增加SPEL语言的支持
2增加属性注册编辑器
spring在DI的时候类似于Date这种属性无法识别,会报错,可以有两种方法解决
1:使用自定义属性编辑器
2:注册spring自带的属性编辑器CustomDateEditor
3添加ApplicationContextAwareProcessor处理器
对于beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this))的主要目的就是注册个BeanPostProcessor。真正的逻辑还在ApplicationContextAwareProcessor中。ApplicationContextAwareProcessor实现BeanPostProcessor接口。之前在bean实例化的时候,也就是spring激活bean的init-method的前后,会调用BeanPostProcessor的postProcessBeforeInitialization方法和postProcessAfterInitialization方法,同样对于ApplicationContextAwareProcessor我们也看这两个方法。
postProcessAfterInitialization方法没有做过多逻辑处理
postProcessBeforeInitialization方法,其中主要的逻辑是调用了invokeAwareInterfaces,从这个方法代码中能看出主要是实现这些Aware接口在被初始化的后,可以获得一些对应的资源。
4.设置忽略依赖。将ApplicationContextAwareProcessor注册后,invokeAwareInterfaces方法中间接调用的Aware已经不是普通的bean了,需要在spring做bean的依赖注入的时候忽略他们。
5.注册依赖。当注册了依赖解析后,例如当注册了对BeanFactory.Class的解析依赖后,当bean的属性注入的时候,一旦检测属性为BeanFactory类型便会将实例beanFactory注入进去。
4_ postProcessBeanFactory BeanFactory的后处理
11_ finishBeanFactoryInitialization(beanFactory)
完成BeanFactory的初始化工作,其中包括ConversionService的设置、配置冻结以及非延迟加载的bean的初始化工作。
1.ConversionService的设置。之前说过用自定义类型转化器可以从String转Date,spring中还提供了另外一种转换方式:使用Converter。
2.冻结配置。冻结所有的bean定义说明注册的bean定义将不能被修改或进行任何进一步处理。
3.初始化非延迟加载。ApplicationContext实现的默认方式就是在启动的时候将所有的单例bean提前实例化,通常只是好事,因为这样在配置的中的错误能马上就发现。这个实例化的过程是在finishBeanFactoryInitialization中完成的。
12_ finishRefresh
在spring中还提供了Lifecycle接口,包好start/stop方法,实现此接口后Spring会保证在启动的时候调用其start方法开始生命周期,并在关闭的时候调用stop方法接受生命周期,通常用来配置后台程序,在启动后一直运行(如对MQ进行轮询)。
1.initLifecycleProcessor:当ApplicationContext启动或停止时,会通过LifecycleProcessor来与所有的bean的周期做状态更新,而在使用前需要初始化
2.onRefresh:启动所有实现了Lifecycle接口的bean
3.publishEvent:当完成ApplicationContext初始化的时候,要通过Spring中的时间发布机制来发出ContextRefreshEvent事件,保证对应的监听器可以进一步的逻辑处理。