https://blog.csdn.net/lihuapiao/article/details/51919283
源码环境 : idea + spring 4.3.4 +tomcat7 + gradle
附 : 基于 java 注解的 配置元数据 的 web.xml 配置做参考(spring 3.0 后支持)
-
<?xml version="1.0" encoding="UTF-8"?>
-
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
-
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
-
xsi:schemaLocation=
"http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
-
version=
"3.1">
-
-
-
<listener>
-
<listener-class>org.springframework.web.context.ContextLoaderListener
</listener-class>
-
</listener>
-
-
<context-param>
-
<param-name>contextClass
</param-name>
-
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
-
</context-param>
-
-
<context-param>
-
<param-name>contextConfigLocation
</param-name>
-
<param-value>
-
com.ycit.config.DataSourceConfig,
-
com.ycit.config.AppConfig
-
</param-value>
-
</context-param>
-
-
<servlet>
-
<servlet-name>solutionServlet
</servlet-name>
-
<servlet-class>org.springframework.web.servlet.DispatcherServlet
</servlet-class>
-
<init-param>
-
<param-name>contextClass
</param-name>
-
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
-
</init-param>
-
<init-param>
-
<param-name>contextConfigLocation
</param-name>
-
<param-value>com.ycit.config.MvcConfig
</param-value>
-
</init-param>
-
</servlet>
-
<servlet-mapping>
-
<servlet-name>solutionServlet
</servlet-name>
-
<url-pattern>/
</url-pattern>
-
</servlet-mapping>
-
-
<!-- 开启 druid 监控-->
-
<servlet>
-
<servlet-name>DruidStatView
</servlet-name>
-
<servlet-class>com.alibaba.druid.support.http.StatViewServlet
</servlet-class>
-
</servlet>
-
<servlet-mapping>
-
<servlet-name>DruidStatView
</servlet-name>
-
<url-pattern>/druid/*
</url-pattern>
-
</servlet-mapping>
-
-
</web-app>
1. ContextLoaderListener 简介
★ 位置 : Spring-web 的 jar 包中 ,包路径 : org.springframework.web.context.ContextLoaderListener
★ UML 关系图如下 :
介绍:
引导性 监听器,用于启动 和 关闭 Spring 的 根 WebApplicationContext,委托(delegate)给 ContextLoader 和 ContextCleanupListener 执行。
如果配置 了 org.Springframework.web.util.Log4jConfigListener(已过时) ,则 应该 配置在 Log4jConfigListener 的后面;Spring 3.1 之后,ContextLoaderListener支持 通过构造函数 直接注入 根 WebApplicationContext ,因此允许 编程式 的 配置 Servlet 3.0+ 的 环境。
该类继承了 ServletContextListener,ServletContextListener 是 servlet 中 八个 分门别类的监听器之一 ,负责监听 Servlet Context 的生命周期 (该生命周期其实就对应着应用的生命周期)。所以 ContextLoaderListener 就负责 监听 Spring 的初始化和 Spring 的 消亡 。当 启动服务器发布项目时,spring 初始化,触发 ContextInitialized()方法,初始化 WebApplicationContext 对象;当关闭服务器时,触发 contextDestroyed ( ) 方法,销毁 WebApplicationContext 对象 。
而主要的操作业务从 ContextLoader 类继承而来;
2. 流程分析
初始化大致流程如下图所示(有所省略,其中省略了 配置并且 刷新 WebApplicationContext 方法)。
分析:
加载 web.xml 中的配置,和 spring 相关的启动配置包括 : ContextLoaderListener 监听器的配置;contextClass ( 配置Spring使用的 ApplicationContext 实现类,可省略,原因见下文)以及 contextConfigLocation(配置文件的位置,可省略,见下) 参数的配置;
静态代码块 :应用启动,ContextLoaderListener 及其父类 ContextLoader 开始工作 。 这里有必要提及一下关于子父类静态代码块,构造函数的执行顺序的问题 。正常的顺序是 。 父类的静态代码块 → 子类的静态代码块 → 父类代码块(非静态) → 父类构造函数 → 子类代码块 (非静态) → 子类构造函数 。 所以首先执行 ContextLoader 的静态代码块 :此代码块的功能是读取 Spring 的配置文件 ContextLoader.properties ,而该配置文件的内容只有如下一行,为 Spring 的字段 defaultStrategies(java.util.Properties 类型) 赋如下的键值对 。
org.springframework.web.context.WebApplicationContext=org.springframework.web.context.support.XmlWebApplicationContext
initWebApplicationContext : 通过 给定的 ServletContext 初始化 Spring 的 web 应用上下文(WebApplicationContext),分别保存在如下两个私有字段中:
-
/**
-
* The 'current' WebApplicationContext, if the ContextLoader class is
-
* deployed in the web app ClassLoader itself.
-
* volatile 为 多线程中用到的 关键字 ,作用是 保持被修饰的字段在被读取的时候返回的都是当前最新的,
-
*/
-
private
static
volatile WebApplicationContext currentContext;
-
-
/**
-
* The root WebApplicationContext instance that this loader manages.
-
*/
-
private WebApplicationContext context;
// 保存初始化的ApplicationContext 实现类,可用于 ServletContext 消亡时 ApplicationContext关闭并释放资源
currentContext 是指 当前 的 WebApplicationContext;
context 是指 每个 ServletContext 对应的那个 WebApplicationContext;
Java支持volatile关键字,但它被用于其他不同的用途。当volatile用于一个作用域时,Java保证如下:
1.(适用于Java所有版本)读和写一个volatile变量有全局的排序。也就是说每个线程访问一个volatile作用域时会在继续执行之前读取它的当前值,而不是(可能)使用一个缓存的值。(但是并不保证经常读写volatile作用域时读和写的相对顺序,也就是说通常这并不是有用的线程构建)。
2.(适用于Java5及其之后的版本)volatile的读和写建立了一个happens-before关系,类似于申请和释放一个互斥锁。
使用volatile会比使用锁更快,但是在一些情况下它不能工作。volatile使用范围在Java5中得到了扩展,特别是双重检查锁定现在能够正确工作。
3 . 源码分析
初始化源码分析
ContextLoader . initWebApplicationContext ()主代码:最终返回 一个 WebApplicationContext 的相关实现类;
-
// Store context in local instance variable, to guarantee that
-
// it is available on ServletContext shutdown.
-
/创建相应的 WebApplicationContext 实例 begin/
-
if (
this.context ==
null) {
-
this.context = createWebApplicationContext(servletContext);
-
}
-
/创建相应的 WebApplicationContext 实例 end/
-
/设置 parent context属性,对于多个 root WebApplicationContext 可以共享,对于单个的不需要关心parent context/
-
if (
this.context
instanceof ConfigurableWebApplicationContext) {
-
ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext)
this.context;
-
if (!cwac.isActive()) {
-
// The context has not yet been refreshed -> provide services such as
-
// setting the parent context, setting the application context id, etc
-
if (cwac.getParent() ==
null) {
-
// The context instance was injected without an explicit parent ->
-
// determine parent for root web application context, if any.
-
ApplicationContext parent = loadParentContext(servletContext);
-
cwac.setParent(parent);
-
}
-
/设置 parent context 属性 end/
-
// 配置 并且刷新 WebApplicationContext,此处比较复杂
-
configureAndRefreshWebApplicationContext(cwac, servletContext);
-
}
-
}
-
//注册 context
-
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,
this.context);
-
/保存当前的应用上下文 begin/
-
ClassLoader ccl = Thread.currentThread().getContextClassLoader();
-
if (ccl == ContextLoader.class.getClassLoader()) {
-
currentContext =
this.context;
-
}
-
else
if (ccl !=
null) {
-
currentContextPerThread.put(ccl,
this.context);
-
}
-
/保存当前的应用上下文 end/
-
return
this.context;
相关类介绍:
ConfigurableWebApplicationContext 接口: WebApplicationContext 和 ConfigurableApplicationContext 的 子接口
WebApplicationConext 接口:ApplicationContext 的子接口,为 web 应用 提供 配置(获取 ServletContext)的接口;当应用正在运行时,是只读的,但是如果实现类支持的话,可以重新加载;相对于其父接口的 ApplicationContext , 该接口提供了 获取 ServletContext 对象的方法;
ConfigurableApplicationContext 接口:ApplicationContext 的子接口,提供 配置 一个 应用上下文的 属性,如设置 environment,BeanFactoryPostProcessor,ApplicationListener,ProtocolResolver 等;
附录1: AnnotationConfigWebApplicationContext 和 XmlWebApplicationContext 的 顶层中 和 BeanFactory 相关的UML 类图;
以上源代码主要做了三件事:
① 实例化 WebApplicationContext 相关 实现类
② 加载并 设置父 上下文 (此处略 ,一般的 web 应用 无 父上下文,返回 null)
③ 配置 并 刷新 WebApplicationContext
3.1 ContextLoader . createWebApplicationContext (ServletContext sc):实例化 WebApplicationContext 实现类
-
protected WebApplicationContext createWebApplicationContext(ServletContext sc) {
-
Class<?> contextClass = determineContextClass(sc);
-
if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {
-
throw
new ApplicationContextException(
“Custom context class [” + contextClass.getName() +
-
“] is not of type [” + ConfigurableWebApplicationContext.class.getName() +
“]”);
-
}
-
return (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
//实例化
-
}
ContextLoader . determineContextClass(ServletContext sc) 方法: 决定contextClass,该 contextClass 决定了 WebApplicationContext 的 实现类的类型;这里创建的 实现类为 AnnotationConfigWebApplicationContext ;
-
protected Class<?> determineContextClass(ServletContext servletContext) {
-
//获取 web.xml 中 初始化参数 contextClass,本文设置了该参数
-
String contextClassName = servletContext.getInitParameter(CONTEXT_CLASS_PARAM);
-
if (contextClassName !=
null) {
-
try {
-
return ClassUtils.forName(contextClassName, ClassUtils.getDefaultClassLoader());
//使用指定的 class 反射出 Class 对象
-
}
-
catch (ClassNotFoundException ex) {
-
throw
new ApplicationContextException(
-
“Failed to load custom context class [” + contextClassName +
“]”, ex);
-
}
-
}
-
else {
-
// 否则使用默认策略,即获得 XMLWebApplicationContext 对应的bean 的名称
-
contextClassName = defaultStrategies.getProperty(WebApplicationContext.class.getName());
-
try {
-
return ClassUtils.forName(contextClassName, ContextLoader.class.getClassLoader());
-
}
-
catch (ClassNotFoundException ex) {
-
throw
new ApplicationContextException(
-
“Failed to load default context class [” + contextClassName +
“]”, ex);
-
}
-
}
-
}
3.2 加载并 设置父 上下文
略
3.3 ContextLoader . configureAndRefreshWebApplicationContext(cwac, servletContext):配置并且刷新 WebApplicationContext
-
protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) {
-
if (ObjectUtils.identityToString(wac).equals(wac.getId())) {
-
// The application context id is still set to its original default value
-
// -> assign a more useful id based on available information
-
//获取 web.xml 中定义的 contextId 初始化值,未定义
-
String idParam = sc.getInitParameter(CONTEXT_ID_PARAM);
-
if (idParam !=
null) {
-
wac.setId(idParam);
-
}
-
else {
-
// Generate default id…
-
wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX +
-
ObjectUtils.getDisplayString(sc.getContextPath()));
-
}
-
}
-
-
wac.setServletContext(sc);
//配置了 servletContext 属性
-
//获取 web.xml 中定义的 contextConfiLocation 初始化参数值 ,已定义,
-
//配置了除 mvc 配置文件的其他配置文件路径如 数据库连接配置 和 spring 配置文件
-
String configLocationParam = sc.getInitParameter(CONFIG_LOCATION_PARAM);
-
if (configLocationParam !=
null) {
-
wac.setConfigLocation(configLocationParam);
//配置了 configLocation 字段属性
-
}
-
-
// The wac environment’s #initPropertySources will be called in any case when the context
-
// is refreshed; do it eagerly here to ensure servlet property sources are in place for
-
// use in any post-processing or initialization that occurs below prior to #refresh
-
/** 初始化 应用上下文 中 和 Servlet 相关的 占位符 属性资源 begin /
-
ConfigurableEnvironment env = wac.getEnvironment();
-
if (env
instanceof ConfigurableWebEnvironment) {
-
((ConfigurableWebEnvironment) env).initPropertySources(sc,
null);
-
}
-
/ 初始化 应用上下文 中 和 Servlet 相关的 占位符 属性资源 end**/
-
// 加载web.xml 中 自定义的 其他初始化内容,这里都没有定义
-
customizeContext(sc, wac);
-
//WebApplicationContext 的刷新
-
wac.refresh();
-
}
---------------------------- environment 获取 begin---------------------------------------------------
ConfigurableWebApplicationContext . getEnvironment 方法为抽象方法;
AbstractApplicationContext . getEnvironment 为方法的实现:
-
public ConfigurableEnvironment getEnvironment() {
-
if (
this.environment ==
null) {
-
this.environment = createEnvironment();
//调用 StandardEnvironment的构造函数
-
}
-
return
this.environment;
-
}
StandardEnvironment 的构造函数会先执行 父类 AbstractEnvironment 的 构造函数:
AbstractEnvironment 构造函数 及 customizePropertySources方法:
-
public AbstractEnvironment() {
-
customizePropertySources(
this.propertySources);
-
if (
this.logger.isDebugEnabled()) {
-
this.logger.debug(String.format(
-
“Initialized %s with PropertySources %s”, getClass().getSimpleName(),
this.propertySources));
-
}
-
}
-
-
protected void customizePropertySources(MutablePropertySources propertySources) {
-
}
Note:父类 中调用 被子类重写(override)的自身方法时,会执行子类的重写方法,而不会执行父类中的方法;如果想要执行父类中的方法,需要明确调用 super.methodName();
所以这里调用 StandardServletEnvironment 中的重写方法:
-
protected void customizePropertySources(MutablePropertySources propertySources) {
-
//添加 key 为 servletConfigInitParams ,value 为 Object 占位符
-
propertySources.addLast(
new StubPropertySource(SERVLET_CONFIG_PROPERTY_SOURCE_NAME));
-
//添加 key 为 servletContextInitParams,value 为 Object 占位符
-
propertySources.addLast(
new StubPropertySource(SERVLET_CONTEXT_PROPERTY_SOURCE_NAME));
-
if (JndiLocatorDelegate.isDefaultJndiEnvironmentAvailable()) {
-
//添加 key 为 jndiProperties,value 为 Object 占位符
-
propertySources.addLast(
new JndiPropertySource(JNDI_PROPERTY_SOURCE_NAME));
-
}
-
super.customizePropertySources(propertySources);
//执行父类 StandardEnvironment 中方法,添加了2 个
-
}
StandardEnvironment 中的重写方法:
-
protected void customizePropertySources(MutablePropertySources propertySources) {
-
//key 为 systemProperties
-
propertySources.addLast(
new MapPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties()));
-
//key 为 systemEnvironment
-
propertySources.addLast(
new SystemEnvironmentPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment()));
-
}
getEnvironment 方法 最终返回 StandardServletEnvironment 实现类,其中的 propertySource 字段(MutablePropertySources 类)中初始化了 5 个 PropertySource(目前前 3 个 source 都是 占位符 object,后期会进行填充和替换);即完成了 Environment 相关实现类的 初始化;
附录2 :StandardEnvironment 顶层父类 UML 图
相关类介绍:
PropertySources 接口 :包含 一个 或者 多个 PropertySource 的对象;即用于 保存;提供了 是否包含 | 获取 property source 的 抽象方法;
MutablePropertySources 类:PropertySources 接口 的实现类,用于 操作 属性资源,并且 提供了可以拷贝 已存在 的 PropertySources 的 构造函数;
PropertySource 抽象类:代表一个 资源 的抽象基类,使用键值对表示;
MapPropertySource:PropertySource 的 实现类,从 Map 对象中读取 键 和 值,即可以通过 Map 对象 构造 PropertySource ;
SystemEnvironmentPopertySource: MapPropertySource 的子类,特殊的 MapPropertySource,用于处理 使用 AbstractEnvironment . getSystemEnvironment 方法 获取到的 系统环境变量;
ServletContextPropertySource:从 一个 ServletContext 对象中 读取 初始化参数,即 通过 ServletContext 对象构造 PropertySource;
ServletConfigPropertySource:类同上;
ConfigurableEnvironment:Environment 类型的 配置接口,提供设置 active profiles 和 default profiles (用于不同的环境开发的不同配置)以及 操作底层属性资源 的 设施;
StandardEnvironment:Environment 的实现类,适合于在标准的场景下使用(如 非 web 场景);
------------------------------------ environment 获取 end---------------------------------------------------
------------------------------------ 初始化 PropertySources begin---------------------------------------------------
ConfigurableWebEnvironment . initPropertySources 为抽象方法;
StandardServletEnvironment . initPropertySources 为方法的实现:
-
public void initPropertySources(ServletContext servletContext, ServletConfig servletConfig) {
-
WebApplicationContextUtils.initServletPropertySources(getPropertySources(), servletContext, servletConfig);
-
}
WebApplicationContextUtils . initServletPropertySources 方法:使用给定的 ServletContext 和 ServletConfig 对象的实例 替换 StubPropertySource 中的相关占位符
-
public static void initServletPropertySources(
-
MutablePropertySources propertySources, ServletContext servletContext, ServletConfig servletConfig) {
-
-
Assert.notNull(propertySources,
“‘propertySources’ must not be null”);
-
// 替换 key 为 servletContextInitParams 的 source 值
-
if (servletContext !=
null && propertySources.contains(StandardServletEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME) &&
-
propertySources.get(StandardServletEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME)
instanceof StubPropertySource) {
-
propertySources.replace(StandardServletEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME,
-
new ServletContextPropertySource(StandardServletEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME, servletContext));
-
}
-
// 替换 key 为 servletConfigInitParams的 source 值
-
if (servletConfig !=
null && propertySources.contains(StandardServletEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME) &&
-
propertySources.get(StandardServletEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME)
instanceof StubPropertySource) {
-
propertySources.replace(StandardServletEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME,
-
new ServletConfigPropertySource(StandardServletEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME, servletConfig));
-
}
-
}
initPropertySources() 方法 在 下面 的 refresh() 方法 中也会调用到 ,这里提前加载 是为了 确保 在 任何 的 后处理 (post-processing)或者 初始化 发生在 refresh() 之前 这两种情况下,Servlet 属性资源 仍然可用;
主要是将 MutablePropertySources 对象中 propertySourceList 列表中保存的和 ServletConfig 和 ServletContext 相关的属性 替换成 当前 环境下 的 ServletContext 和 ServletConfig(此时的 ServletConfig 为 null) ,这样就 顺利的 将 ServletContext 和 ServletConfig 中 保存的 各种资源信息 转移到了 当前 应用上下文中,即 保存在AnnotationConfigWebApplicationContext 对象下的 ConfigurableEnvironment 参数 中;
综上,initPropertySources 方法的目的就是 将 当前的 ServletContext 和 ServletConfig 资源 加载到 WebApplicationContext 的 相关实现类的 environment 属性中;
------------------------------------ 初始化 PropertySources end---------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------
ConfigurableApplicationContext . refresh 方法为抽象方法;
AbstractApplicationContext . refresh : 所有的 ApplicationContext 的唯一实现方法,采用了 模版方法设计模式;
-
public void refresh() throws BeansException, IllegalStateException {
-
synchronized (
this.startupShutdownMonitor) {
-
// 刷新前的准备 工作:涉及属性的设置以及属性资源的 初始化
-
prepareRefresh();
-
-
// 通知子类刷新 内置的 bean 工厂,获得一个新的 bean factory
-
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
-
-
// 配置 工厂的 标准上下文特性,例如 上下文的 ClassLoader 和 post-processors
-
prepareBeanFactory(beanFactory);
-
-
try {
-
//在 应用上下文 子类中 增加 后处理(post-processing) 的 bean 工厂
-
postProcessBeanFactory(beanFactory);
-
-
// 在应用上下文中调用所有 已注册的 BeanFactoryPostProcesser 作为 bean
-
invokeBeanFactoryPostProcessors(beanFactory);
-
-
// 注册具有拦截功能的 bean processors
-
registerBeanPostProcessors(beanFactory);
-
-
// 为应用上下文 初始化 消息 源
-
initMessageSource();
-
-
// 为应用上下文 初始化 事件 多路广播
-
initApplicationEventMulticaster();
-
-
// 初始化其他特殊的 bean
-
onRefresh();
-
-
// 检查 监听器 相关的 bean ,并注册他们
-
registerListeners();
-
-
//实例化所有剩余的单例 bean (非 懒 初始化)
-
finishBeanFactoryInitialization(beanFactory);
-
-
//最后一部:发布 相关的事件
-
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();
-
}
-
}
-
}
相关类介绍:
ConfigurableListableBeanFactory 接口 :ListableBeanFactory,ConfigurableBeanFactory,AutowireCapableBeanFactory 的子接口,
ListableBeanFactory :提供了枚举所有 bean 实例的 方法,而不是提供名称去定向寻找;
ConfigurableBeanFactory:被大多数的 bean 工厂 实现的 配置接口,提供 了用于配置 bean 工厂 的 基础设施;
AutowireCapableBeanFactory: BeanFactory 的直接子接口,是 BeanFactory 的 扩展接口,能够实现自动装配;
刷新工作 所做的 工作比较多 ,下面一个一个分析 :
3.3.1 AbstractApplicationContext . prepareRefresh():为刷新 准备 context;
-
protected void prepareRefresh() {
-
this.startupDate = System.currentTimeMillis();
-
this.closed.set(
false);
//context 是否 已经关闭,false 代表未关闭
-
this.active.set(
true);
// context 当前是否是活跃的,true 代表 活跃
-
-
if (logger.isInfoEnabled()) {
-
-
}
-
-
// Initialize any placeholder property sources in the context environment
-
initPropertySources();
//上面有调用过
-
-
// Validate that all properties marked as required are resolvable
-
// see ConfigurablePropertyResolver#setRequiredProperties
-
getEnvironment().validateRequiredProperties();
//验证资源
-
-
// Allow for the collection of early ApplicationEvents,
-
// to be published once the multicaster is available…
-
this.earlyApplicationEvents =
new LinkedHashSet<ApplicationEvent>();
-
}
AbstractApplicationContext . initPropertySources 方法:空方法,由不同的子类进行不同的实现;这里再次初始化 属性资源方法 ,但是此时 ServletContextPropertySource 已经 成功加入到了 MutablePropertySources 对象的 propertySourceList 列表中;
------------------------------------ property 验证 begin---------------------------------------------------
ConfigurableEnvironment . validateRequiredProperties 为抽象方法;
AbstractEnvironment . validateRequiredProperties 为实现方法:
-
private
final MutablePropertySources propertySources =
new MutablePropertySources(
this.logger);
-
-
private
final ConfigurablePropertyResolver propertyResolver =
-
new PropertySourcesPropertyResolver(
this.propertySources);
-
-
public void validateRequiredProperties() throws MissingRequiredPropertiesException {
-
this.propertyResolver.validateRequiredProperties();
-
}
PopertySourcesPropertyReolver . validateRequiredProperties 方法:
-
public void validateRequiredProperties() {
-
MissingRequiredPropertiesException ex =
new MissingRequiredPropertiesException();
-
for (String key :
this.requiredProperties) {
-
if (
this.getProperty(key) ==
null) {
-
ex.addMissingRequiredProperty(key);
-
}
-
}
-
if (!ex.getMissingRequiredProperties().isEmpty()) {
-
throw ex;
-
}
-
}
------------------------------------ property 验证 end---------------------------------------------------
综上,prepareRefresh()方法用于刷新前打开 AbstractApplicationContext 中的开关字段(close | active)、 environment 资源 的初始化和验证以及初始化 earlyApplicationEvents ;都是准备工作;
3.3.2 AbstractApplicationContext . obtainFreshBeanFactory():返回一个 新的 ConfigurableListableBeanFactory bean 工厂类
-
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
-
/** template method 模式:不同的子类有不同的实现 begin**/
-
refreshBeanFactory();
-
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
// 将上面得到的 bean 工厂返回
-
/** template method 模式:不同的子类有不同的实现 end**/
-
if (logger.isDebugEnabled()) {
-
logger.debug(
"Bean factory for " + getDisplayName() +
": " + beanFactory);
-
}
-
return beanFactory;
-
}
AbstractApplicationContext . refreshBeanFactory 为 抽象方法:使用了 模版方法设计模式,参看【design pattern】Template method(模板方法设计模式) 中的分析;
AbstractRefreshableApplicationContext . refreshBeanFactory 实现:
-
protected final void refreshBeanFactory() throws BeansException {
-
if (hasBeanFactory()) {
-
destroyBeans();
//销毁 bean 工厂管理的所有 bean
-
closeBeanFactory();
//关闭 bean 工厂
-
}
-
/** 重新创建一个 新的 bean 工厂 begin /
-
try {
-
DefaultListableBeanFactory beanFactory = createBeanFactory();
-
beanFactory.setSerializationId(getId());
-
customizeBeanFactory(beanFactory);
-
loadBeanDefinitions(beanFactory);
-
synchronized (
this.beanFactoryMonitor) {
-
this.beanFactory = beanFactory;
//保存创建的 bean 工厂 对象
-
}
-
/ 重新创建一个 新的 bean 工厂 end **/
-
}
-
catch (IOException ex) {
-
throw
new ApplicationContextException(
"I/O error parsing bean definition source for " + getDisplayName(), ex);
-
}
-
}
这里的刷新 bean 工厂 逻辑:如果 beanFactory 属性不为空,则先关闭,然后再构造一个新的 DefaultListableBeanFactory;
------------------------------------ createBeanFactory begin---------------------------------------------------
AbstractRefreshableApplicationContext . createBeanFactory()方法:通过 调用 DefaultListableBeanFactory 构造函数实例化 beanFactory,在调用过程中会调用 其父类 AbstractAutowireCapableBeanFactory 的 无参构造函数,如下:这里配置了需要忽略的依赖接口,保存在其下的 ignoredDependencyInterfaces 字段中
-
public AbstractAutowireCapableBeanFactory() {
-
super();
-
ignoreDependencyInterface(BeanNameAware.class);
//忽略因为自动注入的 依赖接口
-
ignoreDependencyInterface(BeanFactoryAware.class);
-
ignoreDependencyInterface(BeanClassLoaderAware.class);
-
}
-
-
public void ignoreDependencyInterface(Class<?> ifc) {
-
this.ignoredDependencyInterfaces.add(ifc);
-
}
创建 DefaultListableBeanFactory 过程中 配置了 ignoredDependencyInterfaces 属性(增加3个);
------------------------------------ createBeanFactory end---------------------------------------------------
------------------------------------ customizeBeanFactory begin---------------------------------------------------
-
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
-
if (
this.allowBeanDefinitionOverriding !=
null) {
-
beanFactory.setAllowBeanDefinitionOverriding(
this.allowBeanDefinitionOverriding);
-
}
-
if (
this.allowCircularReferences !=
null) {
-
beanFactory.setAllowCircularReferences(
this.allowCircularReferences);
-
}
-
}
用于将 ApplicationContext 中的 部分属性信息 传递给 刚初始化的 beanFactory ;
------------------------------------ customizeBeanFactory end---------------------------------------------------
------------------------------------ loadBeanDefinitions begin---------------------------------------------------
AbstractRefreshableApplicationContext . loadBeanDefinitions 为 抽象方法 ;
AnnotationConfigWebApplicationContext . loadBeanDefinitions 实现方法(不同的子类有不同的实现方法):
-
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) {
-
// 通过 bean 工厂实例化 bean 定义的 reader,并在bean 工厂中注册 相关 的 注解的 post processors
-
AnnotatedBeanDefinitionReader reader = getAnnotatedBeanDefinitionReader(beanFactory);
-
//通过 bean 工厂实例化 bean 定义的扫描器
-
ClassPathBeanDefinitionScanner scanner = getClassPathBeanDefinitionScanner(beanFactory);
-
//返回当前类持有的 bean 名称生成器,此时为null
-
BeanNameGenerator beanNameGenerator = getBeanNameGenerator();
-
if (beanNameGenerator !=
null) {
-
reader.setBeanNameGenerator(beanNameGenerator);
-
scanner.setBeanNameGenerator(beanNameGenerator);
-
beanFactory.registerSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR, beanNameGenerator);
-
}
-
// 返回当前类持有的 bean 定义 范围解析器,此时为 null
-
ScopeMetadataResolver scopeMetadataResolver = getScopeMetadataResolver();
-
if (scopeMetadataResolver !=
null) {
-
reader.setScopeMetadataResolver(scopeMetadataResolver);
-
scanner.setScopeMetadataResolver(scopeMetadataResolver);
-
}
-
-
if (!
this.annotatedClasses.isEmpty()) {
-
if (logger.isInfoEnabled()) {
-
logger.info(
“Registering annotated classes: [” +
-
StringUtils.collectionToCommaDelimitedString(
this.annotatedClasses) +
“]”);
-
}
-
reader.register(
this.annotatedClasses.toArray(
new Class<?>[
this.annotatedClasses.size()]));
-
}
-
-
if (!
this.basePackages.isEmpty()) {
-
if (logger.isInfoEnabled()) {
-
logger.info(
“Scanning base packages: [” +
-
StringUtils.collectionToCommaDelimitedString(
this.basePackages) +
“]”);
-
}
-
scanner.scan(
this.basePackages.toArray(
new String[
this.basePackages.size()]));
-
}
-
// web.xml 中配置的配置文件路径,spring 配置文件和 数据库配置文件,编程式的配置
-
String[] configLocations = getConfigLocations();
-
if (configLocations !=
null) {
-
for (String configLocation : configLocations) {
-
try {
-
//获取每个 java 文件的 Class 对象,并利用 reader 注册
-
Class<?> clazz = getClassLoader().loadClass(configLocation);
-
if (logger.isInfoEnabled()) {
-
-
}
-
reader.register(clazz);
-
}
-
catch (ClassNotFoundException ex) {
-
if (logger.isDebugEnabled()) {
-
logger.debug(
“Could not load class for config location [” + configLocation +
-
"] - trying package scan. " + ex);
-
}
-
int count = scanner.scan(configLocation);
-
if (logger.isInfoEnabled()) {
-
if (count ==
0) {
-
-
}
-
else {
-
-
}
-
}
-
}
-
}
-
}
-
}
相关类介绍:
AnnotatedBeanDefinitionReader : 用于 编程式注册 已注解 bean 的 方便适配器,需要提供 BeanDefinitionRegistry 类 构造对象,注册的是 BeanDefinitionRegisty 中 的 beanDefinition;该类 是 ClassPathBeanDefininationScanner 的 一个替代品,使用 相同的 注解策略但是只显示的注册类;
ClassPathBeanDefininationScanner : 一个 bean 定义的 扫描器 ,用于检查 classpath 下 符合条件的bean ,使用给定的记录器 BeanFactory 或者 ApplicationContext 注册 相关的 bean 定义;符合条件的 类 是 通过 配置 类型过滤器来侦测的,默认的过滤器包括 注解了 Spring 的 Component,Repository,Service,Controller 的 类,而且也支持 Java EE 6 的 ManagedBean 注解 和 JSR-330 的 Named 注解;
------------------------- 第 1 层 --------------------------
AnnotationConfigWebApplicationContext . getAnnotatedBeanDefinitionReader 方法:
-
protected AnnotatedBeanDefinitionReader getAnnotatedBeanDefinitionReader(DefaultListableBeanFactory beanFactory) {
-
return
new AnnotatedBeanDefinitionReader(beanFactory, getEnvironment());
-
}
------------------------- 第 2 层 --------------------------
调用如下的构造函数:
-
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
-
Assert.notNull(registry,
“BeanDefinitionRegistry must not be null”);
-
Assert.notNull(environment,
“Environment must not be null”);
-
this.registry = registry;
-
this.conditionEvaluator =
new ConditionEvaluator(registry, environment,
null);
-
AnnotationConfigUtils.registerAnnotationConfigProcessors(
this.registry);
//注册相关处理器
-
}
相关类:
BeanDefinitionRegistry : 处理 BeanDefinition 的接口,包括注册,移除,获取,判断是否包含等操作,例如处理 RootBeanDefinition 和 ChildBeanDefinition; Spring 的 BeanDefinitionReader 需要 通过 该接口的 实现类 来构造,在 Spring core 中 已知的实现者 是 DefaultListableBeanFactory 和 GenericApplicationContext ;
------------------------- 第 3 层 --------------------------
AnnotationConfigUtils . registerAnnotationConfigProcessors() 方法:注册 registry 中 所有相关的 注解 后 处理器(post processors)
-
public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
-
registerAnnotationConfigProcessors(registry,
null);
-
}
------------------------- 第 4 层 --------------------------
AnnotationConfigUtils . registerAnnotationConfigProcessors 重载(overload)方法:
-
public
static
final AnnotationAwareOrderComparator INSTANCE =
new AnnotationAwareOrderComparator();
-
-
-
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
-
BeanDefinitionRegistry registry, Object source) {
-
// DefaultListableBeanFacotry 为 BeanDefinitionRegistry 的子类,向下转型,转为 DefaultListableBeanFactory
-
DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
-
if (beanFactory !=
null) {
-
if (!(beanFactory.getDependencyComparator()
instanceof AnnotationAwareOrderComparator)) {
-
// 设置bean 工厂的 dependencyComparator 属性,对依赖的列表和数组提供可选的排序
-
beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
-
}
-
if (!(beanFactory.getAutowireCandidateResolver()
instanceof ContextAnnotationAutowireCandidateResolver)) {
-
// 设置 bean 工厂的 autowireCandidateResolver 属性,用来检查 一个 bean 定义是否需要自动注入 的 解析器
-
beanFactory.setAutowireCandidateResolver(
new ContextAnnotationAutowireCandidateResolver());
-
}
-
}
-
-
Set<BeanDefinitionHolder> beanDefs =
new LinkedHashSet<BeanDefinitionHolder>(
4);
-
// bean 工厂的 beanDefinitionMap 字段中是否包含bean 定义:
-
-
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
-
RootBeanDefinition def =
new RootBeanDefinition(ConfigurationClassPostProcessor.class);
-
def.setSource(source);
-
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
-
}
-
//是否包含 org.springframework.context.annotation.internalAutowiredAnnotationProcessor
-
if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
-
RootBeanDefinition def =
new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
-
def.setSource(source);
-
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
-
}
-
//是否包含 org.springframework.context.annotation.internalRequiredAnnotationProcessor,不包含则注册
-
if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
-
RootBeanDefinition def =
new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
-
def.setSource(source);
-
beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
-
}
-
//是否包含 org.springframework.context.annotation.internalCommonAnnotationProcessor
-
// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
-
if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
-
RootBeanDefinition def =
new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
-
def.setSource(source);
-
beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
-
}
-
//是否包含 org.springframework.context.annotation.internalPersistenceAnnotationProcessor
-
// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
-
if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
-
RootBeanDefinition def =
new RootBeanDefinition();
-
try {
-
def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
-
AnnotationConfigUtils.class.getClassLoader()));
-
}
-
catch (ClassNotFoundException ex) {
-
throw
new IllegalStateException(
-
"Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
-
}
-
def.setSource(source);
-
beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
-
}
-
//是否包含 org.springframework.context.event.internalEventListenerProcessor
-
if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
-
RootBeanDefinition def =
new RootBeanDefinition(EventListenerMethodProcessor.class);
-
def.setSource(source);
-
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
-
}
-
-
if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
-
RootBeanDefinition def =
new RootBeanDefinition(DefaultEventListenerFactory.class);
-
def.setSource(source);
-
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
-
}
-
-
return beanDefs;
-
}
注解处理器详情:
org.springframework.context.annotation.internalConfigurationAnnotationProcessor : 内部管理 Configuration 注解处理器 的 bean 的 名称;即ConfigurationClassPostProcessor类;
org.springframework.context.annotation.internalAutowiredAnnotationProcessor:内部管理 Autowired 注解处理器 的 bean 的名称;即AutowiredAnnotationBeanPostProcessor 类;
org.springframework.context.annotation.internalRequiredAnnotationProcessor:内部管理 Required 注解处理器 的 bean 的名称;即RequiredAnnotationBeanPostProcessor
类;
org.springframework.context.annotation.internalCommonAnnotationProcessor:内部管理 JSR-250 注解处理器 的 bean 的名称;即CommonAnnotationBeanPostProcessor 类;
org.springframework.context.annotation.internalPersistenceAnnotationProcessor:内部管理 JPA 注解处理器 的 bean 的名称 , 没有使用 JPA类库,不会加载;即PersistenceAnnotationBeanPostProcessor类;
org.springframework.context.event.internalEventListenerProcessor:内部管理 @EventListener 注解 处理器 的 bean 的名称;即EventListenerMethodProcessor类;
org.springframework.context.event.internalEventListenerFactory:内部管理 EventListenerFactory 的 bean 的名称;即DefaultEventListenerFactory类;
相关类介绍:
DefualtListableBeanFactory: AbstractAutowireCapbleBeanFactory ,ConfigurableListableBeanFactory,BeanDefinitionRegistry 的实现类;一个 基于 bean 定义对象 的完全成熟的 bean 工厂;通常的使用方法是:首先 注册所有 的 beanDefinition(可能从 bean 定义 文件中 读取),
BeanDefinition 接口:一个 BeanDefinition 描述了一个 bean 的实例,包括 属性值,构造函数参数值,以及 更多的 信息
AnnotatedBeanDefinition:BeanDefinition 的抽象类;提供 AnnotationMetadata 类 的 获取方法,不需要保证类已经加载;
AbstractBeanDefinition:BeanDefinition 的抽象类
RootBeanDefinition 实现类: 支持通过 类的 Class 对象 创建 bean 定义,适用于注册 单独的 bean 定义;
GenericBeanDefinition 实现类:在 父 接口的基础上 增加 了 parentName 参数 ;通常情况下使用该类 注册 bean ,可以灵活的配置 父 名称;
AnnotatedGenericBeanDefinition:实现了 AnnotatedBeanDefinition ,继承了 GenericBeanDefinition,GenericBeanDefiniton 类的扩展,通过 AnnotatedBeanDefinition 接口 增加对 给定注解元数据的支持,通过 Class 数组 或者 AnnotationMetadata 或者 MethodMetadata 构造;
BeanDefinitionHolder 类: BeanMetadataElement 的实现类,持有 一个 包含了 名称 和 别名(aliases)的 BeanDefinition,可以注册为一个 内部 bean 的占位符;
AnnotationMetadata:定义 对指定类注解的 访问 ;可以在类未加载的时候访问;
Comparator:jdk 的 用于比较功能的类;
OrderComparator :spring 中 对 Comparator 的实现,用于对象的排序
AnnotationAwareOrderComparator:是 OrderComparator 的一个扩展,支持 Spring 的 Ordered 接口 以及 @Order 注解 和 @Priority 注解
AutowireCandidateResolver:决定 一个 bean 定义 是否需要 自动注入 的 策略接口;
ContextAnnotationAutowireCandidateResolver:实现了 AutowireCandidateResolver,支持 注解 和 @Lazy 的 惰性 注解方法;------------------------- 第 5 层 --------------------------
AnnotationConfigUtils . registerPostProcessor()方法:注册 后处理器, 返回 BeanDefinitionHolder 对象
-
private static BeanDefinitionHolder registerPostProcessor(
-
BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {
-
-
definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
-
registry.registerBeanDefinition(beanName, definition);
-
return
new BeanDefinitionHolder(definition, beanName);
-
}
------------------------- 第 6 层 --------------------------
BeanDefinitionRegistry . registerBeanDefinition()抽象方法
DefaultListableBeanFactory . registerBeanDefinition实现方法:向 bean 工厂中注册 bean 的 定义;实际上是以键值对的形式添加到 beanDefinitionMap 的字段中,同时维护 beanDefinitonName 字段 和 manualSinglethonNames;
-
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
-
throws BeanDefinitionStoreException {
-
-
Assert.hasText(beanName,
“Bean name must not be empty”);
-
Assert.notNull(beanDefinition,
“BeanDefinition must not be null”);
-
-
if (beanDefinition
instanceof AbstractBeanDefinition) {
-
try {
-
((AbstractBeanDefinition) beanDefinition).validate();
//验证 bean 定义
-
}
-
catch (BeanDefinitionValidationException ex) {
-
throw
new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
-
“Validation of bean definition failed”, ex);
-
}
-
}
-
-
BeanDefinition oldBeanDefinition;
-
// 检查该 beanDefinition 是否已经存在
-
oldBeanDefinition =
this.beanDefinitionMap.get(beanName);
-
if (oldBeanDefinition !=
null) {
-
if (!isAllowBeanDefinitionOverriding()) {
-
throw
new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
-
“Cannot register bean definition [” + beanDefinition +
“] for bean '” + beanName +
-
“’: There is already [” + oldBeanDefinition +
“] bound.”);
-
}
-
else
if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
-
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
-
if (
this.logger.isWarnEnabled()) {
-
this.logger.warn(
“Overriding user-defined bean definition for bean '” + beanName +
-
“’ with a framework-generated bean definition: replacing [” +
-
oldBeanDefinition +
“] with [” + beanDefinition +
“]”);
-
}
-
}
-
else
if (!beanDefinition.equals(oldBeanDefinition)) {
-
if (
this.logger.isInfoEnabled()) {
-
this.logger.info(
“Overriding bean definition for bean '” + beanName +
-
“’ with a different definition: replacing [” + oldBeanDefinition +
-
“] with [” + beanDefinition +
“]”);
-
}
-
}
-
else {
-
if (
this.logger.isDebugEnabled()) {
-
this.logger.debug(
“Overriding bean definition for bean '” + beanName +
-
“’ with an equivalent definition: replacing [” + oldBeanDefinition +
-
“] with [” + beanDefinition +
“]”);
-
}
-
}
-
this.beanDefinitionMap.put(beanName, beanDefinition);
-
}
-
else {
-
// 工厂的 bean创建阶段是否已经开始
-
if (hasBeanCreationStarted()) {
-
// Cannot modify startup-time collection elements anymore (for stable iteration)
-
synchronized (
this.beanDefinitionMap) {
-
this.beanDefinitionMap.put(beanName, beanDefinition);
-
List<String> updatedDefinitions =
new ArrayList<String>(
this.beanDefinitionNames.size() +
1);
-
updatedDefinitions.addAll(
this.beanDefinitionNames);
-
updatedDefinitions.add(beanName);
-
this.beanDefinitionNames = updatedDefinitions;
-
if (
this.manualSingletonNames.contains(beanName)) {
-
Set<String> updatedSingletons =
new LinkedHashSet<String>(
this.manualSingletonNames);
-
updatedSingletons.remove(beanName);
-
this.manualSingletonNames = updatedSingletons;
-
}
-
}
-
}
-
//仍然处于 启动注册阶段
-
else {
-
// Still in startup registration phase
-
this.beanDefinitionMap.put(beanName, beanDefinition);
-
this.beanDefinitionNames.add(beanName);
-
this.manualSingletonNames.remove(beanName);
-
}
-
this.frozenBeanDefinitionNames =
null;
-
}
-
-
if (oldBeanDefinition !=
null || containsSingleton(beanName)) {
-
//重置所有 beanName 相关 bean definition 缓存
-
resetBeanDefinition(beanName);
-
}
-
}
DefaultListableBeanFactory 中字段介绍:
beanDefinitionMap: bean 定义 对象的 Map 集合,通过 bean 名称 键入;
beanDefinitionNames:bean 定义 名称的 list 集合,
manualSingletonNames:手动注册的单例的名称的 list 集合;
附录3 :DefualtListableBeanFactory 上层关系图
------------------------- 第 1 层 --------------------------
ClassPathBeanDefinitionScanner 实例化,其内部调用 ClassPathBeanDefinitionScanner 的构造器 ,同时调用了父类 ClassPathScanningCandidateComponentProvider 的构造器,如下:
-
protected ClassPathBeanDefinitionScanner getClassPathBeanDefinitionScanner(DefaultListableBeanFactory beanFactory) {
-
return
new ClassPathBeanDefinitionScanner(beanFactory,
true, getEnvironment());
-
}
------------------------- 第 2 层 --------------------------
-
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters, Environment environment) {
-
super(useDefaultFilters, environment);
-
-
Assert.notNull(registry,
“BeanDefinitionRegistry must not be null”);
-
this.registry = registry;
-
-
// Determine ResourceLoader to use.
-
if (
this.registry
instanceof ResourceLoader) {
-
setResourceLoader((ResourceLoader)
this.registry);
-
}
-
}
------------------------- 第 3 层 --------------------------
-
public ClassPathScanningCandidateComponentProvider(boolean useDefaultFilters, Environment environment) {
-
if (useDefaultFilters) {
-
registerDefaultFilters();
//注册过滤器
-
}
-
Assert.notNull(environment,
“Environment must not be null”);
-
this.environment = environment;
-
}
------------------------- 第 4 层 --------------------------
其中的 registerDefaultFilters() 方法:注册默认的过滤器
-
protected void registerDefaultFilters() {
-
// 为 @Component注解注册 默认过滤器 ,这将隐式的注解所有包含 Component 元注解的注解
-
//包括 Repository 注解, Service注解,Controller注解
-
this.includeFilters.add(
new AnnotationTypeFilter(Component.class));
-
ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
-
try {
-
//如果项目中加载了相关 jar 包,则会为 JSR-250 注册过滤器
-
this.includeFilters.add(
new AnnotationTypeFilter(
-
((Class<? extends Annotation>) ClassUtils.forName(
“javax.annotation.ManagedBean”, cl)),
false));
-
logger.debug(
“JSR-250 ‘javax.annotation.ManagedBean’ found and supported for component scanning”);
-
}
-
catch (ClassNotFoundException ex) {
-
// JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.
-
}
-
try {
-
//如果项目中加载了相关 jar 包,则会为 JSR-330 注册过滤器
-
this.includeFilters.add(
new AnnotationTypeFilter(
-
((Class<? extends Annotation>) ClassUtils.forName(
“javax.inject.Named”, cl)),
false));
-
logger.debug(
“JSR-330 ‘javax.inject.Named’ annotation found and supported for component scanning”);
-
}
-
catch (ClassNotFoundException ex) {
-
// JSR-330 API not available - simply skip.
-
}
-
}
AnnotationTypeFilter 类:TypeFilter 的间接实现类,作用是 使用 给定的注解 匹配 类 的 简单 过滤器,也会 检查 通过 继承得到的注解;通过 给定的注解的类型 实例化;
综上,ClassPathBeanDefinitionScanner 实例化的内部 一定会注册一个 过滤 @Component 注解的 AnnotationTypeFilter,尝试注册 过滤 JSR-250 注解(ManagedBean)的 AnnotationTypeFilter 和 JSR-330 注解(Named)的 AnnotationTypeFilter;说白了就是 配置 beanFactory 的 includeFilters 字段;返回的 scanner 内置了 registry 和 environment
------------------------- 第 1 层 --------------------------
BeanNameGenerator 实例化:返回自定义的 BeanNameGenerator,此处为 null;给 AnnotatedBeanDefinitionReader 类 和 ClassPathBeanDefinitionScanner 类 使用
-
protected BeanNameGenerator getBeanNameGenerator() {
-
return
this.beanNameGenerator;
-
}
BeanNameGenerator : 为 bean 定义 生成 bean 名称的 策略 接口,初始化时获取为空
------------------------- 第 1 层 --------------------------
DefaultListableBeanFactory . registerSingleton 方法:向 beanFactory 中 添加 手动注册的单例,维护 beanFactory 的 manualSingletonNames ,singletonObjects,singletonFactories,earlySingletonObjects,registeredSingletons 字段;
-
public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
-
super.registerSingleton(beanName, singletonObject);
-
-
if (hasBeanCreationStarted()) {
-
// Cannot modify startup-time collection elements anymore (for stable iteration)
-
synchronized (
this.beanDefinitionMap) {
-
if (!
this.beanDefinitionMap.containsKey(beanName)) {
-
Set<String> updatedSingletons =
new LinkedHashSet<String>(
this.manualSingletonNames.size() +
1);
-
updatedSingletons.addAll(
this.manualSingletonNames);
-
updatedSingletons.add(beanName);
-
this.manualSingletonNames = updatedSingletons;
-
}
-
}
-
}
-
else {
-
// Still in startup registration phase
-
if (!
this.beanDefinitionMap.containsKey(beanName)) {
-
this.manualSingletonNames.add(beanName);
-
}
-
}
-
-
clearByTypeCache();
-
}
super . registerSingleton 方法 是 DefaultSingletonBeanRegistry . registerSingleton 方法:
-
public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
-
Assert.notNull(beanName,
“‘beanName’ must not be null”);
-
synchronized (
this.singletonObjects) {
-
Object oldObject =
this.singletonObjects.get(beanName);
-
if (oldObject !=
null) {
-
throw
new IllegalStateException(
“Could not register object [” + singletonObject +
-
“] under bean name '” + beanName +
“’: there is already object [” + oldObject +
“] bound”);
-
}
-
addSingleton(beanName, singletonObject);
-
}
-
}
-
// 维护了 beanFactory 中的多个字段
-
protected void addSingleton(String beanName, Object singletonObject) {
-
synchronized (
this.singletonObjects) {
-
this.singletonObjects.put(beanName, (singletonObject !=
null ? singletonObject : NULL_OBJECT));
-
this.singletonFactories.remove(beanName);
-
this.earlySingletonObjects.remove(beanName);
-
this.registeredSingletons.add(beanName);
-
}
-
}
------------------------- 第 1层 --------------------------
ScopeMetadataResolver 实例化:返回自定义的 ScopeMetadataResolver 类,此时为 null,给 AnnotatedBeanDefinitionReader 类 和 ClassPathBeanDefinitionScanner 类使用;
-
protected ScopeMetadataResolver getScopeMetadataResolver() {
-
return
this.scopeMetadataResolver;
-
}
ScopeMetadataResolver: 为 bean 定义 解析 范围 的 策略接口
------------------------- 第 1 层 --------------------------
AnnotatedBeanDefinitionReader . register 方法
-
public void register(Class<?>… annotatedClasses) {
-
for (Class<?> annotatedClass : annotatedClasses) {
-
registerBean(annotatedClass);
-
}
-
}
-
-
public void registerBean(Class<?> annotatedClass) {
-
registerBean(annotatedClass,
null, (Class<? extends Annotation>[])
null);
-
}
-
-
public void registerBean(Class<?> annotatedClass, String name, Class<? extends Annotation>… qualifiers) {
-
AnnotatedGenericBeanDefinition abd =
new AnnotatedGenericBeanDefinition(annotatedClass);
-
if (
this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
-
return;
-
}
-
-
ScopeMetadata scopeMetadata =
this.scopeMetadataResolver.resolveScopeMetadata(abd);
-
abd.setScope(scopeMetadata.getScopeName());
-
String beanName = (name !=
null ? name :
this.beanNameGenerator.generateBeanName(abd,
this.registry));
-
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
-
if (qualifiers !=
null) {
-
for (Class<? extends Annotation> qualifier : qualifiers) {
-
if (Primary.class == qualifier) {
-
abd.setPrimary(
true);
-
}
-
else
if (Lazy.class == qualifier) {
-
abd.setLazyInit(
true);
-
}
-
else {
-
abd.addQualifier(
new AutowireCandidateQualifier(qualifier));
-
}
-
}
-
}
-
-
BeanDefinitionHolder definitionHolder =
new BeanDefinitionHolder(abd, beanName);
-
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder,
this.registry);
-
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder,
this.registry);
-
}
相关类介绍:
ScopeMetadata:描述 Spring 管理 的 bean 的 作用域,包括 作用域的 名称 和 代理作用域的行为,默认的作用域为 singleton,默认 的代理作用域是 不代理;
AnnotationMetadata:接口,定义 对指定类注解的 访问 ;可以在类未加载的时候访问;
StandardAnnotationMetadata:实现类,使用标准的反射反射一个 给定的类;
ScopeMetadataResolver:解析 bean 定义 的 作用域 的策略接口;
ScopedProxyMode:各种 代理作用域的值 的 枚举 :
default : default 通常 等于 no ,除非 配置了不同的 default
no : 不创建 作用域代理
interfaces:创建 JDK 动态代理
target_class:创建 基于 一个类的 代理(使用 CGLIB)
------------------------- 第 2 层 --------------------------
AnnotatedGenericBeanDefinition 实例化:
-
public AnnotatedGenericBeanDefinition(Class<?> beanClass) {
-
setBeanClass(beanClass);
-
this.metadata =
new StandardAnnotationMetadata(beanClass,
true);
-
}
------------------------- 第 3 层 --------------------------
StandardAnnotationMetadata 实例化:初始化 字段信息;
-
public StandardAnnotationMetadata(Class<?> introspectedClass, boolean nestedAnnotationsAsMap) {
-
super(introspectedClass);
-
this.annotations = introspectedClass.getAnnotations();
//获得类上的注解
-
this.nestedAnnotationsAsMap = nestedAnnotationsAsMap;
-
}
------------------------- 第 2 层 --------------------------
AnnotationScopeMetadataResolver . resolveScopeMetadata 方法
-
public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) {
-
ScopeMetadata metadata =
new ScopeMetadata();
-
if (definition
instanceof AnnotatedBeanDefinition) {
-
AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition;
-
AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(
-
annDef.getMetadata(),
this.scopeAnnotationType);
-
if (attributes !=
null) {
-
metadata.setScopeName(attributes.getString(
“value”));
-
ScopedProxyMode proxyMode = attributes.getEnum(
“proxyMode”);
-
if (proxyMode ==
null || proxyMode == ScopedProxyMode.DEFAULT) {
-
proxyMode =
this.defaultProxyMode;
-
}
-
metadata.setScopedProxyMode(proxyMode);
-
}
-
}
-
return metadata;
-
}
------------------------- 第 2 层 --------------------------
AnnotationBeanNameGenerator . generateBeanName 方法:返回 contextConfigLocation 配置的 bean 的 名称
-
public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
-
if (definition
instanceof AnnotatedBeanDefinition) {
-
String beanName = determineBeanNameFromAnnotation((AnnotatedBeanDefinition) definition);
-
if (StringUtils.hasText(beanName)) {
-
// Explicit bean name found.
-
return beanName;
-
}
-
}
-
// Fallback: generate a unique default bean name.
-
return buildDefaultBeanName(definition, registry);
-
}
-
-
protected String determineBeanNameFromAnnotation(AnnotatedBeanDefinition annotatedDef) {
-
AnnotationMetadata amd = annotatedDef.getMetadata();
-
Set<String> types = amd.getAnnotationTypes();
-
String beanName =
null;
-
for (String type : types) {
-
AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(amd, type);
-
if (isStereotypeWithNameValue(type, amd.getMetaAnnotationTypes(type), attributes)) {
-
Object value = attributes.get(
“value”);
-
if (value
instanceof String) {
-
String strVal = (String) value;
-
if (StringUtils.hasLength(strVal)) {
-
if (beanName !=
null && !strVal.equals(beanName)) {
-
throw
new IllegalStateException(
"Stereotype annotations suggest inconsistent " +
-
“component names: '” + beanName +
“’ versus '” + strVal +
“’”);
-
}
-
beanName = strVal;
-
}
-
}
-
}
-
}
-
return beanName;
-
}
-
-
protected String buildDefaultBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
-
return buildDefaultBeanName(definition);
-
}
-
-
-
-
protected String buildDefaultBeanName(BeanDefinition definition) {
-
String shortClassName = ClassUtils.getShortName(definition.getBeanClassName());
-
return Introspector.decapitalize(shortClassName);
-
}
------------------------- 第3层 --------------------------
StandardAnnotationMetadata . getAnnotationTypes 方法:遍历 annotations 字段,获取所有的注解名字的 set 集合;
-
public Set<String> getAnnotationTypes() {
-
Set<String> types =
new LinkedHashSet<String>();
-
for (Annotation ann :
this.annotations) {
-
types.add(ann.annotationType().getName());
-
}
-
return types;
-
}
------------------------- 第 2 层 --------------------------
AnnotationConfigUtils . applyScopedProxyMode 方法:
-
static BeanDefinitionHolder applyScopedProxyMode(
-
ScopeMetadata metadata, BeanDefinitionHolder definition, BeanDefinitionRegistry registry) {
-
-
ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode();
-
-
return definition;
-
}
-
boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS);
-
return ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass);
// 使用代理
-
}
------------------------- 第 3 层 --------------------------
若使用代理, ScopedProxyCreater . createScopeProxy :
-
public static BeanDefinitionHolder createScopedProxy(
-
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry, boolean proxyTargetClass) {
-
-
return ScopedProxyUtils.createScopedProxy(definitionHolder, registry, proxyTargetClass);
-
}
------------------------- 第 4 层 --------------------------
ScopeProxyUtils . createScopedProxy:
-
public static BeanDefinitionHolder createScopedProxy(BeanDefinitionHolder definition,
-
BeanDefinitionRegistry registry, boolean proxyTargetClass) {
-
-
String originalBeanName = definition.getBeanName();
-
BeanDefinition targetDefinition = definition.getBeanDefinition();
-
String targetBeanName = getTargetBeanName(originalBeanName);
-
-
// Create a scoped proxy definition for the original bean name,
-
// “hiding” the target bean in an internal target definition.
-
RootBeanDefinition proxyDefinition =
new RootBeanDefinition(ScopedProxyFactoryBean.class);
-
proxyDefinition.setDecoratedDefinition(
new BeanDefinitionHolder(targetDefinition, targetBeanName));
-
proxyDefinition.setOriginatingBeanDefinition(targetDefinition);
-
proxyDefinition.setSource(definition.getSource());
-
proxyDefinition.setRole(targetDefinition.getRole());
-
-
proxyDefinition.getPropertyValues().add(
“targetBeanName”, targetBeanName);
-
if (proxyTargetClass) {
-
targetDefinition.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
-
// ScopedProxyFactoryBean’s "
源码环境 : idea + spring 4.3.4 +tomcat7 + gradle
附 : 基于 java 注解的 配置元数据 的 web.xml 配置做参考(spring 3.0 后支持)
<code class="language-html