好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

Spring refresh()源码解析

正文

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public void refresh() throws BeansException, IllegalStateException {
     synchronized ( this .startupShutdownMonitor) {
         // 1. 初始化前的预处理
         this .prepareRefresh();
         // 2. 刷新Bean工厂
         ConfigurableListableBeanFactory beanFactory = this .obtainFreshBeanFactory();
         // 3. BeanFactory的预处理配置
         this .prepareBeanFactory(beanFactory);
         try {
             // 4. BeanFactory的后置处理
             this .postProcessBeanFactory(beanFactory);
             // 5. 执行BeanFactory后置处理器
             this .invokeBeanFactoryPostProcessors(beanFactory);
             // 6. 注册Bean的后置处理器
             this .registerBeanPostProcessors(beanFactory);
             // 7. 初始化MessageSource
             this .initMessageSource();
             // 8. 初始化事件派发器
             this .initApplicationEventMulticaster();
             // 9. 子类的多态onRefresh
             this .onRefresh();
             // 10. 注册监听器
             this .registerListeners();
             // 11. 初始化所有剩下的单例Bean
             this .finishBeanFactoryInitialization(beanFactory);
             // 12. 完成容器的创建工作
             this .finishRefresh();
         } catch (BeansException var9) {
             if ( this .logger.isWarnEnabled()) {
                 this .logger.warn( "Exception encountered during context initialization - cancelling refresh attempt: " + var9);
             }
             this .destroyBeans();
             this .cancelRefresh(var9);
             throw var9;
         } finally {
             // 13. 清除缓存
             this .resetCommonCaches();
         }
     }
}

一、prepareRefresh:初始化前的预处理

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
protected void prepareRefresh() {
     //设置容器启动时间
     this .startupDate = System.currentTimeMillis();
     //设置容器关闭状态为false
     this .closed.set( false );
     //设置容器激活状态为true
     this .active.set( true );
     if ( this .logger.isDebugEnabled()) {
         if ( this .logger.isTraceEnabled()) {
             this .logger.trace( "Refreshing " + this );
         } else {
             this .logger.debug( "Refreshing " + this .getDisplayName());
         }
     }
     //1.1初始化属性资源
     this .initPropertySources();
     //1.2校验
     this .getEnvironment().validateRequiredProperties();
     this .earlyApplicationEvents = new LinkedHashSet();
}

1.1初始化属性值

初始化方法是个模压方法,由子类重写

?
1
2
protected void initPropertySources() {
}

Web容器GenericWebApplicationContext重写了此方法

?
1
2
3
4
5
6
7
8
protected void initPropertySources() {
     //获取环境信息
    ConfigurableEnvironment env = getEnvironment();
    //判断是否是web配置环境
    if (env instanceof ConfigurableWebEnvironment) {
       ((ConfigurableWebEnvironment) env).initPropertySources( this .servletContext, null );
    }
}

最终由StandardServletEnvironment进行初始化

?
1
2
3
4
public void initPropertySources( @Nullable ServletContext servletContext, @Nullable ServletConfig servletConfig) {
//使用web容器工具初始化
WebApplicationContextUtils.initServletPropertySources(getPropertySources(), servletContext, servletConfig);
}

把 Servlet 的一些初始化参数放入IOC容器中

?
1
2
3
4
5
6
7
8
9
10
11
public static void initServletPropertySources(MutablePropertySources sources, @Nullable ServletContext servletContext, @Nullable ServletConfig servletConfig) {
     Assert.notNull(sources, "'propertySources' must not be null" );
     String name = "servletContextInitParams" ;
     if (servletContext != null && sources.contains(name) && sources.get(name) instanceof StubPropertySource) {
         sources.replace(name, new ServletContextPropertySource(name, servletContext));
     }
     name = "servletConfigInitParams" ;
     if (servletConfig != null && sources.contains(name) && sources.get(name) instanceof StubPropertySource) {
         sources.replace(name, new ServletConfigPropertySource(name, servletConfig));
     }
}

