文档章节

Spring核心源码:ApplicationContext

GITTODO
 GITTODO
发布于 2018/04/25 09:32
字数 2347
阅读 75
收藏 4

废话

  1. spring版本:4.0.6
  2. 随便做了这么多年的spring,但是源码就只阅读过 shiro的。一直想去读一下spring,mybatis,netty,这些结构优美的开源框架的源码。

核心包:

  • spring-context:spring的上下文类,管理可以看作是spring容器的主要管理者,及对外提供接口方。
    • ApplicationContext
  • spring-core:核心工具包,提供了环境、解析工具、创建工具。
  • spring-beans: bean对象创建、对象属性加载
  • spring-aop:IOC注入工具
  • spring-expression:展示工具包,类型转换,反射工具。

基本流程:

  • 1.创建beanFactory、BeanDefinition(一个bean的信息类)

  • (context)AbstractApplication.refresh():核心类型。初始化环境信息,加载配置路径、实例化对象

    • (context)AbstractApplication.prepareRefresh():加载环境信息
    • (context)AbstractApplication.obtainFreshBeanFactory():创建bean工程
      • (context)AbstractRefreshableApplicationContext.refreshBeanFactory():创建bean工厂DefaultListableBeanFactory(),接着调用loadBeanDefinitions()
        • (context)AbstractXmlApplicationContext.loadBeanDefinitions():实例化一个XML解析器(XmlBeanDefinitionReader),将环境信息和工厂加载进去,调用loadBeanDefinitions(),最后调用XmlBeanDefinitionReader.loadBeanDefinitions()出解析xml配置.
          • (bean)XmlBeanDefinitionReader.loadBeanDefinitiodins():先加载配置文件到内存,创建一个BeanDefinitionDocumentReader。在实例化bean对象
            • (bean)BeanDefinitionDocumentReader.registerBeanDefinitions():创建XmlReaderContext解析器,实例化bean对象
            • (bean)BeanDefinitionDocumentReader.parseBeanDefinitions():开始解析xml配置
            • (bean)BeanDefinitionDocumentReader.parseDefaultElement():解析import、alias、bean、beans配置,然后调用到DefaultListableBeanFactory.registerBeanDefinition()(bean创建类)
              • (bean)BeanDefinitionParserDelegate.parseBeanDefinitionElement():解析属性并检测,调用core层工具类。
                • (core)BeanDefinitionReaderUtils.createBeanDefinition():创建BeanDefinition,直接将类名加进去
              • (bean)DefaultListableBeanFactory.registerBeanDefinition():开始创建BeanDefinition,先给beanDefinitionMap加锁,如果已经有了跳过,释放锁。然后resetBeanDefinition()创建
              • (bean)DefaultListableBeanFactory.resetBeanDefinition():先清理之前的BeanDefinition
    • (context)AbstractApplication.prepareBeanFactory():加载环境信息
    • (context)AbstractApplication.postProcessBeanFactory():加载环境信息
    • (context)AbstractApplication.invokeBeanFactoryPostProcessors():加载环境信息
    • (context)AbstractApplication.registerBeanPostProcessors():加载环境信息
    • (context)AbstractApplication.initMessageSource():加载环境信息
    • (context)AbstractApplication.initApplicationEventMulticaster():加载环境信息
    • (context)AbstractApplication.onRefresh():加载环境信息
    • (context)AbstractApplication.registerListeners():加载环境信息
    • (context)AbstractApplication.finishBeanFactoryInitialization():初始化bean
    • (context)AbstractApplication.finishRefresh():加载环境信息
    • (context)AbstractApplication.destroyBeans():加载环境信息
    • (context)AbstractApplication.cancelRefresh():加载环境信息
  • 2.实例化对象:AbstractApplication.finishBeanFactoryInitialization()

    • (context)AbstractApplicationContext.getBean():调用工厂,通过工厂根据名称获取代理对象。
      • (bean)DefaultListableBeanFactory.doGetBean():先检测名称,查看是否存在。
      • (bean)DefaultListableBeanFactory.doCreateBean()-->createBeanInstance():先检测名称,查看是否存在。
        • (bean)SimpleInstantiationStrategy.instantiate():通过class<?>.getDeclaredConstructor(),获取目标bean的构造器
          • (bean)BeanUtils.instantiateClass():ctor.newInstance(args),实例化数据 直接实例化一个对象。
  • 注入:构造器注入、方法注入

    • 构造器注入
      • 在 (bean)DefaultListableBeanFactory.doCreateBean()-->createBeanInstance() 中,检测构造器是注入是否被使用。然后调用autowireConstructor()
        • new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs);
          • 直接检测构造器类,根据引用beanFactory.getBean()获取bean。如果没有,直接走beanFactory.doGetBean()获取
          • 直接在初始化的时候,将构造器数据传入进去
    • 方法注入
      • 在构造器实例化之后,会直接调用 DefaultListableBeanFactory.doCreateBean()->populateBean()
      • 检测Property的 ref,然后根据引用beanFactory.getBean()获取bean。如果没有,直接走beanFactory.doGetBean()获取
      • 通过反射,获取method。最后调用Method.invoke()注入进去

