欢迎访问悦橙教程(wld5.com),关注java教程。悦橙教程  java问答|  每日更新
页面导航 : > > 文章正文

Spring refresh()源码解析,

来源: javaer 分享于  点击 9587 次 点评:252

Spring refresh()源码解析,


目录
  • 正文
  • 一、prepareRefresh:初始化前的预处理
    • 1.1初始化属性值
    • 1.2属性校验
  • 二、obtainFreshBeanFactory:刷新Bean工厂
    • 三、prepareBeanFactory:Bean工厂预处理
      • 3.1 ApplicationContextDProcessor:Aware执行器
      • 3.2 registerResolvableDependency:自动注入的支持
      • 3.3 添加监听器执行器
    • 四、BeanFactory的后置处理
      • 4.1 后置处理bean工厂
        • 4.1.1 WebApplicationContextServletContextAwareProcessor
        • 4.1.2 registerWebApplicationScopes 注册web的应用域

    正文

    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:初始化前的预处理

    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初始化属性值

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

    protected void initPropertySources() {
    }
    

    Web容器GenericWebApplicationContext重写了此方法

    protected void initPropertySources() {
        //获取环境信息
       ConfigurableEnvironment env = getEnvironment();
       //判断是否是web配置环境
       if (env instanceof ConfigurableWebEnvironment) {
          ((ConfigurableWebEnvironment) env).initPropertySources(this.servletContext, null);
       }
    }
    

    最终由StandardServletEnvironment进行初始化

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

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

    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属性校验

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

    public void validateRequiredProperties() throws MissingRequiredPropertiesException {
       this.propertyResolver.validateRequiredProperties();
    }
    

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

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

    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;
       }
    }
    

    案例: 资源文件

    name=zhansan
    age=${name},10
    encoding=utf-8
    name2=${name}
    

    测试代码

        @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工厂

    protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
       //2.1刷新Bean工厂
       refreshBeanFactory();
       return getBeanFactory();
    }
    

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

    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工厂预处理

    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初始化前会执行当前方法

    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中

    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:自动注入的支持

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

    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实现

    protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    }
    

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

    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工厂中注入了一个执行器

    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初始化前执行)

    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的应用域

    // 所在类及方法:ServletWebServerApplicationContext#registerWebApplicationScopes
       private void registerWebApplicationScopes() {
              ExistingWebApplicationScopes existingScopes = new ExistingWebApplicationScopes(getBeanFactory());
              WebApplicationContextUtils.registerWebApplicationScopes(getBeanFactory());
              existingScopes.restore();
        }
    

    ExistingWebApplicationScopes是ServletWebServerApplicationContext类中的一个静态类

    源码如下:

        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了,源码如下

        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()的资料请关注3672js教程其它相关文章!

    您可能感兴趣的文章:
    • Spring Cloud动态配置刷新RefreshScope使用示例详解
    • Spring中的refresh方法分析
    • Java Spring的refresh方法你知道吗
    • Springboot使用@RefreshScope注解实现配置文件的动态加载
    • SpringCloud的@RefreshScope 注解你了解吗
    相关栏目:

    用户点评