【spring】源码分析 一 从ContextLoaderListener开始·

https://blog.csdn.net/lihuapiao/article/details/51919283

源码环境 : idea + spring 4.3.4 +tomcat7 + gradle

附 : 基于 java  注解的 配置元数据 的 web.xml 配置做参考(spring 3.0 后支持)


   
   
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
  3. xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation= "http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
  5. version= "3.1">
  6. <listener>
  7. <listener-class>org.springframework.web.context.ContextLoaderListener </listener-class>
  8. </listener>
  9. <context-param>
  10. <param-name>contextClass </param-name>
  11. <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext </param-value>
  12. </context-param>
  13. <context-param>
  14. <param-name>contextConfigLocation </param-name>
  15. <param-value>
  16. com.ycit.config.DataSourceConfig,
  17. com.ycit.config.AppConfig
  18. </param-value>
  19. </context-param>
  20. <servlet>
  21. <servlet-name>solutionServlet </servlet-name>
  22. <servlet-class>org.springframework.web.servlet.DispatcherServlet </servlet-class>
  23. <init-param>
  24. <param-name>contextClass </param-name>
  25. <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext </param-value>
  26. </init-param>
  27. <init-param>
  28. <param-name>contextConfigLocation </param-name>
  29. <param-value>com.ycit.config.MvcConfig </param-value>
  30. </init-param>
  31. </servlet>
  32. <servlet-mapping>
  33. <servlet-name>solutionServlet </servlet-name>
  34. <url-pattern>/ </url-pattern>
  35. </servlet-mapping>
  36. <!-- 开启 druid 监控-->
  37. <servlet>
  38. <servlet-name>DruidStatView </servlet-name>
  39. <servlet-class>com.alibaba.druid.support.http.StatViewServlet </servlet-class>
  40. </servlet>
  41. <servlet-mapping>
  42. <servlet-name>DruidStatView </servlet-name>
  43. <url-pattern>/druid/* </url-pattern>
  44. </servlet-mapping>
  45. </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),分别保存在如下两个私有字段中:


   
   
  1. /**
  2. * The 'current' WebApplicationContext, if the ContextLoader class is
  3. * deployed in the web app ClassLoader itself.
  4. * volatile 为 多线程中用到的 关键字 ,作用是 保持被修饰的字段在被读取的时候返回的都是当前最新的,
  5. */
  6. private static volatile WebApplicationContext currentContext;
  7. /**
  8. * The root WebApplicationContext instance that this loader manages.
  9. */
  10. private WebApplicationContext context; // 保存初始化的ApplicationContext 实现类,可用于 ServletContext 消亡时 ApplicationContext关闭并释放资源


currentContext 是指 当前 的 WebApplicationContext;

context 是指 每个 ServletContext 对应的那个 WebApplicationContext;

                           注 :  维基百科对 java 中的  volatile 介绍如下 : 
  

Java支持volatile关键字,但它被用于其他不同的用途。当volatile用于一个作用域时,Java保证如下:

1.(适用于Java所有版本)读和写一个volatile变量有全局的排序。也就是说每个线程访问一个volatile作用域时会在继续执行之前读取它的当前值,而不是(可能)使用一个缓存的值。(但是并不保证经常读写volatile作用域时读和写的相对顺序,也就是说通常这并不是有用的线程构建)。
2.(适用于Java5及其之后的版本)volatile的读和写建立了一个happens-before关系,类似于申请和释放一个互斥锁。
使用volatile会比使用锁更快,但是在一些情况下它不能工作。volatile使用范围在Java5中得到了扩展,特别是双重检查锁定现在能够正确工作。

3 . 源码分析

 初始化源码分析

