2019独角兽企业重金招聘Python工程师标准>>>
ApplicationContext vs BeanFactory
beanFactory就是一个容器,它的工作就是实例化、依赖注入,但是仅仅只是这样用户使用比较麻烦,很多事还需要自己做,比如通过Resource加载配置、注册扩展点、添加监听器等等,所以spring提供了一些常用的应用上下文ApplicationContext来帮助用户快速开发,ApplicationContext在beanFactory的基础之上做了扩展,它包含beanFactory的所有功能,并初始化了很多默认功能。
AbstractApplicationContext
ApplicationContext也有很多实现类,这里选取一个常用的ClassPathXmlApplicationContext做测试,跟踪他的构造方法:
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
设置好配置配置文件路径后就进入到refresh方法中,这个refresh方法是在上层抽象类AbstractApplicationContext中,先看一下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.
// 读取配置文件初始化beanFactory(加载bean, loadBeanDefinitions)
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
// 上面BeanFactory加载完毕,下面开始ApplicationContext的扩展
//额外填充beanFactory
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
// 给子类覆盖用的,子类可以对BeanFactory做一些处理
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
//执行BeanFactoryPostProcessor
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
//扩展点BeanPostProcessor的注册,在BeanFactory getBean的时候会调用
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
// 初始化message源, 国际化处理
initMessageSource();
// Initialize event multicaster for this context.
// 注册applicationEventMulticaster
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();
}
catch (BeansException ex) {
logger.warn("Exception encountered during context initialization - cancelling refresh attempt", ex);
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
}
}
这块代码流程一看就比较清晰,依次看每块实现逻辑:
prepareRefresh
protected void prepareRefresh() {
this.startupDate = System.currentTimeMillis();
//状态标识
synchronized (this.activeMonitor) {
this.active = true;
}
if (logger.isInfoEnabled()) {
logger.info("Refreshing " + this);
}
// Initialize any placeholder property sources in the context environment
//留给子类实现的
initPropertySources();
// Validate that all properties marked as required are resolvable
// see ConfigurablePropertyResolver#setRequiredProperties
//验证
getEnvironment().validateRequiredProperties();
}
初始化之前的准备,这个方法很简单,设置标志,准备初始化参数,验证必要的参数,initPropertySources留给子类扩展的。
obtainFreshBeanFactory
这步就是获取beanFactory,这个操作委托给了refreshBeanFactory方法,继续看代码:
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
//根据当前context的特点对其内部的beanFactory设置属性
customizeBeanFactory(beanFactory);
// 这个里面就是通过XmlBeanDefinitionReader加载配置到beanFactory中
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
} catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(),
ex);
}
}
先关闭之前的beanFactory,再创建新的,并根据当前上下文特点对beanFactory设置一些初始化特性参数,然后加载bean的配置。
customizeBeanFactory方法中设置参数,这里主要包括两个参数: allowBeanDefinitionOverriding允许bean名称重复,后面的覆盖前面的,默认开启、关闭后遇到相同的beanName直接抛异常,allowCircularReferences设置允许循环引用
loadBeanDefinitions方法里面用BeanDefinitionReader读取配置解析加载到beanFactory的BeanDefinitions中,这里就是beanFactory的启动了,从这里也可以看出ApplicationContext做的事情要比 beanFactory多。
prepareBeanFactory
这步就是根据当前应用上下文ApplicationContext配置它内部beanFactory的特色,具体特色还是看代码:
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// Tell the internal bean factory to use the context's class loader etc.
beanFactory.setBeanClassLoader(getClassLoader());
//el表达式 #{}
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver());
//属性转换器
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// Configure the bean factory with context callbacks.
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
//autowireByName autowireByType忽略?
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
// BeanFactory interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
//这些不作为可解析的类型,直接把对应的注入value放到集合中
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// Detect a LoadTimeWeaver and prepare for weaving, if found.
// AspectJ
//一个内置扩展点, 主要用于注入LoadTimeWeaver
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// Set a temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
// Register default environment beans.
//注册默认的环境bean
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
}
- ClassLoader:使用自己的类加载器
- BeanExpressionResolver:el表达式解析器,配置中使用#{xxx}
- ResourceEditorRegistrar: 属性转换器,比如定义属性为Date,配置文件中配置成字符串,就是通过这个里面的功能把它转换过来的,spring内置了很多属性编辑器。
- Aware-processors:对实现了对象的Aware接口注入,如:EnvironmentAware、ApplicationEventPublisherAware、ApplicationContextAware等等。
- ignoreDependencyInterface:忽略依赖注入的接口,这步跟第4步是对应的,上面处理了这里就忽略,默认只有BeanFactoryAware,可以调用该方法往忽略集合里面添加。
- registerResolvableDependency:如果注入的时候遇到这些类型,不去解析他们而是直接取对应固定的value值
- LoadTimeWeaverAwareProcessor: 设置扩展点,如果过bean实现LoadTimeWeaverAware接口,则LoadTimeWeaver对象注入到bean中,LoadTimeWeaver这里涉及到aop相关的概念(spring中实现aop用了好几种方式)
- 注册默认环境bean: environment、systemProperties、systemEnvironment
postProcessBeanFactory
上面是spring根据当前ApplicationContext做了很多设定,如果用户自定义ApplicationContext可以重写postProcessBeanFactory做其他设置,这里默认实现为空就是留给子类实现的。
invokeBeanFactoryPostProcessors
执行BeanFactoryPostProcessor,这个也是spring的开闭原则,必须在bean实例化之前执行,BeanFactoryPostProcessor的方法postProcessBeanFactory参数是beanFactory,这些后处理器可以对beanFactory进行修改,所以bean实例化之后再做这边就没有意义了。
registerBeanPostProcessors
扩展点BeanPostProcessor的注册,在BeanFactory getBean的时候会调用
initMessageSource
常用作国际化,spring里面处处都是bean,这里也一样,定义一个MessageSource的bean,在用到该功能的时候获取该bean。
initApplicationEventMulticaster
初始化event multicaster,广播所有事件到所有注册的监听器,让它们自己忽略不感兴趣的事件,默认实现类为SimpleApplicationEventMulticaster,它里面会让所有监听器在当前线程执行,这就有可能某个监听器阻塞整个应用,所有第二种方式是可以指定一个任务执行线程池来执行这些监听器。
onRefresh
留给子类实现,对于指定的bean可以进行特殊初始化
registerListeners
注册监听器到EventMulticaster中,用于接收EventMulticaster的消息,所有实现了ApplicationListener接口的都算,并且不需要提前初始化,
protected void registerListeners() {
// Register statically specified listeners first.
//先把已经指定的添加
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
// Do not initialize FactoryBeans here: We need to leave all regular
// beans
// uninitialized to let post-processors apply to them!
//再把未初始化的添加
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String lisName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(lisName);
}
}
finishBeanFactoryInitialization
在上下文中bean工厂初始化好了之后对里面必要的bean进行初始化
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// Initialize conversion service for this context.
// 初始化类型转换服务
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME)
&& beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory
.setConversionService(beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
// 先初始化实现了LoadTimeWeaverAware接口的bean
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// Stop using the temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(null);
// Allow for caching all bean definition metadata, not expecting further changes.
//冻结配置,不允许在修改了
beanFactory.freezeConfiguration();
// Instantiate all remaining (non-lazy-init) singletons.
// 根据条件(非静态、单例、非懒加载)遍历所有beanName实例化
beanFactory.preInstantiateSingletons();
}
这里最先初始化了类型转换服务,这个服务在后面getBean的时候需要用到类型转换,所以放在第一位,第二位初始化的是实现了LoadTimeWeaverAware的bean,这个里面涉及的比较多,要后面专门开篇,最后实例化满足非静态、单例、非懒加载三个条件的bean。
finishRefresh
protected void finishRefresh() {
// Initialize lifecycle processor for this context.
// 初始化lifecycle processor , 默认DefaultLifecycleProcessor
initLifecycleProcessor();
// Propagate refresh to lifecycle processor first.
//
getLifecycleProcessor().onRefresh();
// Publish the final event.
publishEvent(new ContextRefreshedEvent(this));
// Participate in LiveBeansView MBean, if active.
LiveBeansView.registerApplicationContext(this);
}
最后完成ApplicationContext初始化后要初始化一下生命周期处理类,默认DefaultLifecycleProcessor,然后调用它的onRefresh,这里引出另外一个概念:生命周期,spring中Lifecycle接口为生命周期接口,bean只要实现这个接口,在ApplicationContext初始化、销毁后会收到对应的通知,这也是ApplicationContext跟业务bean交互的一种方式。
最后发布上下文启动完毕的通知。
异常结束
如果在初始化的过程中出现了异常,spring会捕获该异常,并把已经创建的单例对象销毁,重置启动状态标志位
总结
spring中以BeanFactory为核心,它的里面处处都是以bean的形式存在,比如国际化资源,事件广播器,生命周期处理器等等都是以bean的形式注册在beanFactory上的,在该核心的基础之上封装了好几种应用上下文,用户通常是通过应用上下文的方式使用。