"模仿案例"
Class<?> ob = Class.forName("com.fxl.spring.test.SayServiceImpl");
SayService say = (SayService) ob.newInstance();
Method[] methodList = ob.getMethods();
for (Method method : methodList) {
	System.out.println(method.getName());
	if("setReflectNum".equals(method.getName())){
		method.invoke(say, new Integer(2));
	}
}
say.getMessage();

从说明开始:

ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:conf/Test.xml");
One one = (One) ctx.getBean("one");
System.out.println(one.getTwo().getName());
one.getDateTime();

一般,我们开始学习spring的时候,都会从上面的使用模版开始。无论是谁都会告诉你第一行是生成一个beanFactroy的工厂,第二行就是从获取需要的class对象。但是里面发生了什么,我们并不了解。

  • ApplicationContext
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
		MessageSource, ApplicationEventPublisher, ResourcePatternResolver

1.查看源码,我们发现是spring上下文的基本功能实现。查看说明

  • ApplicationContext:Central interface to provide configuration for an application. This is read-only while the application is running, but may be reloaded if the implementation supports this.
    • spring的上下文:为spring提供核心的应用接口,当spring运行的时候,只能做读操作。当然可以重新呗加载<不能修改,只能重新创建>

//ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:conf/Test.xml");
1. ClassPathXmlApplicationContext:'记录配置源'

public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext {
	private Resource[] configResources;
}

2. AbstractXmlApplicationContext:'Context封装的xml实现'
public abstract class AbstractXmlApplicationContext extends AbstractRefreshableConfigApplicationContext {
	private boolean validating = true;
}

3.'AbstractRefreshableConfigApplicationContext':'记录配置信息'
public abstract class AbstractRefreshableConfigApplicationContext extends AbstractRefreshableApplicationContext
		implements BeanNameAware, InitializingBean {
	private String[] configLocations;
}

4. 'AbstractRefreshableApplicationContext':'refresh上下文的适配类型,用来创建beanfactory'
public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {

	private Boolean allowBeanDefinitionOverriding;

	private Boolean allowCircularReferences;

	/** Bean factory for this context */
	// 默认的beanfactory
	private DefaultListableBeanFactory beanFactory;

	/** Synchronization monitor for the internal BeanFactory */
	private final Object beanFactoryMonitor = new Object();
}

5. 'AbstractApplicationContext':context的核心类、
    // 实例化spring-core的对象
    // refresh()刷新context