ContextLoader . initWebApplicationContext ()主代码:最终返回 一个 WebApplicationContext 的相关实现类;


 
 
  1. // Store context in local instance variable, to guarantee that
  2. // it is available on ServletContext shutdown.
  3. /创建相应的 WebApplicationContext 实例 begin/
  4. if ( this.context == null) {
  5. this.context = createWebApplicationContext(servletContext);
  6. }
  7. /创建相应的 WebApplicationContext 实例 end/
  8. /设置 parent context属性,对于多个 root WebApplicationContext 可以共享,对于单个的不需要关心parent context/
  9. if ( this.context instanceof ConfigurableWebApplicationContext) {
  10. ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context;
  11. if (!cwac.isActive()) {
  12. // The context has not yet been refreshed -> provide services such as
  13. // setting the parent context, setting the application context id, etc
  14. if (cwac.getParent() == null) {
  15. // The context instance was injected without an explicit parent ->
  16. // determine parent for root web application context, if any.
  17. ApplicationContext parent = loadParentContext(servletContext);
  18. cwac.setParent(parent);
  19. }
  20. /设置 parent context 属性 end/
  21. // 配置 并且刷新 WebApplicationContext,此处比较复杂
  22. configureAndRefreshWebApplicationContext(cwac, servletContext);
  23. }
  24. }
  25. //注册 context
  26. servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
  27. /保存当前的应用上下文 begin/
  28. ClassLoader ccl = Thread.currentThread().getContextClassLoader();
  29. if (ccl == ContextLoader.class.getClassLoader()) {
  30. currentContext = this.context;
  31. }
  32. else if (ccl != null) {
  33. currentContextPerThread.put(ccl, this.context);
  34. }
  35. /保存当前的应用上下文 end/
  36. 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 实现类



 
 
  1. protected WebApplicationContext createWebApplicationContext(ServletContext sc) {
  2. Class<?> contextClass = determineContextClass(sc);
  3. if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {
  4. throw new ApplicationContextException( “Custom context class [” + contextClass.getName() +
  5. “] is not of type [” + ConfigurableWebApplicationContext.class.getName() + “]”);
  6. }
  7. return (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass); //实例化
  8. }


  ContextLoader . determineContextClass(ServletContext sc) 方法: 决定contextClass,该 contextClass 决定了  WebApplicationContext 的 实现类的类型;这里创建的 实现类为 AnnotationConfigWebApplicationContext ;


 
 
  1. protected Class<?> determineContextClass(ServletContext servletContext) {
  2. //获取 web.xml 中 初始化参数 contextClass,本文设置了该参数
  3. String contextClassName = servletContext.getInitParameter(CONTEXT_CLASS_PARAM);
  4. if (contextClassName != null) {
  5. try {
  6. return ClassUtils.forName(contextClassName, ClassUtils.getDefaultClassLoader()); //使用指定的 class 反射出 Class 对象
  7. }
  8. catch (ClassNotFoundException ex) {
  9. throw new ApplicationContextException(
  10. “Failed to load custom context class [” + contextClassName + “]”, ex);
  11. }
  12. }
  13. else {
  14. // 否则使用默认策略,即获得 XMLWebApplicationContext 对应的bean 的名称
  15. contextClassName = defaultStrategies.getProperty(WebApplicationContext.class.getName());
  16. try {
  17. return ClassUtils.forName(contextClassName, ContextLoader.class.getClassLoader());
  18. }
  19. catch (ClassNotFoundException ex) {
  20. throw new ApplicationContextException(
  21. “Failed to load default context class [” + contextClassName + “]”, ex);
  22. }
  23. }
  24. }

         3.2 加载并 设置父 上下文

         3.3   ContextLoader . configureAndRefreshWebApplicationContext(cwac, servletContext):配置并且刷新 WebApplicationContext


 
 
  1. protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) {
  2. if (ObjectUtils.identityToString(wac).equals(wac.getId())) {
  3. // The application context id is still set to its original default value
  4. // -> assign a more useful id based on available information
  5. //获取 web.xml 中定义的 contextId 初始化值,未定义
  6. String idParam = sc.getInitParameter(CONTEXT_ID_PARAM);
  7. if (idParam != null) {
  8. wac.setId(idParam);
  9. }
  10. else {
  11. // Generate default id…
  12. wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX +
  13. ObjectUtils.getDisplayString(sc.getContextPath()));
  14. }
  15. }
  16. wac.setServletContext(sc); //配置了 servletContext 属性
  17. //获取 web.xml 中定义的 contextConfiLocation 初始化参数值 ,已定义,
  18. //配置了除 mvc 配置文件的其他配置文件路径如 数据库连接配置 和 spring 配置文件
  19. String configLocationParam = sc.getInitParameter(CONFIG_LOCATION_PARAM);
  20. if (configLocationParam != null) {
  21. wac.setConfigLocation(configLocationParam); //配置了 configLocation 字段属性
  22. }
  23. // The wac environment’s #initPropertySources will be called in any case when the context
  24. // is refreshed; do it eagerly here to ensure servlet property sources are in place for
  25. // use in any post-processing or initialization that occurs below prior to #refresh
  26. /** 初始化 应用上下文 中 和 Servlet 相关的 占位符 属性资源 begin /
  27. ConfigurableEnvironment env = wac.getEnvironment();
  28. if (env instanceof ConfigurableWebEnvironment) {
  29. ((ConfigurableWebEnvironment) env).initPropertySources(sc, null);
  30. }
  31. / 初始化 应用上下文 中 和 Servlet 相关的 占位符 属性资源 end**/
  32. // 加载web.xml 中 自定义的 其他初始化内容,这里都没有定义
  33. customizeContext(sc, wac);
  34. //WebApplicationContext 的刷新
  35. wac.refresh();
  36. }

----------------------------  environment 获取 begin---------------------------------------------------

ConfigurableWebApplicationContext . getEnvironment 方法为抽象方法;

AbstractApplicationContext . getEnvironment 为方法的实现:


 
 
  1. public ConfigurableEnvironment getEnvironment() {
  2. if ( this.environment == null) {
  3. this.environment = createEnvironment(); //调用 StandardEnvironment的构造函数
  4. }
  5. return this.environment;
  6. }
StandardEnvironment 的构造函数会先执行 父类 AbstractEnvironment 的 构造函数:

AbstractEnvironment 构造函数 及 customizePropertySources方法:


 
 
  1. public AbstractEnvironment() {
  2. customizePropertySources( this.propertySources);
  3. if ( this.logger.isDebugEnabled()) {
  4. this.logger.debug(String.format(
  5. “Initialized %s with PropertySources %s”, getClass().getSimpleName(), this.propertySources));
  6. }
  7. }
  8. protected void customizePropertySources(MutablePropertySources propertySources) {
  9. }

Note:父类 中调用 被子类重写(override)的自身方法时,会执行子类的重写方法,而不会执行父类中的方法;如果想要执行父类中的方法,需要明确调用 super.methodName();

所以这里调用 StandardServletEnvironment 中的重写方法:


 
 
  1. protected void customizePropertySources(MutablePropertySources propertySources) {
  2. //添加 key 为 servletConfigInitParams ,value 为 Object 占位符
  3. propertySources.addLast( new StubPropertySource(SERVLET_CONFIG_PROPERTY_SOURCE_NAME));
  4. //添加 key 为 servletContextInitParams,value 为 Object 占位符
  5. propertySources.addLast( new StubPropertySource(SERVLET_CONTEXT_PROPERTY_SOURCE_NAME));
  6. if (JndiLocatorDelegate.isDefaultJndiEnvironmentAvailable()) {
  7. //添加 key 为 jndiProperties,value 为 Object 占位符
  8. propertySources.addLast( new JndiPropertySource(JNDI_PROPERTY_SOURCE_NAME));
  9. }
  10. super.customizePropertySources(propertySources); //执行父类 StandardEnvironment 中方法,添加了2 个
  11. }

StandardEnvironment 中的重写方法:


 
 
  1. protected void customizePropertySources(MutablePropertySources propertySources) {
  2. //key 为 systemProperties
  3. propertySources.addLast( new MapPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties()));
  4. //key 为 systemEnvironment
  5. propertySources.addLast( new SystemEnvironmentPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment()));
  6. }

getEnvironment 方法 最终返回 StandardServletEnvironment 实现类,其中的 propertySource 字段(MutablePropertySources 类)中初始化了 5 个 PropertySource(目前前 3 个 source 都是 占位符 object,后期会进行填充和替换);即完成了 Environment 相关实现类的 初始化;


附录2 :StandardEnvironment 顶层父类 UML 图



相关类介绍:

PropertySources 接口 :包含 一个 或者 多个 PropertySource 的对象;即用于 保存;提供了 是否包含 | 获取 property source 的 抽象方法;

           MutablePropertySources 类:PropertySources 接口 的实现类,用于 操作 属性资源,并且 提供了可以拷贝 已存在 的 PropertySources 的 构造函数;  

