Spring源码之ApplicationContext

本文是针对Srping的ClassPathXMLApplicationContext来进行源码解析,在本篇博客中将不会讲述spring Xml解析注册代码,因为ApplicationContext是BeanFactory的扩展版本,ApplicationContext的GetBean和xml解析注册BeanDefinition都是用一套代码,如果您是第一次看请先看一下XMLBeanFactory解析和BeanFactory.GetBean源码解析:XMLBeanFactory源码解析地址:Srping
摘要由CSDN通过智能技术生成

本文是针对Srping的ClassPathXMLApplicationContext来进行源码解析,在本篇博客中将不会讲述spring Xml解析注册代码,因为ApplicationContext是BeanFactory的扩展版本,ApplicationContext的GetBean和xml解析注册BeanDefinition都是用一套代码,如果您是第一次看请先看一下XMLBeanFactory解析和BeanFactory.GetBean源码解析:

作者整理了spring-framework 5.x的源码注释,代码已经上传者作者的GitHub了,可以让读者更好的理解,地址:

例如现在有这样一个需求,工程在运行过程中用到的某个设置(例如VAR)是从系统环境变量中取得的,而如果用户没有在系统环境变量中配置这个参数,工程不会工作。这一要求也各种各样的解决办法,在Spring中可以这么做,可以直接修改Spring的源码,例如修改ClassPathXmlApplicationContext.当然,最好的办法是对源码进行扩展,可以自定义类:

  • 接下来直接上源码:
  • package lantao;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    import org.springframework.lantao.UserBean;
    
    public class ApplicationContextTest {
    
    	public static void main(String[] args) {
    		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-bean.xml");
    		UserBean userBean = (UserBean) applicationContext.getBean("userBean");
    		System.out.println(userBean.getName());
    	}
    
    }

    在这里直接使用ClassPathXmlApplicationContext进行xml解析,在这里xml解析的代码和GetBean的代码就不过多的描述了,ApplicationContext是BeanFactory的扩展,所以想要看这两部分源码的请看作者的上两篇博客Sprin源码解析;

  • 接下来我们看一下ClassPathXmlApplicationContext的源码:
  • /**
     * Create a new ClassPathXmlApplicationContext with the given parent,
     * loading the definitions from the given XML files.
     * @param configLocations array of resource locations
     * @param refresh whether to automatically refresh the context,
     * loading all bean definitions and creating all singletons.
     * Alternatively, call refresh manually after further configuring the context.
     * @param parent the parent context
     * @throws BeansException if context creation failed
     * @see #refresh()
     */
    public ClassPathXmlApplicationContext(
    		String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
    		throws BeansException {
    
    	super(parent);
    	// 支持解析多文件
    	setConfigLocations(configLocations);
    	if (refresh) {
    		refresh();
    	}
    }

    在setConfigLocations方法中将资源文件放入configLocations全局变量中,,并且支持多文件解析,接下来我们你看一下重点,refresh方法;

  • 源码refresh方法:
  • @Override
    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的各种功能填充,加载beanFactory,经过这个方法 applicationContext就有了BeanFactory的所有功能
    		ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    
    		// Prepare the bean factory for use in this context.
    		// 对beanFactory进行各种功能填充
    		prepareBeanFactory(beanFactory);
    
    			try {
    			// Allows post-processing of the bean factory in context subclasses.
    			//  允许在context子类中对BeanFactory进行post-processing。
    			// 允许在上下文子类中对Bean工厂进行后处理
    			// 可以在这里进行 硬编码形式的 BeanFactoryPostProcessor 调用 addBeanFactoryPostProcessor
    			postProcessBeanFactory(beanFactory);
    
    			// Invoke factory processors registered as beans in the context.
    			// 激活各种BeanFactory处理器 BeanFactoryPostProcessors是在实例化之前执行
    			invokeBeanFactoryPostProcessors(beanFactory);
    
    			// Register bean processors that intercept bean creation.
    			// 注册 拦截Bean创建 的Bean处理器,这里只是注册,真正地调用在getBean的时候  BeanPostProcessors实在init方法前后执行 doCreateBean方法中的 实例化方法中执行
    			// BeanPostProcessor执行位置:doCreateBean --> initializeBean --> applyBeanPostProcessorsBeforeInitialization 和 applyBeanPostProcessorsAfterInitialization
    			registerBeanPostProcessors(beanFactory);
    
    			// Initialize message source for this context.
    			//为上下文初始化Message源,(比如国际化处理) 这里没有过多深入
    			initMessageSource();
    
    			// Initialize event multicaster for this context.
    			//初始化应用消息广播,并放入 applicationEventMulticaster bean中
    			initApplicationEventMulticaster();
    
    			// Initialize other special beans in specific context subclasses.
    			//留给子类来初始化其它的bean
    			onRefresh();
    
    			// Check for listener beans and register them.
    			//在所有注册的bean中查找Listener bean,注册到消息广播器中
    			registerListeners();
    
    			// Instantiate all remaining (non-lazy-init) singletons.
    			//初始化剩下的单实例
    			finishBeanFactoryInitialization(beanFactory);
    
    			// Last step: publish corresponding event.
    			//完成刷新过程,通知生命周期护处理器lifecycleProcessor刷新过程,同时发出ContextRefreshEvent通知别人(LifecycleProcessor 用来与所有声明的bean的周期做状态更新)
    			finishRefresh();
    		}
    
    		catch (BeansException ex) {
    			if (logger.isWarnEnabled()) {
    				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;
    		}
    
    		finally {
    			// Reset common introspection caches in Spring's core, since we
    			// might not ever need metadata for singleton beans anymore...
    			resetCommonCaches();
    		}
    	}
    }

    对于ApplicationContext来说,refresh方法几乎涵盖了所有的基础和扩展功能,接下来看一下这个方法都做了什么;

    1. 刷新上下文,初始化前的准备工作;
    2. 加载beanFactory,经过这个方法 applicationContext就有了BeanFactory的所有功能
    3. 对beanFactory进行各种功能填充
    4. 允许在这里对BeanFactory的二次加工,例如:可以在这里进行硬编码方法的对BeanFactory进行BeanFactoryPostProcessor或BeanPostProcessor的操作;在这里简单说一下BeanFactoryPostProcessor是在bean实例化之前执行的,BeanPostProcessor是在初始化方法前后执行的,BeanFactoryPostProcessor操作的是BeanFactoryBeanPostProcessor操作的是Bean,其次这里还涉及了一个扩展BeanDefinitionRegistryPostProcessor它是继承了BeanFactoryPostProcessor,并且还有自己的定义方法 postProcessBeanDefinitionRegistry,这个方法可以操作BeanDefinitionRegistry,BeanDefinitionRegistry有个最主要的方法就是registerBeanDefinition,可以注册BeanDefinition,可以用这方法来处理一下不受spring管理的一下bean;
    5. 处理所有的BeanFactoryPostProcessor,也可以说是激活BeanFactory处理器,在这个方法里会先处理BeanDefinitionRegistryPostProcessor,在处理BeanFactoryPostProcessor,因为BeanDefinitionRegistryPostProcessor有自己的定义,所以先执行;
    6. 注册BeanPostProcessors ,这里只是注册,真正地调用在getBean的时候 BeanPostProcessors是在init方法前后执行 BeanPostProcessor执行位置:doCreateBean --> initializeBean --> applyBeanPostProcessorsBeforeInitialization 和 applyBeanPostProcessorsAfterInitialization方法中;
    7. 为上下文初始化Message源,(比如国际化处理) 这里没有过多深入;
    8. 初始化应用消息广播,初始化 applicationEventMulticaster ,判断使用自定义的还是默认的;
    9. 留给子类来初始化其它的bean;
    10. 在所有注册的bean中查找 ApplicationListener bean,注册到消息广播器中;
    11. 初始化剩下的单实例(非懒加载),这里会是涉及conversionService,LoadTimeWeaverAware,冻结BeanFactory,初始化Bean等操作;
    12. 完成刷新过程,包括 清除 下文级资源(例如扫描的元数据),通知生命周期处理器lifecycleProcessor并strat,同时publish Event发出ContextRefreshEvent通知别人;
  • 先来看prepareRefresh方法:
  • /**
     * Prepare this context for refreshing, setting its startup date and
     * active flag as well as performing any initialization of property sources.
     */
    protected void prepareRefresh() {
    	// Switch to active.
    	this.startupDate = System.currentTimeMillis();
        // 标志,指示是否已关闭此上下文
    	this.closed.set(false);
        // 指示此上下文当前是否处于活动状态的标志
    	this.active.set(true);
    
    	if (logger.isDebugEnabled()) {
    		if (logger.isTraceEnabled()) {
    			logger.trace("Refreshing " + this);
    		}
    		else {
    			logger.debug("Refreshi
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值