【笔记】Spring源码深度解析-2(ApplicationContext)

容器的扩展功能

以ApplicationContext 切入点:

 final ApplicationContext applicationContext = new ClassPathXmlApplicationContext("MyTestBean.xml");
 final MyTestBean myTestBean = (MyTestBean)applicationContext.getBean("myTestBean");
 assert myTestBean.getS().equals("test");

1、设置配置路径

解析
ClassPathXmlApplicationContext构造方法
setConfigLocations
resolvePath

2、扩展功能

集中查看refresh()方法

	@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// 1、准备刷新上下文环境
			prepareRefresh();

			// 2、初始化BeanFactory 并进行XMLd读取
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// 3、对BeanFactory进行各种功能填充例如@Qualifier 和@Autowired注解等
			prepareBeanFactory(beanFactory);

			try {
				// 4、子类覆盖父类方法做额外的处理
				postProcessBeanFactory(beanFactory);

				// 5、激活各种BeanFactory处理器
				invokeBeanFactoryPostProcessors(beanFactory);

				// 6、注册拦截bean创建的bean处理器
				registerBeanPostProcessors(beanFactory);

				// 7、为上下文初始化Message源,对不同的消息体进行国际化处理
				initMessageSource();

				// 8、初始化应用消息广播器,并放入applicationEventMulticaster  bean中;
				initApplicationEventMulticaster();

				// 9、留给子类来初始化其他的bean
				onRefresh();

				// 10、在所有注册的bean中查找listener bean ,注册到消息广播器中
				registerListeners();

				// 11、初始化剩下的单实例(非惰性的)
				finishBeanFactoryInitialization(beanFactory);

				// 完成刷新过程,通知声明周期处理器lifecycleProcessor刷新过程,同时发出ContextRefreshEvent通知别人
				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();
			}
		}
	}

3、环境准备

  • prepareRefresh();
    • initPropertySources 留给子类覆盖,符合Spring开放式结构设计,给用户最大扩展Spring的能力 ;
    • validateRequiredProperties 则是对属性进行验证
prepareRefresh
initPropertySources
validateRequiredProperties
public class MyClassPathXmlAppCon extends ClassPathXmlApplicationContext {
    public MyClassPathXmlAppCon(String... configLocation) throws BeansException {
        super(configLocation);
    }
    @Override
    protected void initPropertySources() {
        //添加验证要求
        getEnvironment().setRequiredProperties("VAR");
    }
}

4、加载BeanFactory

obtainFreshBeanFactory方法
refreshBeanFactory方法
customizeBeanFactory方法
loadBeanDefinitions方法
	@Override
	protected final void refreshBeanFactory() throws BeansException {
		if (hasBeanFactory()) {
			destroyBeans();
			closeBeanFactory();
		}
		try {
			//1、创建DefaultListableBeanFactory
			DefaultListableBeanFactory beanFactory = createBeanFactory();
			//2、指定序列化Id
			beanFactory.setSerializationId(getId());
			//3、定制BeanFactory
			customizeBeanFactory(beanFactory);
			//4、加载BeanDefinition
			loadBeanDefinitions(beanFactory);
			//5、使用全局变量记录beanFactory
			this.beanFactory = beanFactory;
		}
		catch (IOException ex) {
			throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
		}
	}

4-1、定制BeanFactory

在这里插入图片描述

4-2、加载 BeanDefinition

为指定的beanFactory初始化相应的XmlBeanDefinitionReader,并进行环境变量的设置,使用loadBeanDefinitions(XmlBeanDefinitionReader)进行加载;

5、功能扩展

prepareBeanFactory方法
在这里插入图片描述

6、BeanFactory的后处理

6-1、激活注册的BeanFactoryPostProcesser