PropertySource 抽象类:代表一个 资源 的抽象基类,使用键值对表示;

          StubPopertySource:PropertySource 的内部静态实现类;当一个实际的属性资源不能在 应用上下文创建时初始化,则使用此类,此类中的 source 为 object 占位符,后期进行替换;

          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 为方法的实现:


 
 
  1. public void initPropertySources(ServletContext servletContext, ServletConfig servletConfig) {
  2. WebApplicationContextUtils.initServletPropertySources(getPropertySources(), servletContext, servletConfig);
  3. }


WebApplicationContextUtils . initServletPropertySources 方法:使用给定的 ServletContext 和 ServletConfig 对象的实例 替换 StubPropertySource 中的相关占位符


 
 
  1. public static void initServletPropertySources(
  2. MutablePropertySources propertySources, ServletContext servletContext, ServletConfig servletConfig) {
  3. Assert.notNull(propertySources, “‘propertySources’ must not be null”);
  4. // 替换 key 为 servletContextInitParams 的 source 值
  5. if (servletContext != null && propertySources.contains(StandardServletEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME) &&
  6. propertySources.get(StandardServletEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME) instanceof StubPropertySource) {
  7. propertySources.replace(StandardServletEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME,
  8. new ServletContextPropertySource(StandardServletEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME, servletContext));
  9. }
  10. // 替换 key 为 servletConfigInitParams的 source 值
  11. if (servletConfig != null && propertySources.contains(StandardServletEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME) &&
  12. propertySources.get(StandardServletEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME) instanceof StubPropertySource) {
  13. propertySources.replace(StandardServletEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME,
  14. new ServletConfigPropertySource(StandardServletEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME, servletConfig));
  15. }
  16. }


          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 的唯一实现方法,采用了 模版方法设计模式;


 
 
  1. public void refresh() throws BeansException, IllegalStateException {
  2. synchronized ( this.startupShutdownMonitor) {
  3. // 刷新前的准备 工作:涉及属性的设置以及属性资源的 初始化
  4. prepareRefresh();
  5. // 通知子类刷新 内置的 bean 工厂,获得一个新的 bean factory
  6. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
  7. // 配置 工厂的 标准上下文特性,例如 上下文的 ClassLoader 和 post-processors
  8. prepareBeanFactory(beanFactory);
  9. try {
  10. //在 应用上下文 子类中 增加 后处理(post-processing) 的 bean 工厂
  11. postProcessBeanFactory(beanFactory);
  12. // 在应用上下文中调用所有 已注册的 BeanFactoryPostProcesser 作为 bean
  13. invokeBeanFactoryPostProcessors(beanFactory);
  14. // 注册具有拦截功能的 bean processors
  15. registerBeanPostProcessors(beanFactory);
  16. // 为应用上下文 初始化 消息 源
  17. initMessageSource();
  18. // 为应用上下文 初始化 事件 多路广播
  19. initApplicationEventMulticaster();
  20. // 初始化其他特殊的 bean
  21. onRefresh();
  22. // 检查 监听器 相关的 bean ,并注册他们
  23. registerListeners();
  24. //实例化所有剩余的单例 bean (非 懒 初始化)
  25. finishBeanFactoryInitialization(beanFactory);
  26. //最后一部:发布 相关的事件
  27. finishRefresh();
  28. }
  29. catch (BeansException ex) {
  30. if (logger.isWarnEnabled()) {
  31. logger.warn( "Exception encountered during context initialization - " +
  32. "cancelling refresh attempt: " + ex);
  33. }
  34. // Destroy already created singletons to avoid dangling resources.
  35. destroyBeans();
  36. // Reset ‘active’ flag.
  37. cancelRefresh(ex);
  38. // Propagate exception to caller.
  39. throw ex;
  40. }
  41. finally {
  42. // Reset common introspection caches in Spring’s core, since we
  43. // might not ever need metadata for singleton beans anymore…
  44. resetCommonCaches();
  45. }
  46. }
  47. }

相关类介绍:

ConfigurableListableBeanFactory 接口 :ListableBeanFactory,ConfigurableBeanFactory,AutowireCapableBeanFactory 的子接口,

          ListableBeanFactory :提供了枚举所有 bean 实例的 方法,而不是提供名称去定向寻找;

          ConfigurableBeanFactory:被大多数的 bean 工厂 实现的 配置接口,提供 了用于配置 bean 工厂 的 基础设施;

          AutowireCapableBeanFactory: BeanFactory 的直接子接口,是 BeanFactory 的 扩展接口,能够实现自动装配;


刷新工作 所做的 工作比较多 ,下面一个一个分析 :

3.3.1  AbstractApplicationContext . prepareRefresh():为刷新 准备 context;


 
 
  1. protected void prepareRefresh() {
  2. this.startupDate = System.currentTimeMillis();
  3. this.closed.set( false); //context 是否 已经关闭,false 代表未关闭
  4. this.active.set( true); // context 当前是否是活跃的,true 代表 活跃
  5. if (logger.isInfoEnabled()) {
  6. logger.info( "Refreshing " + this);
  7. }
  8. // Initialize any placeholder property sources in the context environment
  9. initPropertySources(); //上面有调用过
  10. // Validate that all properties marked as required are resolvable
  11. // see ConfigurablePropertyResolver#setRequiredProperties
  12. getEnvironment().validateRequiredProperties(); //验证资源
  13. // Allow for the collection of early ApplicationEvents,
  14. // to be published once the multicaster is available…
  15. this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
  16. }

AbstractApplicationContext . initPropertySources 方法:空方法,由不同的子类进行不同的实现;这里再次初始化 属性资源方法 ,但是此时 ServletContextPropertySource 已经 成功加入到了 MutablePropertySources  对象的 propertySourceList  列表中;

------------------------------------  property 验证 begin---------------------------------------------------

ConfigurableEnvironment . validateRequiredProperties 为抽象方法;

AbstractEnvironment . validateRequiredProperties 为实现方法:


 
 
  1. private final MutablePropertySources propertySources = new MutablePropertySources( this.logger);
  2. private final ConfigurablePropertyResolver propertyResolver =
  3. new PropertySourcesPropertyResolver( this.propertySources);
  4. public void validateRequiredProperties() throws MissingRequiredPropertiesException {
  5. this.propertyResolver.validateRequiredProperties();
  6. }

PopertySourcesPropertyReolver . validateRequiredProperties 方法:


 
 
  1. public void validateRequiredProperties() {
  2. MissingRequiredPropertiesException ex = new MissingRequiredPropertiesException();
  3. for (String key : this.requiredProperties) {
  4. if ( this.getProperty(key) == null) {
  5. ex.addMissingRequiredProperty(key);
  6. }
  7. }
  8. if (!ex.getMissingRequiredProperties().isEmpty()) {
  9. throw ex;
  10. }
  11. }