public abstract class AbstractApplicationContext extends DefaultResourceLoader
		implements ConfigurableApplicationContext, DisposableBean {
	/** Logger used by this class. Available to subclasses. */
	protected final Log logger = LogFactory.getLog(getClass());

	/** Unique id for this context, if any */
	private String id = ObjectUtils.identityToString(this);

	/** Display name */
	private String displayName = ObjectUtils.identityToString(this);

	/** Parent context */
	// 父类上下文
	private ApplicationContext parent;

	/** BeanFactoryPostProcessors to apply on refresh */
	private final List<BeanFactoryPostProcessor> beanFactoryPostProcessors =
			new ArrayList<BeanFactoryPostProcessor>();

	/** System time in milliseconds when this context started */
	private long startupDate;

	/** Flag that indicates whether this context is currently active */
	private boolean active = false;

	/** Flag that indicates whether this context has been closed already */
	private boolean closed = false;

	/** Synchronization monitor for the "active" flag */
	// active锁
	private final Object activeMonitor = new Object();

	/** Synchronization monitor for the "refresh" and "destroy" */
	private final Object startupShutdownMonitor = new Object();

	/** Reference to the JVM shutdown hook, if registered */
	private Thread shutdownHook;

	/** ResourcePatternResolver used by this context */
	// 资源加载匹配
	private ResourcePatternResolver resourcePatternResolver;

	/** LifecycleProcessor for managing the lifecycle of beans within this context */
	// 生命周期管理
	private LifecycleProcessor lifecycleProcessor;

	/** MessageSource we delegate our implementation of this interface to */
	//消息实现类
	private MessageSource messageSource;

	/** Helper class used in event publishing */
	//事件封装类型
	private ApplicationEventMulticaster applicationEventMulticaster;

	/** Statically specified listeners */
	private Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<ApplicationListener<?>>();

	/** Environment used by this context; initialized by {@link #createEnvironment()} */
	// 环境配置:JVM环境
	private ConfigurableEnvironment environment;
}

6. DefaultResourceLoader: 类加载器
public class DefaultResourceLoader implements ResourceLoader {
	private ClassLoader classLoader;
}		
  • EnvironmentCapable:All Spring application contexts are EnvironmentCapable, and the interface is used primarily for performing instanceof checks in framework methods that accept BeanFactory instances that may or may not actually be ApplicationContext instances in order to interact with the environment if indeed it is available.

    • 所有的spring都是环境功能,在如果需要和各种环境进行交互,当接受BeaFactory 实例,提供instanceof这一类的接口。<这个方法应该是用来屏蔽一些不同系统差异>
  • ListableBeanFactory:Extension of the BeanFactory interface to be implemented by bean factories that can enumerate all their bean instances, rather than attempting bean lookup by name one by one as requested by clients. BeanFactory implementations that preload all their bean definitions (such as XML-based factories) may implement this interface. (beanfactory的一个扩展接口)

  • HierarchicalBeanFactory:Sub-interface implemented by bean factories that can be part of a hierarchy.

    • 由bean工厂实现的子接口,可以作为层次结构的一部分。
  • MessageSource:Strategy interface for resolving messages, with support for the parameterization and internationalization of such messages.

    • 解决消息的策略接口,支持参数化和此类消息的国际化。
  • ApplicationEventPublisher:Interface that encapsulates event publication functionality .(事件封装)

  • ResourcePatternResolver:Strategy interface for resolving a location pattern (for example, an Ant-style path pattern) into Resource objects. (资源处理)

  • ClassPathXmlApplicationContext

public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
			throws BeansException {
        super(parent);  //加载applicationContext
		setConfigLocations(configLocations);    //设置配置文件地址
		if (refresh) {
			refresh();  
		}
	}    

debug进classPathXmlApplication里面,发现最重要的是上上面这段代码。用eclipse的crtl+T,我们可以看见继承关系.主要是获取一下applicationContext,然后将xml文件的路径重新设置。最后通过AbstractApplicationContext 将配置重新加载到内存中。

  • AbstractApplicationContext

1.spring上下文的实现抽象类。用于application的合并,beanFactory的重新实现等等

