服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Java教程 - Spring refresh()源码解析

Spring refresh()源码解析

2023-03-16 14:47无名之辈J Java教程

这篇文章主要为大家介绍了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是占位符解析器,将数据源中占位符替换成目标值

Spring refresh()源码解析

校验是否有需要被占位符修饰的属性,如果有但是资源中找不到对应属性的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.compareAndSet(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<Object>) () -> {
         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://www.tuohang.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

延伸 · 阅读

精彩推荐
  • Java教程Java Thread之Sleep()案例详解

    Java Thread之Sleep()案例详解

    这篇文章主要介绍了Java Thread之Sleep()案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下...

    每天都要进步一点点6792021-11-18
  • Java教程Spring Cloud 负载均衡器 Ribbon原理及实现

    Spring Cloud 负载均衡器 Ribbon原理及实现

    这篇文章主要介绍了Spring Cloud 负载均衡器 Ribbon原理及实现,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    林塬11582021-04-10
  • Java教程基于Spring Mvc实现的Excel文件上传下载示例

    基于Spring Mvc实现的Excel文件上传下载示例

    本篇文章主要介绍了基于Spring Mvc实现的Excel文件上传下载示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    xingoo6522020-08-19
  • Java教程Java编程思想对象的容纳实例详解

    Java编程思想对象的容纳实例详解

    这篇文章主要介绍了Java编程思想对象的容纳实例详解,内容比较详细,涵盖的东西也比较多,具有参考价值,需要的朋友了解下。...

    鬼步9612021-01-05
  • Java教程全面解析Java8观察者模式

    全面解析Java8观察者模式

    这篇文章主要为大家全面解析Java8观察者模式,通过在 Java8 环境下实现观察者模式的实例,进一步介绍了什么是观察者模式、专业化及其命名规则,感兴趣...

    仲浩3462020-04-02
  • Java教程RabbitMQ 客户端源码系列 - Flow Controller 原理

    RabbitMQ 客户端源码系列 - Flow Controller 原理

    流控制是一个在计算机网络和网络软件中存在了几十年的概念。本质上,它是一种向发送方施加背压以避免接收方过载的机制。...

    Java架构师进阶编程6212022-04-21
  • Java教程java设计模式之抽像工厂详解

    java设计模式之抽像工厂详解

    这篇文章主要为大家详细介绍了java设计模式之抽像工厂的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    bateman698810282021-01-04
  • Java教程Java TreeSet 添加失败的解决

    Java TreeSet 添加失败的解决

    这篇文章主要介绍了Java TreeSet 添加失败的解决,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    予悦君兮善窈窕6442020-09-29