------------------------------------  property 验证 end---------------------------------------------------


  综上,prepareRefresh()方法用于刷新前打开  AbstractApplicationContext 中的开关字段(close | active)、 environment 资源 的初始化和验证以及初始化 earlyApplicationEvents ;都是准备工作;


3.3.2 AbstractApplicationContext . obtainFreshBeanFactory():返回一个 新的 ConfigurableListableBeanFactory   bean 工厂类


 
 
  1. protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
  2. /** template method 模式:不同的子类有不同的实现 begin**/
  3. refreshBeanFactory();
  4. ConfigurableListableBeanFactory beanFactory = getBeanFactory(); // 将上面得到的 bean 工厂返回
  5. /** template method 模式:不同的子类有不同的实现 end**/
  6. if (logger.isDebugEnabled()) {
  7. logger.debug( "Bean factory for " + getDisplayName() + ": " + beanFactory);
  8. }
  9. return beanFactory;
  10. }

AbstractApplicationContext . refreshBeanFactory 为 抽象方法:使用了 模版方法设计模式,参看【design pattern】Template method(模板方法设计模式) 中的分析;

AbstractRefreshableApplicationContext . refreshBeanFactory 实现:


 
 
  1. protected final void refreshBeanFactory() throws BeansException {
  2. if (hasBeanFactory()) {
  3. destroyBeans(); //销毁 bean 工厂管理的所有 bean
  4. closeBeanFactory(); //关闭 bean 工厂
  5. }
  6. /** 重新创建一个 新的 bean 工厂 begin /
  7. try {
  8. DefaultListableBeanFactory beanFactory = createBeanFactory();
  9. beanFactory.setSerializationId(getId());
  10. customizeBeanFactory(beanFactory);
  11. loadBeanDefinitions(beanFactory);
  12. synchronized ( this.beanFactoryMonitor) {
  13. this.beanFactory = beanFactory; //保存创建的 bean 工厂 对象
  14. }
  15. / 重新创建一个 新的 bean 工厂 end **/
  16. }
  17. catch (IOException ex) {
  18. throw new ApplicationContextException( "I/O error parsing bean definition source for " + getDisplayName(), ex);
  19. }
  20. }

这里的刷新 bean 工厂 逻辑:如果 beanFactory 属性不为空,则先关闭,然后再构造一个新的 DefaultListableBeanFactory;

------------------------------------  createBeanFactory   begin---------------------------------------------------

AbstractRefreshableApplicationContext . createBeanFactory()方法:通过 调用  DefaultListableBeanFactory 构造函数实例化 beanFactory,在调用过程中会调用 其父类 AbstractAutowireCapableBeanFactory 的 无参构造函数,如下:这里配置了需要忽略的依赖接口,保存在其下的  ignoredDependencyInterfaces 字段中


 
 
  1. public AbstractAutowireCapableBeanFactory() {
  2. super();
  3. ignoreDependencyInterface(BeanNameAware.class); //忽略因为自动注入的 依赖接口
  4. ignoreDependencyInterface(BeanFactoryAware.class);
  5. ignoreDependencyInterface(BeanClassLoaderAware.class);
  6. }
  7. public void ignoreDependencyInterface(Class<?> ifc) {
  8. this.ignoredDependencyInterfaces.add(ifc);
  9. }


创建 DefaultListableBeanFactory 过程中 配置了  ignoredDependencyInterfaces 属性(增加3个);

------------------------------------  createBeanFactory    end---------------------------------------------------

------------------------------------  customizeBeanFactory     begin---------------------------------------------------

AbstractRefreshableApplicationContext . customizeBeanFactory() 方法:  将 Context 上下文中的参数属性传递给 bean 工厂;包括 allowBeanDefinitionOverriding   和 allowCircularReferences 属性值(均为 boolean 值)


 
 
  1. protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
  2. if ( this.allowBeanDefinitionOverriding != null) {
  3. beanFactory.setAllowBeanDefinitionOverriding( this.allowBeanDefinitionOverriding);
  4. }
  5. if ( this.allowCircularReferences != null) {
  6. beanFactory.setAllowCircularReferences( this.allowCircularReferences);
  7. }
  8. }

用于将 ApplicationContext 中的 部分属性信息 传递给 刚初始化的 beanFactory ;

------------------------------------  customizeBeanFactory    end---------------------------------------------------

------------------------------------ loadBeanDefinitions      begin---------------------------------------------------

 AbstractRefreshableApplicationContext . loadBeanDefinitions 为 抽象方法  ;

AnnotationConfigWebApplicationContext . loadBeanDefinitions 实现方法(不同的子类有不同的实现方法):


 
 
  1. protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) {
  2. // 通过 bean 工厂实例化 bean 定义的 reader,并在bean 工厂中注册 相关 的 注解的 post processors
  3. AnnotatedBeanDefinitionReader reader = getAnnotatedBeanDefinitionReader(beanFactory);
  4. //通过 bean 工厂实例化 bean 定义的扫描器
  5. ClassPathBeanDefinitionScanner scanner = getClassPathBeanDefinitionScanner(beanFactory);
  6. //返回当前类持有的 bean 名称生成器,此时为null
  7. BeanNameGenerator beanNameGenerator = getBeanNameGenerator();
  8. if (beanNameGenerator != null) {
  9. reader.setBeanNameGenerator(beanNameGenerator);
  10. scanner.setBeanNameGenerator(beanNameGenerator);
  11. beanFactory.registerSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR, beanNameGenerator);
  12. }
  13. // 返回当前类持有的 bean 定义 范围解析器,此时为 null
  14. ScopeMetadataResolver scopeMetadataResolver = getScopeMetadataResolver();
  15. if (scopeMetadataResolver != null) {
  16. reader.setScopeMetadataResolver(scopeMetadataResolver);
  17. scanner.setScopeMetadataResolver(scopeMetadataResolver);
  18. }
  19. if (! this.annotatedClasses.isEmpty()) {
  20. if (logger.isInfoEnabled()) {
  21. logger.info( “Registering annotated classes: [” +
  22. StringUtils.collectionToCommaDelimitedString( this.annotatedClasses) + “]”);
  23. }
  24. reader.register( this.annotatedClasses.toArray( new Class<?>[ this.annotatedClasses.size()]));
  25. }
  26. if (! this.basePackages.isEmpty()) {
  27. if (logger.isInfoEnabled()) {
  28. logger.info( “Scanning base packages: [” +
  29. StringUtils.collectionToCommaDelimitedString( this.basePackages) + “]”);
  30. }
  31. scanner.scan( this.basePackages.toArray( new String[ this.basePackages.size()]));
  32. }
  33. // web.xml 中配置的配置文件路径,spring 配置文件和 数据库配置文件,编程式的配置
  34. String[] configLocations = getConfigLocations();
  35. if (configLocations != null) {
  36. for (String configLocation : configLocations) {
  37. try {
  38. //获取每个 java 文件的 Class 对象,并利用 reader 注册
  39. Class<?> clazz = getClassLoader().loadClass(configLocation);
  40. if (logger.isInfoEnabled()) {
  41. logger.info( “Successfully resolved class for [” + configLocation + “]”);
  42. }
  43. reader.register(clazz);
  44. }
  45. catch (ClassNotFoundException ex) {
  46. if (logger.isDebugEnabled()) {
  47. logger.debug( “Could not load class for config location [” + configLocation +
  48. "] - trying package scan. " + ex);
  49. }
  50. int count = scanner.scan(configLocation);
  51. if (logger.isInfoEnabled()) {
  52. if (count == 0) {
  53. logger.info( “No annotated classes found for specified class/package [” + configLocation + “]”);
  54. }
  55. else {
  56. logger.info( “Found " + count + " annotated classes in package [” + configLocation + “]”);
  57. }
  58. }
  59. }
  60. }
  61. }
  62. }