public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing. (刷新前)
			// 获取JVM环境Environment,检测启动传入的参数
			'prepareRefresh()'';

			// Tell the subclass to refresh the internal bean factory. 
			// 创建一个 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.(允许子类中正在执行中的工厂)
				// 实例化并调用所有已注册的BeanPostProcessor bean(事件bean),按照给定顺序。处理一些示例化过程中的业务逻辑,就像servlet的filter
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.(执行工厂作为一个bean注册到context中)
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.(注册bean执行者拦截创建)
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.(初始化)
				initMessageSource();

				// Initialize event multicaster for this context.(初始化事件)
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.(初始化特别的的子类bean)
				onRefresh();

				// Check for listener beans and register them.(检测监听的bean,创建它们)
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.(实例化所有重名了的单例)
				// 完成这个上下文的bean工厂的初始化,初始化所有剩余的单例bean。
				'finishBeanFactoryInitialization(beanFactory)';

				// Last step: publish corresponding event.(最后一步:发布事件)
				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.(摧毁bean)
				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();
			}
		}
	}
  • prepareRefresh:获取JVM环境Environment,检测启动传入的参数

  • ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory():加载并解析配置信息

  • prepareBeanFactory(beanFactory):将JVM环境全部传入全部实例化放在 beanfactory中

  • postProcessBeanFactory(beanFactory):在它的标准初始化之后修改应用程序上下文的内部bean工厂。所有的bean定义都已经加载了,但是还没有实例化bean。这允许在特定的应用程序环境实现中注册特殊的beanpost处理器等。(空方法)

  • invokeBeanFactoryPostProcessors(beanFactory):执行BeanPostProcessor,用于处理一些bean的示例

  • registerBeanPostProcessors(beanFactory):将BeanPostProcessor放入beanfactory中

  • initMessageSource():初始化message信息

  • initApplicationEventMulticaster():初始化applicationEventMulticaster,用来处理event事件。由哪个listener来处理

  • onRefresh()

  • registerListeners():消息事件监听器

  • finishBeanFactoryInitialization(beanFactory):将剩余的bean实例化,存放在beanfactory的singletonObjects中。一般来说剩余的都是配置文件中的信息

  • finishRefresh()

  • destroyBeans()

  • cancelRefresh(ex)

  • resetCommonCaches()

© 著作权归作者所有

GITTODO

GITTODO

粉丝 25
博文 138
码字总数 197485
作品 0
程序员
私信 提问
Spring Boot 运作原理

1、Spring Boot 简介 SpringBoot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义...

编程SHA
02/22
224
0
spring ApplicationContextAware接口

ApplicationContextAware 首先 ApllicationContextAware 解释 应用上下文 感知 ApplicationContext 是spring 的核心:应用容器 不说了 ,上代码 注意事项: 1 本类需要由spring容器管理 2 从...

随身听1111
2017/11/06
16
0
给spring-boot测试提供unitils支持的开源项目

一、unitils测试框架优缺点介绍 在unitils的支持下,xml配置的spring项目在测试时,有如下好处: 1、利用注解@DataSet、@ExpectedDataSet来准备数据和校验结果数据,每次运行测试用例不用重新...

yangjianzhou
2018/07/09
548
1
三条路线告诉你如何掌握Spring IoC容器的核心原理

一、前言 前三篇已经从历史的角度和大家一起探讨了为什么会有Spring,Spring的两个核心概念:IoC和AOP的雏形,Spring的历史变迁和如今的生态帝国。本节的主要目的就是通过一个切入点带大家一...

Java小铺
2018/08/27
0
0
spring源码-bean之初始化-1

  一、spring的IOC控制反转:控制反转——Spring通过一种称作控制反转(IOC)的技术促进了松耦合。当应用了IOC,一个对象依赖的其它对象会通过被动的方式传递进来,而不是这个对象自己创建...

小不点丶
2018/08/09
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Activity启动模式二

上篇文章Activity启动模式一主要介绍了Activity的四种启动模式,这些启动模式都是在AndroidManifest中进行配置的。除此之外,Android系统还通过Intent类提供了一些标志位,同样可以指定Activ...

ltlovezh
11分钟前
4
0
三原色还原

1、Color Filter Array — CFA 随着数码相机、手机的普及,CCD/CMOS 图像传感器近年来得到广泛的关注和应用。 图像传感器一般都采用一定的模式来采集图像数据,常用的有 BGR 模式和 CFA 模式...

天王盖地虎626
23分钟前
3
0
kubernetes pod exec接口调用

正文 一般生产环境上由于网络安全策略,大多数端口是不能为集群外部访问的。多个集群之间一般都是通过k8s的ApiServer组件提供的接口通信,如https://192.168.1.101:6443。所以在做云平台时,...

码农实战
今天
8
0
3_数组

3_数组

行者终成事
今天
8
0
经典系统设计面试题解析:如何设计TinyURL(二)

原文链接:https://www.educative.io/courses/grokking-the-system-design-interview/m2ygV4E81AR 编者注:本文以一道经典的系统设计面试题:《如何设计TinyURL》的参考答案和解析为例,帮助...

APEMESH
今天
7
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部