Spring IOC源码分析(一):ApplicationContext体系结构设计之自底向上分析
spring-context包
1. ApplicationContext接口
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
MessageSource, ApplicationEventPublisher, ResourcePatternResolver
最顶层接口,通过继承BeanFactory接口的方法,定义了与BeanFactory的关联绑定,以及其他功能组件,如Environment,MessageSource等的关联。
ApplicationContext是bean容器的一个运行环境,而实际的bean容器为内部绑定的BeanFactory,由BeanFactory来存放bean的元数据beanDefinitions,具体存放在BeanFactory的实现类的一个类型为ConcurrentHashMap的map中,其中key为beanName,value为BeanDefinition;以及bean实例的创建。
2. ConfigurableApplicationContext接口
public interface ConfigurableApplicationContext extends ApplicationContext, Lifecycle, Closeable
继承于ApplicationContext接口,提供与applicationListener,environment,beanFactoryProcessor等相关的get/set方法,还有启动入口方法refresh。
从ApplicationContext接口额外派生这个接口,而不是直接在ApplicationContext接口声明这些的原因:这些组件都是ApplicationContext接口的实现类在内部自身使用的,而ApplicationContext接口主要是定义对外的功能和方法声明,故在ConfigurableApplicationContext接口中声明这些方法,保证接口的清晰和职责的明确。
3. AbstractApplicationContext抽象类
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext
实现ConfigurableApplicationContext接口。
refresh方法:容器启动的骨架实现,使用了模板设计模式。提供对ConfigurableApplicationContext接口的refresh方法的模板实现,即定义了ApplicationContext的启动步骤,但是不提供具体每步的实现,由子类提供。
成员变量定义:定义了applicationListener,environment,beanFactoryProcessor等相关的成员变量。
4. AbstractRefreshableApplicationContext抽象类
public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext
public abstract class AbstractRefreshableConfigApplicationContext extends AbstractRefreshableApplicationContext
implements BeanNameAware, InitializingBean
public abstract class AbstractXmlApplicationContext extends AbstractRefreshableConfigApplicationContext
FileSystemXmlApplicationContext:具体实现类,继承于AbstractXmlApplicationContext,指定从文件系统加载xml配置文件。
public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry
继承于AbstractApplicationContext抽象类,故不具备上面的Config,Refreshable功能。而Bean的注册,是通过实现BeanDefinitionRegistry接口来提供往内部的beanFactory注入beanDefinitions,而beanDefinitions的来源则是通过BeanDefinitionParser解析,如xml文件来获取的。不支持重复调用refresh。例子如下:
GenericApplicationContext ctx = new GenericApplicationContext(); XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(ctx);
xmlReader.loadBeanDefinitions(new ClassPathResource("applicationContext.xml")); PropertiesBeanDefinitionReader propReader = new PropertiesBeanDefinitionReader(ctx);
propReader.loadBeanDefinitions(new ClassPathResource("otherBeans.properties")); ctx.refresh();
public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry
// 注册指定注解的类作为bean,如@Configuration,@Component等 /**
* Create a new AnnotationConfigApplicationContext, deriving bean definitions
* from the given annotated classes and automatically refreshing the context.
* @param annotatedClasses one or more annotated classes,
* e.g. {@link Configuration @Configuration} classes
*/
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
this();
register(annotatedClasses);
refresh();
}
使用包的数组作为构造函数参数,表示扫描这些包下面的类,将需要注册的类注册成bean。处理basePackages的包下面的@Component,以及派生的如@Service,@Controller,@Repository等,具体可以通过includeFilters和excludeFilters来配置需要哪些注解的类和排除哪些注解的类
/**
* Create a new AnnotationConfigApplicationContext, scanning for bean definitions
* in the given packages and automatically refreshing the context.
* @param basePackages the packages to check for annotated classes
*/
public AnnotationConfigApplicationContext(String... basePackages) {
this();
scan(basePackages);
refresh();
}
将ServletContext中的context-param的键值对数据,放到WebApplicationContext的environment中。servlet相关的则是servletConfig的init-param的键值对数据。
String ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class.getName() + ".ROOT";
2.spring-mvc包的FrameworkServlet(或者是DispatcherServlet)所绑定WebApplicationContext为:即包含CONTEXT
/** Should we publish the context as a ServletContext attribute?. */
private boolean publishContext = true; protected WebApplicationContext initWebApplicationContext() { ... if (this.publishContext) {
// Publish the context as a servlet context attribute.
String attrName = getServletContextAttributeName();
getServletContext().setAttribute(attrName, wac);
} return wac;
} /**
* Return the ServletContext attribute name for this servlet's WebApplicationContext.
* <p>The default implementation returns
* {@code SERVLET_CONTEXT_PREFIX + servlet name}.
* @see #SERVLET_CONTEXT_PREFIX
* @see #getServletName
*/
public String getServletContextAttributeName() {
return SERVLET_CONTEXT_PREFIX + getServletName();
} /**
* Prefix for the ServletContext attribute for the WebApplicationContext.
* The completion is the servlet name.
*/
public static final String SERVLET_CONTEXT_PREFIX = FrameworkServlet.class.getName() + ".CONTEXT.";
而作为一个servlet,在web容器中,通常会绑定一个servletConfig来指定该servlet的一些属性,如在web.xml配置这个servlet时,通过init-param标签来指定。所以在WebApplicationContext中,需要在DispatcherServlet绑定的WebApplicationContext中,将与DispatcherServlet绑定的servletConfig中相关的键值对数据,放到该WebApplicationContext的environment中。
如果是编程方式,则通常是从WebApplicationInitializer接口的实现类中指定并注入。