1.2属性校验

通过占位符解析器校验资源集合

?
1
2
3
public void validateRequiredProperties() throws MissingRequiredPropertiesException {
    this .propertyResolver.validateRequiredProperties();
}

这里的解析器作为常量在环境被实例化时就被创建出来的,PropertySourcesPropertyResolver是占位符解析器,将数据源中占位符替换成目标值

校验是否有需要被占位符修饰的属性,如果有但是资源中找不到对应属性的key就会抛出异常

?
1
2
3
4
5
6
7
8
9
10
11
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;
    }
}

案例: 资源文件

?
1
2
3
4
name=zhansan
age=${name}, 10
encoding=utf- 8
name2=${name}

测试代码

?
1
2
3
4
5
6
7
8
@Test
public void test1() throws Exception {
     //省略propertySources
     PropertyResolver propertyResolver = new PropertySourcesPropertyResolver(getPropertySources());
     System.out.println(propertyResolver.getProperty( "age" ));   
     System.out.println(propertyResolver.getProperty( "encoding" ));
     System.out.println(propertyResolver.resolvePlaceholders( "must be encoding ${encoding}" ));  //输出must be encoding gbk
}

输出结果

10,zhansan
utf-8
must be encoding utf-8

二、obtainFreshBeanFactory:刷新Bean工厂

?
1
2
3
4
5
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    //2.1刷新Bean工厂
    refreshBeanFactory();
    return getBeanFactory();
}

将容器刷新标识改为true,并且设置了工厂序列化id

?
1
2
3
4
5
6
7
protected final void refreshBeanFactory() throws IllegalStateException {
    if (! this .refreshed测试数据pareAndSet( false , true )) {
       throw new IllegalStateException(
             "GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once" );
    }
    this .beanFactory.setSerializationId(getId());
}

三、prepareBeanFactory:Bean工厂预处理

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    // 设置BeanFactory的类加载器、表达式解析器等
    beanFactory.setBeanClassLoader(getClassLoader());
    beanFactory.setBeanExpressionResolver( new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
    beanFactory.addPropertyEditorRegistrar( new ResourceEditorRegistrar( this , getEnvironment()));
    // 3.1 添加Aware执行器
    beanFactory.addBeanPostProcessor( new ApplicationContextDProcessor( this ));
    beanFactory.ignoreDependencyInterface(EnvironmentAware. class );
    beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware. class );
    beanFactory.ignoreDependencyInterface(ResourceLoaderAware. class );
    beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware. class );
    beanFactory.ignoreDependencyInterface(MessageSourceAware. class );
    beanFactory.ignoreDependencyInterface(ApplicationContextAware. class );
    // 3.2 自动注入的支持
    beanFactory.registerResolvableDependency(BeanFactory. class , beanFactory);
    beanFactory.registerResolvableDependency(ResourceLoader. class , this );
    beanFactory.registerResolvableDependency(ApplicationEventPublisher. class , this );
    beanFactory.registerResolvableDependency(ApplicationContext. class , this );
    // 3.3 添加监听器执行器
    beanFactory.addBeanPostProcessor( new ApplicationListenerDetector( this ));
    // Detect a LoadTimeWeaver and prepare for weaving, if found.
    if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
       beanFactory.addBeanPostProcessor( new LoadTimeWeaverAwareProcessor(beanFactory));
       // Set a temporary ClassLoader for type matching.
       beanFactory.setTempClassLoader( new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }
    // Register default environment beans.
    if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
       beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
    }
    if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
       beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
    }
    if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
       beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
    }
}

3.1 ApplicationContextDProcessor:Aware执行器

