广告位联系
返回顶部
分享到

Spring refresh()源码解析介绍

java 来源:互联网 作者:佚名 发布时间:2023-08-27 22:29:09 人浏览
摘要

正文 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. 初始

正文

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.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销毁之前)方法

详情:https://www.jb51.net/article/277948.htm

四、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);

   }

}


版权声明 : 本文内容来源于互联网或用户自行发布贡献,该文观点仅代表原作者本人。本站仅提供信息存储空间服务和不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权, 违法违规的内容, 请发送邮件至2530232025#qq.cn(#换@)举报,一经查实,本站将立刻删除。
原文链接 : https://juejin.cn/post/7202531472720789559
相关文章
  • jmap执行失败如何获取heapdump

    jmap执行失败如何获取heapdump
    在之前的OOM问题复盘中,我们添加了jmap脚本来自动dump内存现场,方便排查OOM问题。 但当我反复模拟OOM场景测试时,发现jmap有时可以dump成功
  • Spring refresh()源码解析介绍

    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, IllegalStateExcept
  • 线程阻塞唤醒工具LockSupport使用介绍
    LockSupport 简介 LockSupport是 Java 并发编程中一个非常重要的组件,我们熟知的并发组件Lock、线程池、CountDownLatch等都是基于AQS实现的,而AQS内
  • RocketMQ的存储模型全介绍
    RocketMQ有Producer、Consumer、NameSrv、Broker四个部分。其中Broker用于存储消息,维护消息队列和订阅关系,是RocketMQ四个部分中最重要的一个部分
  • 规则引擎Drools的应用介绍
    现在有这么个需求,网上购物,需要根据不同的规则计算商品折扣,比如VIP客户增加5%的折扣,购买金额超过1000元的增加10%的折扣等,而且
  • Spring populateBean属性赋值和自动注入
    protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { if (bw == null) { if (mbd.hasPropertyValues()) { throw new BeanCreationException( mb
  • ThreadPoolExecutor参数的用法及说明
    一、ThreadPoolExecutor核心参数说明 1、corePoolSize:核心线程数 * 核心线程会一直存活,及时没有任务需要执行 * 当线程数小于核心线程数时,即
  • springcloud gateway无法路由问题的解决
    现在企业微服务架构基本上都是用springcloud体系了,在国内基本上新项目都用springcloud alibaba,而且基本上都是所有服务聚合在一个父项目中
  • RocketMQ broker 消息投递流程处理PULL_MESSAGE请求解析
    RocketMq消息处理整个流程如下: 本系列RocketMQ4.8注释github地址,希望对大家有所帮助,要是觉得可以的话麻烦给点一下Star哈 消息接收:消息
  • idea搭建SSM框架遇踩的坑(附完整过程)
    首先说明这是我一个不熟悉idea和SSM框架的新手小白遇到的坑,适合用idea搭建SSM框架的小伙伴看一看,老鸟就不用看了。以下为详细步骤(傻
  • 本站所有内容来源于互联网或用户自行发布,本站仅提供信息存储空间服务,不拥有版权,不承担法律责任。如有侵犯您的权益,请您联系站长处理!
  • Copyright © 2017-2022 F11.CN All Rights Reserved. F11站长开发者网 版权所有 | 苏ICP备2022031554号-1 | 51LA统计