相关类介绍:

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 方法:


 
 
  1. protected AnnotatedBeanDefinitionReader getAnnotatedBeanDefinitionReader(DefaultListableBeanFactory beanFactory) {
  2. return new AnnotatedBeanDefinitionReader(beanFactory, getEnvironment());
  3. }

-------------------------     第 2 层     --------------------------

调用如下的构造函数:


 
 
  1. public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
  2. Assert.notNull(registry, “BeanDefinitionRegistry must not be null”);
  3. Assert.notNull(environment, “Environment must not be null”);
  4. this.registry = registry;
  5. this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
  6. AnnotationConfigUtils.registerAnnotationConfigProcessors( this.registry); //注册相关处理器
  7. }

相关类:

BeanDefinitionRegistry : 处理 BeanDefinition 的接口,包括注册,移除,获取,判断是否包含等操作,例如处理 RootBeanDefinition 和 ChildBeanDefinition; Spring 的 BeanDefinitionReader 需要 通过 该接口的 实现类 来构造,在 Spring core 中 已知的实现者 是  DefaultListableBeanFactory 和 GenericApplicationContext ;

-------------------------     第 3 层     --------------------------
AnnotationConfigUtils . registerAnnotationConfigProcessors() 方法:注册 registry 中 所有相关的 注解 后 处理器(post processors)


 
 
  1. public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
  2. registerAnnotationConfigProcessors(registry, null);
  3. }
-------------------------     第 4 层     --------------------------
AnnotationConfigUtils . registerAnnotationConfigProcessors  重载(overload)方法:


 
 
  1. public static final AnnotationAwareOrderComparator INSTANCE = new AnnotationAwareOrderComparator();
  2. public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
  3. BeanDefinitionRegistry registry, Object source) {
  4. // DefaultListableBeanFacotry 为 BeanDefinitionRegistry 的子类,向下转型,转为 DefaultListableBeanFactory
  5. DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
  6. if (beanFactory != null) {
  7. if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
  8. // 设置bean 工厂的 dependencyComparator 属性,对依赖的列表和数组提供可选的排序
  9. beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
  10. }
  11. if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
  12. // 设置 bean 工厂的 autowireCandidateResolver 属性,用来检查 一个 bean 定义是否需要自动注入 的 解析器
  13. beanFactory.setAutowireCandidateResolver( new ContextAnnotationAutowireCandidateResolver());
  14. }
  15. }
  16. Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<BeanDefinitionHolder>( 4);
  17. // bean 工厂的 beanDefinitionMap 字段中是否包含bean 定义:
  18. if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
  19. RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
  20. def.setSource(source);
  21. beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
  22. }
  23. //是否包含 org.springframework.context.annotation.internalAutowiredAnnotationProcessor
  24. if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
  25. RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
  26. def.setSource(source);
  27. beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
  28. }
  29. //是否包含 org.springframework.context.annotation.internalRequiredAnnotationProcessor,不包含则注册
  30. if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
  31. RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
  32. def.setSource(source);
  33. beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
  34. }
  35. //是否包含 org.springframework.context.annotation.internalCommonAnnotationProcessor
  36. // Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
  37. if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
  38. RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
  39. def.setSource(source);
  40. beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
  41. }
  42. //是否包含 org.springframework.context.annotation.internalPersistenceAnnotationProcessor
  43. // Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
  44. if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
  45. RootBeanDefinition def = new RootBeanDefinition();
  46. try {
  47. def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
  48. AnnotationConfigUtils.class.getClassLoader()));
  49. }
  50. catch (ClassNotFoundException ex) {
  51. throw new IllegalStateException(
  52. "Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
  53. }
  54. def.setSource(source);
  55. beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
  56. }
  57. //是否包含 org.springframework.context.event.internalEventListenerProcessor
  58. if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
  59. RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
  60. def.setSource(source);
  61. beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
  62. }
  63. if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
  64. RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
  65. def.setSource(source);
  66. beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
  67. }
  68. return beanDefs;
  69. }