ApplicationContextDProcessor实现了BeanPostProcessor的postProcessBeforeInitialization接口,在所有Bean初始化前会执行当前方法

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    //判断Bean是Aware的子类
    if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
          bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
          bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)){
       return bean;
    }
    AccessControlContext acc = null ;
    if (System.getSecurityManager() != null ) {
       acc = this .applicationContext.getBeanFactory().getAccessControlContext();
    }
    if (acc != null ) {
       AccessController.doPrivileged((PrivilegedAction&lt;Object&gt;) () -&gt; {
          invokeAwareInterfaces(bean);
          return null ;
       }, acc);
    }
    else {
        //回调执行Aware接口
       invokeAwareInterfaces(bean);
    }
    return bean;
}

如果当前Bean是Aware的子类,那么将Bean强转成Aware类型,通过回调将信息设置到Bean中

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
private void invokeAwareInterfaces(Object bean) {
    if (bean instanceof EnvironmentAware) {
       ((EnvironmentAware) bean).setEnvironment( this .applicationContext.getEnvironment());
    }
    if (bean instanceof EmbeddedValueResolverAware) {
       ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver( this .embeddedValueResolver);
    }
    if (bean instanceof ResourceLoaderAware) {
       ((ResourceLoaderAware) bean).setResourceLoader( this .applicationContext);
    }
    if (bean instanceof ApplicationEventPublisherAware) {
       ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher( this .applicationContext);
    }
    if (bean instanceof MessageSourceAware) {
       ((MessageSourceAware) bean).setMessageSource( this .applicationContext);
    }
    if (bean instanceof ApplicationContextAware) {
       ((ApplicationContextAware) bean).setApplicationContext( this .applicationContext);
    }
}

3.2 registerResolvableDependency:自动注入的支持

如果过容器中有多个相同接口的实现类,那么在自动注入的时候会注入注册的实现类

?
1
2
3
4
beanFactory.registerResolvableDependency(BeanFactory. class , beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader. class , this );
beanFactory.registerResolvableDependency(ApplicationEventPublisher. class , this );
beanFactory.registerResolvableDependency(ApplicationContext. class , this );

3.3 添加监听器执行器

ApplicationListenerDetector主要作用是添加和销毁监听器,实现了BeanPostProcessor的postProcessAfterInitialization(Bean实例化之后)方法和DestructionAwareBeanPostProcessor的postProcessBeforeDestruction(Bean销毁之前)方法

详情: http://HdhCmsTesttuohang.net/article/265608.html

四、BeanFactory的后置处理

这是个模压方法,由子类AnnotationConfigServletWebServerApplicationContext实现

?
1
2
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
}

AnnotationConfigServletWebServerApplicationContext首先调了父类 ServletWebServerApplicationContext 的 postProcessBeanFactory 方法

?
1
2
3
4
5
6
7
8
9
10
11
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    //4.1后置处理Bean工厂
    super .postProcessBeanFactory(beanFactory);
    if ( this .basePackages != null && this .basePackages.length > 0 ) {
       //basePackages为空不会执行
       this .scanner.scan( this .basePackages);
    }
    if (! this .annotatedClasses.isEmpty()) {
       this .reader.register(ClassUtils.toClassArray( this .annotatedClasses));
    }
}

4.1 后置处理bean工厂

父类ServletWebServerApplicationContext首先向Bean工厂中注入了一个执行器

?
1
2
3
4
5
6
7
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    //4.1.1注入执行器
    beanFactory.addBeanPostProcessor( new WebApplicationContextServletContextAwareProcessor( this ));
    beanFactory.ignoreDependencyInterface(ServletContextAware. class );
    //4.1.2注册作用域
    registerWebApplicationScopes();
}

4.1.1 WebApplicationContextServletContextAwareProcessor

WebApplicationContextServletContextAwareProcessor继承了ServletContextAwareProcessor

ServletContextAwareProcessor继承了BeanPostProcessor实现了postProcessBeforeInitialization(Bean初始化前执行)

?
1
2
3
4
5
6
7
8
9
10
11
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
     //注入ServletContext
    if (getServletContext() != null && bean instanceof ServletContextAware) {
       ((ServletContextAware) bean).setServletContext(getServletContext());
    }
    //注入ServletConfig
    if (getServletConfig() != null && bean instanceof ServletConfigAware) {
       ((ServletConfigAware) bean).setServletConfig(getServletConfig());
    }
    return bean;
}