postProcessBeanFactory(beanFactory);
invokeBeanFactoryPostProcessors(beanFactory);

  • SpringIoC容器允许BeanFactoryPostProcessor在容器实际实例化任何其他的bean之前读取元素据,并可能修改它;
  • 如果想要改变实际的bean实例,最好使用BeanPostProcessor;BeanFactoryPostProcessor的作用域是容器级的,如果你在容器中定义一个BeanFactoryPostProcesser,他只会对此容器中的bean进行后置处理。
  • 典型应用:PropertyPlaceholderConfigurer
  • 参考链接
  • 自定义BeanFactoryPostProcesser
  • 激活BeanFactoryPostProcesser

6-2、注册BeanPostProcessor

registerBeanPostProcessors(beanFactory);

6-3、初始化消息资源

initMessageSource();

6-4、初始化ApplicationEventMulticaster

initApplicationEventMulticaster()

  • 如果用户自定义了事件广播器,那么使用用户自定义的事件广播器。
  • 如果用户没有自定义事件广播器,那么使用默认的ApplicationEventMulticaster。
  • (转)了解Spring的事件监听机制

6-5、注册监听器

registerListeners();

7、初始化非延迟加载单例

finishBeanFactoryInitialization();

  • ConverionService的设置
  • 配置冻结(冻结所有的bean定义,说明注册的bean定义将不被修改或进行任何进一步的处理)
  • 非延迟加载bean的操作(ApplicationContext的默认行为是在启动时将所有单例bean提前进行实例化)

8、finishReresh

  • initLifecycleProcessor():通过LifecycleProcessor来与所有声明的bean的周期做状态更新;
  • onRefresh():启动所有实现Lifecyce接口的bean;
  • publishEvent():要通过Spring中的事件发布机制来发出;ContextRefreshedEvent事件,以保证对应的监听器来做进一步的逻辑处理;

参考书籍《Spring源码深度解析》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring框架是一个非常流行的开发框架,它提供了众多的特性和功能,如依赖注入、AOP、事务管理等等。如果要深入理解Spring框架,最好的方法就是阅读它的源代码。在这里,我将简单介绍一下Spring源码的结构和阅读方法,希望对你有所帮助。 Spring源码的结构 Spring源码的结构非常清晰,主要分为以下几个模块: 1. Spring Core:这是Spring框架的核心模块,提供了依赖注入和AOP功能等基本特性。 2. Spring Context:这个模块构建在Spring Core之上,提供了更高级的特性,如国际化、事件传播等。 3. Spring Web:这个模块提供了与Web相关的特性,如MVC框架、RestTemplate等。 4. Spring Data:这个模块提供了与数据访问相关的特性,如JPA、MongoDB等支持。 5. Spring Security:这个模块提供了安全相关的特性,如认证、授权等。 阅读Spring源码的方法 1. 熟悉设计模式 Spring框架使用了很多设计模式,如工厂模式、单例模式、装饰器模式等等。因此,在阅读Spring源码之前,你需要熟悉这些设计模式的基本原理。 2. 了解Spring的工作原理 在阅读Spring源码之前,你需要了解Spring框架的基本原理,如依赖注入、AOP、Bean生命周期等等。这些知识将帮助你更好地理解Spring源码。 3. 从Spring的入口开始 阅读Spring源码的最好方法是从Spring的入口开始,这通常是一个ApplicationContext对象。你可以通过调试工具进入ApplicationContext的构造函数,从而了解Spring框架是如何初始化的。 4. 跟踪代码流程 在阅读Spring源码时,你需要跟踪代码的流程,了解每个方法的作用和调用关系。这将帮助你更好地理解Spring框架的内部实现。 5. 阅读注释和文档 Spring源码中有很多注释和文档,这些都是非常有用的参考资料。在阅读源码时,你应该仔细阅读这些注释和文档,以便更好地理解代码的含义和作用。 总结 阅读Spring源码是一个非常有挑战性的任务,但也是一个非常有价值的学习过程。通过阅读Spring源码,你将深入理解Spring框架的内部实现,从而更好地应用它的特性和功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值