注解处理器详情:

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 对象


 
 
  1. private static BeanDefinitionHolder registerPostProcessor(
  2. BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {
  3. definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
  4. registry.registerBeanDefinition(beanName, definition);
  5. return new BeanDefinitionHolder(definition, beanName);
  6. }

-------------------------     第 6 层     --------------------------

BeanDefinitionRegistry . registerBeanDefinition()抽象方法

DefaultListableBeanFactory . registerBeanDefinition实现方法:向 bean 工厂中注册 bean 的 定义;实际上是以键值对的形式添加到 beanDefinitionMap 的字段中,同时维护 beanDefinitonName 字段 和 manualSinglethonNames;


 
 
  1. public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
  2. throws BeanDefinitionStoreException {
  3. Assert.hasText(beanName, “Bean name must not be empty”);
  4. Assert.notNull(beanDefinition, “BeanDefinition must not be null”);
  5. if (beanDefinition instanceof AbstractBeanDefinition) {
  6. try {
  7. ((AbstractBeanDefinition) beanDefinition).validate(); //验证 bean 定义
  8. }
  9. catch (BeanDefinitionValidationException ex) {
  10. throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
  11. “Validation of bean definition failed”, ex);
  12. }
  13. }
  14. BeanDefinition oldBeanDefinition;
  15. // 检查该 beanDefinition 是否已经存在
  16. oldBeanDefinition = this.beanDefinitionMap.get(beanName);
  17. if (oldBeanDefinition != null) {
  18. if (!isAllowBeanDefinitionOverriding()) {
  19. throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
  20. “Cannot register bean definition [” + beanDefinition + “] for bean '” + beanName +
  21. “’: There is already [” + oldBeanDefinition + “] bound.”);
  22. }
  23. else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
  24. // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
  25. if ( this.logger.isWarnEnabled()) {
  26. this.logger.warn( “Overriding user-defined bean definition for bean '” + beanName +
  27. “’ with a framework-generated bean definition: replacing [” +
  28. oldBeanDefinition + “] with [” + beanDefinition + “]”);
  29. }
  30. }
  31. else if (!beanDefinition.equals(oldBeanDefinition)) {
  32. if ( this.logger.isInfoEnabled()) {
  33. this.logger.info( “Overriding bean definition for bean '” + beanName +
  34. “’ with a different definition: replacing [” + oldBeanDefinition +
  35. “] with [” + beanDefinition + “]”);
  36. }
  37. }
  38. else {
  39. if ( this.logger.isDebugEnabled()) {
  40. this.logger.debug( “Overriding bean definition for bean '” + beanName +
  41. “’ with an equivalent definition: replacing [” + oldBeanDefinition +
  42. “] with [” + beanDefinition + “]”);
  43. }
  44. }
  45. this.beanDefinitionMap.put(beanName, beanDefinition);
  46. }
  47. else {
  48. // 工厂的 bean创建阶段是否已经开始
  49. if (hasBeanCreationStarted()) {
  50. // Cannot modify startup-time collection elements anymore (for stable iteration)
  51. synchronized ( this.beanDefinitionMap) {
  52. this.beanDefinitionMap.put(beanName, beanDefinition);
  53. List<String> updatedDefinitions = new ArrayList<String>( this.beanDefinitionNames.size() + 1);
  54. updatedDefinitions.addAll( this.beanDefinitionNames);
  55. updatedDefinitions.add(beanName);
  56. this.beanDefinitionNames = updatedDefinitions;
  57. if ( this.manualSingletonNames.contains(beanName)) {
  58. Set<String> updatedSingletons = new LinkedHashSet<String>( this.manualSingletonNames);
  59. updatedSingletons.remove(beanName);
  60. this.manualSingletonNames = updatedSingletons;
  61. }
  62. }
  63. }
  64. //仍然处于 启动注册阶段
  65. else {
  66. // Still in startup registration phase
  67. this.beanDefinitionMap.put(beanName, beanDefinition);
  68. this.beanDefinitionNames.add(beanName);
  69. this.manualSingletonNames.remove(beanName);
  70. }
  71. this.frozenBeanDefinitionNames = null;
  72. }
  73. if (oldBeanDefinition != null || containsSingleton(beanName)) {
  74. //重置所有 beanName 相关 bean definition 缓存
  75. resetBeanDefinition(beanName);
  76. }
  77. }

DefaultListableBeanFactory 中字段介绍:

           beanDefinitionMap: bean 定义 对象的 Map 集合,通过 bean 名称 键入;

           beanDefinitionNames:bean 定义 名称的 list 集合,

           manualSingletonNames:手动注册的单例的名称的 list 集合;


所以,AnnotatedBeanDefinitionReader 构造函数的内部 使用工具类 为 beanFactory  注册了注解相关的 bean 定义,以及功能类;说白了就是,配置bean 工厂如下的几个字段: dependencyComparator ,autowireCandidateResolver,beanDefinitionMap,beanDefinitionNames,manualSingletonNames;返回的 reader 内置了 registry 和 environment ;

附录3 :DefualtListableBeanFactory 上层关系图


-------------------------     第 1 层     --------------------------

 ClassPathBeanDefinitionScanner  实例化,其内部调用 ClassPathBeanDefinitionScanner 的构造器 ,同时调用了父类 ClassPathScanningCandidateComponentProvider 的构造器,如下:


 
 
  1. protected ClassPathBeanDefinitionScanner getClassPathBeanDefinitionScanner(DefaultListableBeanFactory beanFactory) {
  2. return new ClassPathBeanDefinitionScanner(beanFactory, true, getEnvironment());
  3. }

-------------------------     第 2 层     --------------------------


 
 
  1. public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters, Environment environment) {
  2. super(useDefaultFilters, environment);
  3. Assert.notNull(registry, “BeanDefinitionRegistry must not be null”);
  4. this.registry = registry;
  5. // Determine ResourceLoader to use.
  6. if ( this.registry instanceof ResourceLoader) {
  7. setResourceLoader((ResourceLoader) this.registry);
  8. }
  9. }

-------------------------     第 3 层     --------------------------


 
 
  1. public ClassPathScanningCandidateComponentProvider(boolean useDefaultFilters, Environment environment) {
  2. if (useDefaultFilters) {
  3. registerDefaultFilters(); //注册过滤器
  4. }
  5. Assert.notNull(environment, “Environment must not be null”);
  6. this.environment = environment;
  7. }

-------------------------     第 4 层     --------------------------

其中的 registerDefaultFilters() 方法:注册默认的过滤器


 
 
  1. protected void registerDefaultFilters() {
  2. // 为 @Component注解注册 默认过滤器 ,这将隐式的注解所有包含 Component 元注解的注解
  3. //包括 Repository 注解, Service注解,Controller注解
  4. this.includeFilters.add( new AnnotationTypeFilter(Component.class));
  5. ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
  6. try {
  7. //如果项目中加载了相关 jar 包,则会为 JSR-250 注册过滤器
  8. this.includeFilters.add( new AnnotationTypeFilter(
  9. ((Class<? extends Annotation>) ClassUtils.forName( “javax.annotation.ManagedBean”, cl)), false));
  10. logger.debug( “JSR-250 ‘javax.annotation.ManagedBean’ found and supported for component scanning”);
  11. }
  12. catch (ClassNotFoundException ex) {
  13. // JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.
  14. }
  15. try {
  16. //如果项目中加载了相关 jar 包,则会为 JSR-330 注册过滤器
  17. this.includeFilters.add( new AnnotationTypeFilter(
  18. ((Class<? extends Annotation>) ClassUtils.forName( “javax.inject.Named”, cl)), false));
  19. logger.debug( “JSR-330 ‘javax.inject.Named’ annotation found and supported for component scanning”);
  20. }
  21. catch (ClassNotFoundException ex) {
  22. // JSR-330 API not available - simply skip.
  23. }
  24. }