4.1.2 registerWebApplicationScopes 注册web的应用域
?
1
2
3
4
5
6
// 所在类及方法:ServletWebServerApplicationContext#registerWebApplicationScopes
    private void registerWebApplicationScopes() {
           ExistingWebApplicationScopes existingScopes = new ExistingWebApplicationScopes(getBeanFactory());
           WebApplicationContextUtils.registerWebApplicationScopes(getBeanFactory());
           existingScopes.restore();
     }

ExistingWebApplicationScopes是ServletWebServerApplicationContext类中的一个静态类

源码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public static class ExistingWebApplicationScopes {
      static {
       Set<String> scopes = new LinkedHashSet<>();
       scopes.add(WebApplicationContext.SCOPE_REQUEST);
       scopes.add(WebApplicationContext.SCOPE_SESSION);
       SCOPES = Collections.unmodifiableSet(scopes);
    }
      // 这是构造方法,大概就是根据SCOPES获取beanFactory中已经注册的scope,然后放入scopes
      // 需要注意的是,在上面的方法中,第二行才在向beanFactory中注册,也就是这时的beanFactory里面没有request和session这两个scop
      // 所以这里就完成了beanFactory的赋值。建议打断点进去看看
    public ExistingWebApplicationScopes(ConfigurableListableBeanFactory beanFactory) {
       this .beanFactory = beanFactory;
       for (String scopeName : SCOPES) {
          Scope scope = beanFactory.getRegisteredScope(scopeName);
          if (scope != null ) {
             this .scopes.put(scopeName, scope);
          }
       }
    }
      // 由于上面的方法并没有值存入scopes,所以这里也就没执行里面的内容
    public void restore() {
       this .scopes.forEach((key, value) -> {
          if (logger.isInfoEnabled()) {
             logger.info( "Restoring user defined scope " + key);
          }
          this .beanFactory.registerScope(key, value);
       });
    }
}

WebApplicationContextUtils.registerWebApplicationScopes(),这个方法就是向beanFactory注册web的scope了,源码如下

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public static void registerWebApplicationScopes(ConfigurableListableBeanFactory beanFactory) {
    registerWebApplicationScopes(beanFactory, null );
}
  public static void registerWebApplicationScopes(ConfigurableListableBeanFactory beanFactory,
       @Nullable ServletContext sc) {
      // 注册作用域
    beanFactory.registerScope(WebApplicationContext.SCOPE_REQUEST, new RequestScope()); // 注册request  SCOP
    beanFactory.registerScope(WebApplicationContext.SCOPE_SESSION, new SessionScope()); // 注册session SCOP
    if (sc != null ) {
       ServletContextScope appScope = new ServletContextScope(sc);
       beanFactory.registerScope(WebApplicationContext.SCOPE_APPLICATION, appScope); // 注册application SCOP
       // Register as ServletContext attribute, for ContextCleanupListener to detect it.
       sc.setAttribute(ServletContextScope. class .getName(), appScope);
    }
      // 添加依赖项
    beanFactory.registerResolvableDependency(ServletRequest. class , new RequestObjectFactory());
    beanFactory.registerResolvableDependency(ServletResponse. class , new ResponseObjectFactory());
    beanFactory.registerResolvableDependency(HttpSession. class , new SessionObjectFactory());
    beanFactory.registerResolvableDependency(WebRequest. class , new WebRequestObjectFactory());
    if (jsfPresent) {
       FacesDependencyRegistrar.registerFacesDependencies(beanFactory);
    }
}

以上就是Spring refresh()源码解析的详细内容,更多关于Spring refresh()的资料请关注其它相关文章!

原文链接:https://juejin.cn/post/7202531472720789559

查看更多关于Spring refresh()源码解析的详细内容...

  阅读:14次