Spring IOC源码分析(一):ApplicationContext体系结构设计之自底向上分析的更多相关文章
- Spring Ioc源码分析系列--Ioc的基础知识准备
Spring Ioc源码分析系列--Ioc的基础知识准备 本系列文章代码基于Spring Framework 5.2.x Ioc的概念 在Spring里,Ioc的定义为The IoC Containe ...
- Spring Ioc源码分析系列--Ioc源码入口分析
Spring Ioc源码分析系列--Ioc源码入口分析 本系列文章代码基于Spring Framework 5.2.x 前言 上一篇文章Spring Ioc源码分析系列--Ioc的基础知识准备介绍了I ...
- Spring IOC 源码分析
Spring 最重要的概念是 IOC 和 AOP,本篇文章其实就是要带领大家来分析下 Spring 的 IOC 容器.既然大家平时都要用到 Spring,怎么可以不好好了解 Spring 呢?阅读本文 ...
- Spring Ioc源码分析系列--前言
Spring Ioc源码分析系列--前言 为什么要写这个系列文章 首先这是我个人很久之前的一个计划,拖了很久没有实施,现在算是填坑了.其次,作为一个Java开发者,Spring是绕不开的课题.在Spr ...
- Spring Ioc源码分析系列--Ioc容器BeanFactoryPostProcessor后置处理器分析
Spring Ioc源码分析系列--Ioc容器BeanFactoryPostProcessor后置处理器分析 前言 上一篇文章Spring Ioc源码分析系列--Ioc源码入口分析已经介绍到Ioc容器 ...
- Spring Ioc源码分析系列--Ioc容器注册BeanPostProcessor后置处理器以及事件消息处理
Spring Ioc源码分析系列--Ioc容器注册BeanPostProcessor后置处理器以及事件消息处理 前言 上一篇分析了BeanFactoryPostProcessor的作用,那么这一篇继续 ...
- Spring Ioc源码分析系列--Bean实例化过程(一)
Spring Ioc源码分析系列--Bean实例化过程(一) 前言 上一篇文章Spring Ioc源码分析系列--Ioc容器注册BeanPostProcessor后置处理器以及事件消息处理已经完成了对 ...
- Spring Ioc源码分析系列--@Autowired注解的实现原理
Spring Ioc源码分析系列--@Autowired注解的实现原理 前言 前面系列文章分析了一把Spring Ioc的源码,是不是云里雾里,感觉并没有跟实际开发搭上半毛钱关系?看了一遍下来,对我的 ...
- Spring Ioc源码分析系列--自动注入循环依赖的处理
Spring Ioc源码分析系列--自动注入循环依赖的处理 前言 前面的文章Spring Ioc源码分析系列--Bean实例化过程(二)在讲解到Spring创建bean出现循环依赖的时候并没有深入去分 ...
随机推荐
- Java + selenium 启动谷歌浏览器
在之前创建的test项目下建一个test包,然后在包下建一个Chrome.java类.写入如下代码 package test; import java.util.concurrent.TimeUnit ...
- apache的commons-fileupload中FileItem类和ServletFileUpload
FileItem类的常用方法 1.boolean isFormField().isFormField方法用来判断FileItem对象里面封装的数据是一个普通文本表单字段,还是一个文件表单字 ...
- vue aliasConfig(模块别名配置)
今天研究了下鹏哥搭建的项目代码,一个人捣鼓了半天模块别名配置,边写边测试,才慢慢明白,所有写下来当个笔记: 在vue项目中,经常根据需要引入不同的功能模块,默认情况下我们通过代码 import mod ...
- 2018-8-10-win10-UWP-圆形等待
title author date CreateTime categories win10 UWP 圆形等待 lindexi 2018-08-10 19:16:50 +0800 2018-2-13 1 ...
- Vim: Overwrite read-only file without quiting vim
当你忘记以sudo命令使用vim编辑一个只读文件时,可以执行以下vim命令强制覆写该文件: :w !sudo tee % > /dev/null 命令太长,可在vimrc文件中做命令映射(映射为 ...
- ZOJ-3662 Math Magic 背包DP
这题不错,可惜我还是太弱了,没想到qwq. 看了网上大佬题解之后写的,对比了一下代码,好像我写的还是挺简洁的(逃,只是吞行比较多). 因为直接用lcm的值做下标会超时,所以我们观察发现可以组成lcm为 ...
- SpringCloud---分布式服务跟踪---Spring Cloud Sleuth
1.概述 1.1 为什么要用到服务跟踪? 随着业务的发展,系统规模也会变得越来越大,各服务之间的调用关系也变得越来越错综复杂: 通常一个由客户端发起的请求 在后端系统中会经过多个不同的微服务调用 ...
- Dart编程实例 - Dynamic 关键字
Dart编程实例 - Dynamic 关键字 void main() { dynamic x = "tom"; print(x); } 本文转自:http://codingdict ...
- Yii2 自定义组件
basic\components\HelloWidget namespace app\components; use yii\base\Widget; use yii\helpers\Html; cl ...
- Shiro学习(16)综合实例
简单的实体关系图 简单数据字典 用户(sys_user) 名称 类型 长度 描述 id bigint 编号 主键 username varchar 100 用户名 password varchar 1 ...