AnnotationTypeFilter 类:TypeFilter 的间接实现类,作用是 使用 给定的注解 匹配 类 的 简单 过滤器,也会 检查 通过 继承得到的注解;通过 给定的注解的类型 实例化;

综上,ClassPathBeanDefinitionScanner  实例化的内部 一定会注册一个 过滤 @Component 注解的 AnnotationTypeFilter,尝试注册 过滤 JSR-250 注解(ManagedBean)的 AnnotationTypeFilter 和 JSR-330 注解(Named)的 AnnotationTypeFilter;说白了就是 配置 beanFactory 的 includeFilters 字段;返回的 scanner 内置了 registry 和 environment

-------------------------     第 1 层     --------------------------

BeanNameGenerator 实例化:返回自定义的 BeanNameGenerator,此处为 null;给 AnnotatedBeanDefinitionReader 类 和 ClassPathBeanDefinitionScanner 类 使用


 
 
  1. protected BeanNameGenerator getBeanNameGenerator() {
  2. return this.beanNameGenerator;
  3. }

BeanNameGenerator : 为 bean 定义 生成 bean 名称的 策略 接口,初始化时获取为空

-------------------------     第 1 层     --------------------------

DefaultListableBeanFactory . registerSingleton 方法:向  beanFactory 中  添加 手动注册的单例,维护  beanFactory 的 manualSingletonNames ,singletonObjects,singletonFactories,earlySingletonObjects,registeredSingletons 字段;


 
 
  1. public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
  2. super.registerSingleton(beanName, singletonObject);
  3. if (hasBeanCreationStarted()) {
  4. // Cannot modify startup-time collection elements anymore (for stable iteration)
  5. synchronized ( this.beanDefinitionMap) {
  6. if (! this.beanDefinitionMap.containsKey(beanName)) {
  7. Set<String> updatedSingletons = new LinkedHashSet<String>( this.manualSingletonNames.size() + 1);
  8. updatedSingletons.addAll( this.manualSingletonNames);
  9. updatedSingletons.add(beanName);
  10. this.manualSingletonNames = updatedSingletons;
  11. }
  12. }
  13. }
  14. else {
  15. // Still in startup registration phase
  16. if (! this.beanDefinitionMap.containsKey(beanName)) {
  17. this.manualSingletonNames.add(beanName);
  18. }
  19. }
  20. clearByTypeCache();
  21. }

super . registerSingleton 方法 是 DefaultSingletonBeanRegistry . registerSingleton 方法:


 
 
  1. public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
  2. Assert.notNull(beanName, “‘beanName’ must not be null”);
  3. synchronized ( this.singletonObjects) {
  4. Object oldObject = this.singletonObjects.get(beanName);
  5. if (oldObject != null) {
  6. throw new IllegalStateException( “Could not register object [” + singletonObject +
  7. “] under bean name '” + beanName + “’: there is already object [” + oldObject + “] bound”);
  8. }
  9. addSingleton(beanName, singletonObject);
  10. }
  11. }
  12. // 维护了 beanFactory 中的多个字段
  13. protected void addSingleton(String beanName, Object singletonObject) {
  14. synchronized ( this.singletonObjects) {
  15. this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));
  16. this.singletonFactories.remove(beanName);
  17. this.earlySingletonObjects.remove(beanName);
  18. this.registeredSingletons.add(beanName);
  19. }
  20. }

-------------------------     第 1层     --------------------------

ScopeMetadataResolver 实例化:返回自定义的 ScopeMetadataResolver 类,此时为 null,给 AnnotatedBeanDefinitionReader 类 和 ClassPathBeanDefinitionScanner 类使用;


 
 
  1. protected ScopeMetadataResolver getScopeMetadataResolver() {
  2. return this.scopeMetadataResolver;
  3. }


ScopeMetadataResolver: 为 bean 定义 解析 范围 的 策略接口

-------------------------     第 1 层     --------------------------

AnnotatedBeanDefinitionReader . register 方法


 
 
  1. public void register(Class<?>… annotatedClasses) {
  2. for (Class<?> annotatedClass : annotatedClasses) {
  3. registerBean(annotatedClass);
  4. }
  5. }
  6. public void registerBean(Class<?> annotatedClass) {
  7. registerBean(annotatedClass, null, (Class<? extends Annotation>[]) null);
  8. }
  9. public void registerBean(Class<?> annotatedClass, String name, Class<? extends Annotation>… qualifiers) {
  10. AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
  11. if ( this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
  12. return;
  13. }
  14. ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
  15. abd.setScope(scopeMetadata.getScopeName());
  16. String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
  17. AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
  18. if (qualifiers != null) {
  19. for (Class<? extends Annotation> qualifier : qualifiers) {
  20. if (Primary.class == qualifier) {
  21. abd.setPrimary( true);
  22. }
  23. else if (Lazy.class == qualifier) {
  24. abd.setLazyInit( true);
  25. }
  26. else {
  27. abd.addQualifier( new AutowireCandidateQualifier(qualifier));
  28. }
  29. }
  30. }
  31. BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
  32. definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
  33. BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
  34. }

相关类介绍:

ScopeMetadata:描述 Spring 管理 的 bean 的 作用域,包括 作用域的 名称 和  代理作用域的行为,默认的作用域为 singleton,默认 的代理作用域是 不代理;

AnnotationMetadata:接口,定义 对指定类注解的 访问 ;可以在类未加载的时候访问;

        StandardAnnotationMetadata:实现类,使用标准的反射反射一个 给定的类;

ScopeMetadataResolver:解析 bean 定义 的 作用域 的策略接口;

ScopedProxyMode:各种 代理作用域的值 的 枚举 :

             default  : default 通常 等于 no ,除非 配置了不同的 default

              no : 不创建 作用域代理

              interfaces:创建 JDK 动态代理

              target_class:创建 基于 一个类的 代理(使用 CGLIB)

