ApplicationContext拓展功能

本文详细介绍了Spring的ApplicationContext在初始化过程中涉及的关键步骤,包括属性设置、刷新上下文的具体流程,如环境准备、加载BeanFactory、激活BeanFactory后处理器、注册BeanPostProcessor等。在刷新上下文中,Spring对BeanFactory进行功能填充,如支持SpEL、属性编辑器、AspectJ等功能,并实现了Bean生命周期管理和事件广播机制。最后,文章总结了ApplicationContext相对于BeanFactory的拓展功能,如SpEL支持、 Aware接口、消息源和生命周期管理等。
摘要由CSDN通过智能技术生成

一、属性设置

对于ApplicationContext,其实例化前必须要设置的就是配置文件的路径--configLocation。例如:

对于非Web环境下的ClasspathXmlApplicationContext,需要通过构造函数或调用setConfigLocation设置配置文件路径;

对于Web环境下的XmlWebApplicationContext,会使用web.xml中配置的contextConfigLocation作为配置文件路径

//另外Web环境下使用的WebXmlApplicationContext还会保存ServletContext对象以及一些Web环境下的参数。

二、刷新上下文

refresh方法基本算是ApplicationContext最重要的方法之一,基本包含了ApplicationContext的大部分功能。需要注意的是,refresh方法并不是在ApplicationContext接口中定义的,而是在其子接口ConfigurableApplicationContext中定义的。下面是refresh的实现(代码位于AbstractApplicationContext):

public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// 准备刷新的上下文
			prepareRefresh();

			// 初始化BeanFactory,并读取配置文件
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// 对BeanFactory进行填充
			prepareBeanFactory(beanFactory);

			try {
				// 模版方法,由子类对初始化好的BeanFactory进行额外的处理
				postProcessBeanFactory(beanFactory);

				// 调用BeanFactoryPostProcessor后处理器
				invokeBeanFactoryPostProcessors(beanFactory);

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

				// 初始化Message源,与国际化处理相关
				initMessageSource();

				// 初始化应用消息广播器,并作为一个Bean注册到BeanFactory中
				initApplicationEventMulticaster();

				// 模版方法,交由子类实现,刷新前的特殊处理
				onRefresh();

				// 在注册的bean列表中查找Listener类型的bean,注册到消息广播器中
				registerListeners();

				// 提前初始化单例bean(非惰性的)
				finishBeanFactoryInitialization(beanFactory);

				// 通知生命周期处理器LifecycleProcessor刷新过程,并且发出ContextRefreshEvent事件
				finishRefresh();
			}

			catch (BeansException ex) {
				//log..
				// 销毁已经创建好的bean
				destroyBeans();
				// Reset 'active' flag.
				cancelRefresh(ex);
				throw ex;
			}
			finally {
				resetCommonCaches();
			}
		}
	}

刷新的流程为:

  1. 初始化的准备工作,如系统属性或环境变量的准备和验证
  2. 创建BeanFactory,并读取xml配置文件
  3. 对BeanFactory进行功能填充
  4. 通过模版方法模式,交由子类覆盖方法postProcessBeanFactory,对BeanFactory做额外处理
  5. 激活BeanFactory后处理器
  6. 注册拦截Bean创建的Bean处理器
  7. 初始化Message源
  8. 初始化消息广播器
  9. 留给子类初始化其他bean
  10. 将注册的Listener bean注册到消息广播器中
  11. 提前初始化单例bean(非惰性)
  12. 完成刷新,发出ContextRefreshEvent事件,并通知生命周期处理器LifecycleProcessor刷新过程

1、环境准备

主要是做些准备工作,对属性进行初始化和验证工作

	protected void prepareRefresh() {
		this.startupDate = System.currentTimeMillis();
		this.closed.set(false);
		this.active.set(true);
		
		//log...
		// 交由子类覆盖
		initPropertySources();

		// 验证需要的属性是否都已经被放入环境中
		getEnvironment().validateRequiredProperties();

		// Allow for the collection of early ApplicationEvents,
		// to be published once the multicaster is available...
		this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
	}

2、加载BeanFactory

ApplicationContext通过obtainFreshBeanFactory函数创建BeanFactory,自此方法后也就拥有了BeanFactory的所有功能:

	protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
		//委托给了refreshBeanFactory方法
		refreshBeanFactory();
		//因为创建BeanFactory实在子类中实现的,所以需要通过getBeanFactory才能获取到实例
		ConfigurableListableBeanFactory beanFactory = getBeanFactory();
		if (logger.isDebugEnabled()) {
			logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
		}
		return beanFactory;
	}

下面是refreshBeanFactory的实现(位于AbstractRefreshableApplicationContext):

	protected final void refreshBeanFactory() throws BeansException {
		//如果已经创建过BeanFactory,则销毁所有已经创建的Bean并且重新创建BeanFactory
		if (hasBeanFactory()) {
			destroyBeans();
			closeBeanFactory();
		}
		try {
			//实例化
			DefaultListableBeanFactory beanFactory = createBeanFactory();
			beanFactory.setSerializationId(getId());
			//设置一些属性
			customizeBeanFactory(beanFactory);
			//加载xml配置文件
			loadBeanDefinitions(beanFactory);
			//将BeanFactory实例设置到ApplicationContext中
			synchronized (this.beanFactoryMonitor) {
				this.beanFactory = beanFactory;
			}
		}
		catch (IOException ex) {
			throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
		}
	}

初始化流程:

  1. 如果已经创建过,则销毁、清理掉以前创建的BeanFactory
  2. 实例化BeanFactory
  3. 定制BeanFactory
  4. 加载xml配置文件

a、实例化BeanFactory

实例化的代码比较简单,直接新建了一个DefaultListableBeanFactory,并且传入父ApplicationContext(如果存在的话)中的BeanFactory作为父BeanFactory,下面是实例化代码:

	protected DefaultListableBeanFactory createBeanFactory() {
		//如果存在父ApplicationContext,会通过它获取父BeanFactory传出构造函数
		return new DefaultListableBeanFactory(getInternalParentBeanFactory());
	}

getInternalParentBeanFactory实现:

	protected BeanFactory getInternalParentBeanFactory() {
		return (getParent() instanceof ConfigurableApplicationContext) ?
				((ConfigurableApplicationContext) getParent()).getBeanFactory() : getParent();
	}

如果父ApplicationContext类型是ConfigurableApplicationContext,则获取其中的BeanFactory,否则将父ApplicationContext作为BeanFactory传入。

b、定制BeanFactory

	protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
		//allowBeanDefinitionOverriding:是否允许覆盖同名称的不同定义的对象
		if (this.allowBeanDefinitionOverriding != null) {
			beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
		}
		//allowCircularReferences:是否允许循环依赖
		if (this.allowCircularReferences != null) {
			beanFactory.setAllowCircularReferences(this.allowCircularReferences);
		}
	}

主要是对allowBeanDefinitionOverriding和allowCircularReferences属性进行设置,在AbstractRefreshableApplicationContext中并未对这两个属性进行设置,而是需要由子类来进行配置。

c、加载配置文件

	protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
		// 为指定的BeanFactory创建XmlBeanDefinitionReader
		XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

		// 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值