-------------------------     第 2 层     --------------------------

AnnotatedGenericBeanDefinition 实例化:


 
 
  1. public AnnotatedGenericBeanDefinition(Class<?> beanClass) {
  2. setBeanClass(beanClass);
  3. this.metadata = new StandardAnnotationMetadata(beanClass, true);
  4. }

-------------------------     第 3 层     --------------------------

StandardAnnotationMetadata 实例化:初始化 字段信息;


 
 
  1. public StandardAnnotationMetadata(Class<?> introspectedClass, boolean nestedAnnotationsAsMap) {
  2. super(introspectedClass);
  3. this.annotations = introspectedClass.getAnnotations(); //获得类上的注解
  4. this.nestedAnnotationsAsMap = nestedAnnotationsAsMap;
  5. }

-------------------------     第 2 层     --------------------------


AnnotationScopeMetadataResolver . resolveScopeMetadata 方法


 
 
  1. public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) {
  2. ScopeMetadata metadata = new ScopeMetadata();
  3. if (definition instanceof AnnotatedBeanDefinition) {
  4. AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition;
  5. AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(
  6. annDef.getMetadata(), this.scopeAnnotationType);
  7. if (attributes != null) {
  8. metadata.setScopeName(attributes.getString( “value”));
  9. ScopedProxyMode proxyMode = attributes.getEnum( “proxyMode”);
  10. if (proxyMode == null || proxyMode == ScopedProxyMode.DEFAULT) {
  11. proxyMode = this.defaultProxyMode;
  12. }
  13. metadata.setScopedProxyMode(proxyMode);
  14. }
  15. }
  16. return metadata;
  17. }

-------------------------     第 2 层     --------------------------

AnnotationBeanNameGenerator . generateBeanName 方法:返回 contextConfigLocation 配置的 bean 的 名称


 
 
  1. public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
  2. if (definition instanceof AnnotatedBeanDefinition) {
  3. String beanName = determineBeanNameFromAnnotation((AnnotatedBeanDefinition) definition);
  4. if (StringUtils.hasText(beanName)) {
  5. // Explicit bean name found.
  6. return beanName;
  7. }
  8. }
  9. // Fallback: generate a unique default bean name.
  10. return buildDefaultBeanName(definition, registry);
  11. }
  12. protected String determineBeanNameFromAnnotation(AnnotatedBeanDefinition annotatedDef) {
  13. AnnotationMetadata amd = annotatedDef.getMetadata();
  14. Set<String> types = amd.getAnnotationTypes();
  15. String beanName = null;
  16. for (String type : types) {
  17. AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(amd, type);
  18. if (isStereotypeWithNameValue(type, amd.getMetaAnnotationTypes(type), attributes)) {
  19. Object value = attributes.get( “value”);
  20. if (value instanceof String) {
  21. String strVal = (String) value;
  22. if (StringUtils.hasLength(strVal)) {
  23. if (beanName != null && !strVal.equals(beanName)) {
  24. throw new IllegalStateException( "Stereotype annotations suggest inconsistent " +
  25. “component names: '” + beanName + “’ versus '” + strVal + “’”);
  26. }
  27. beanName = strVal;
  28. }
  29. }
  30. }
  31. }
  32. return beanName;
  33. }
  34. protected String buildDefaultBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
  35. return buildDefaultBeanName(definition);
  36. }
  37. protected String buildDefaultBeanName(BeanDefinition definition) {
  38. String shortClassName = ClassUtils.getShortName(definition.getBeanClassName());
  39. return Introspector.decapitalize(shortClassName);
  40. }


-------------------------     第3层     --------------------------

StandardAnnotationMetadata . getAnnotationTypes 方法:遍历 annotations 字段,获取所有的注解名字的 set 集合;


 
 
  1. public Set<String> getAnnotationTypes() {
  2. Set<String> types = new LinkedHashSet<String>();
  3. for (Annotation ann : this.annotations) {
  4. types.add(ann.annotationType().getName());
  5. }
  6. return types;
  7. }
-------------------------     第 2 层     --------------------------
AnnotationConfigUtils . applyScopedProxyMode 方法:


 
 
  1. static BeanDefinitionHolder applyScopedProxyMode(
  2. ScopeMetadata metadata, BeanDefinitionHolder definition, BeanDefinitionRegistry registry) {
  3. ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode();
  4. if (scopedProxyMode.equals( ScopedProxyMode.NO)) { // 不使用代理
  5. return definition;
  6. }
  7. boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS);
  8. return ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass); // 使用代理
  9. }

-------------------------     第 3 层     --------------------------

若使用代理, ScopedProxyCreater . createScopeProxy :


 
 
  1. public static BeanDefinitionHolder createScopedProxy(
  2. BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry, boolean proxyTargetClass) {
  3. return ScopedProxyUtils.createScopedProxy(definitionHolder, registry, proxyTargetClass);
  4. }
-------------------------     第 4 层     --------------------------
ScopeProxyUtils . createScopedProxy:


 
 
  1. public static BeanDefinitionHolder createScopedProxy(BeanDefinitionHolder definition,
  2. BeanDefinitionRegistry registry, boolean proxyTargetClass) {
  3. String originalBeanName = definition.getBeanName();
  4. BeanDefinition targetDefinition = definition.getBeanDefinition();
  5. String targetBeanName = getTargetBeanName(originalBeanName);
  6. // Create a scoped proxy definition for the original bean name,
  7. // “hiding” the target bean in an internal target definition.
  8. RootBeanDefinition proxyDefinition = new RootBeanDefinition(ScopedProxyFactoryBean.class);
  9. proxyDefinition.setDecoratedDefinition( new BeanDefinitionHolder(targetDefinition, targetBeanName));
  10. proxyDefinition.setOriginatingBeanDefinition(targetDefinition);
  11. proxyDefinition.setSource(definition.getSource());
  12. proxyDefinition.setRole(targetDefinition.getRole());
  13. proxyDefinition.getPropertyValues().add( “targetBeanName”, targetBeanName);
  14. if (proxyTargetClass) {
  15. targetDefinition.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
  16. // ScopedProxyFactoryBean’s "




    源码环境 : idea + spring 4.3.4 +tomcat7 + gradle

    附 : 基于 java  注解的 配置元数据 的 web.xml 配置做参考(spring 3.0 后支持)

    <code class="language-html
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hello_world!

你的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值