前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >springboot源码解析(四)

springboot源码解析(四)

作者头像
写一点笔记
发布2020-09-10 15:46:44
3730
发布2020-09-10 15:46:44
举报
文章被收录于专栏:程序员备忘录程序员备忘录

之前通过debug的方式详细了解了SpringBoot启动的配置文件加载和容器初始化的相关的工作。但是对于核心的refresh()没有进行解析。而spring对于SpringApplication的准备工作的最终处理都是在refresh中执行的。所以深入理解refresh是理解spring的基础。而我们之前的学习为我们理解refresh打下了坚实的基础。甚至我们也猜测了后置处理器的工作方式,所以个人感觉理解refresh不会遇到特别难的地方。这里写一点个人学习的小经验。

首先我们认为兴趣是最好的老师这句话是正确的。可是对于一个人来说,他对所谓的兴趣并没有兴趣。那么问题就变成了有教无类和因人而异的两种教育教育理念。话虽说的很有道理,貌似都是极大的发挥了个人的天性并冒失实现了个人的价值。毫无疑问,如果按这种指导思想每个人都可以很伟大。但是现实在很大程度并不是这样,所谓人无完人,你所在乎的在别人看来并非如此。所以一切都是听天由命,不要被新闻的惨剧而担忧。不因自己的幸运而庆幸。所以真确的价值观是面对选择的根本执念。明白什么是核心什么是外表修饰。所以我的观点是:有教无类+因人而异。那么如何判断这两者的边界?你总不能做个两面派然后来回跳吧。其实这两者是有明确的边界的。我个人觉得有教无类是就是正确观的教育。因人而异则是个人优势的放大。很多人没有正确的价值观,无限放到的个人的优势的过程其实是没有什么意义。毕竟人还是要对主流思潮保持敬畏。那么在上边说的正确观的教育中如何培训那种兴趣?因人而异的特质是不需要刻意的引导的。所以问题的核心是如何培养那种这种关乎核心甚至决定一切的核心力量的兴趣上。第一点,要经常反思自己。反思的意义深远而悠长。第二,对于面对的挑战和问题,勇于提出自己的观点,这种观点建立在自己已知的是事情上,并尝试基于此解释现有的困难。第三,查看现有的资料,通过不断对比两种想法的差距,不断反思和自我鼓励。从而使得灵魂更上一个层次。

一不小心说了那么多话,其实我觉得相比技术来说,那些看似没有用的话,其实才是最有用的,当然说出来并不见的有用。正如一个人只能挣他认知范围内的钱一般,一时的思绪万千和急性的死记硬背都毫无意义。从某种意义上说我其实是在洗涤我自己。而观众的体验如何并非我关心的主体,虽然我希望我说的对大家有点用。

废话不说,开启我们的springBoot源码学习吧。

但是我们发现AbstractApplicationContext只是一个虚类,所以它的作用就是给子类一个限定的框架。所以看这块的代码要和子类结合起来。而这里说的的子类就是我们在SpringApplication中创建的content,也就是AnnotationConfigServletWebServerApplicationContext

代码语言:javascript
复制
//刷新容器之前做一些准备工作
  protected void prepareRefresh() {
    // 开始的时间 
    this.startupDate = System.currentTimeMillis();
    this.closed.set(false);
    this.active.set(true);
    if (logger.isDebugEnabled()) {
      if (logger.isTraceEnabled()) {
        logger.trace("Refreshing " + this);
      }
      else {
        logger.debug("Refreshing " + getDisplayName());
      }
    }
    // Initialize any placeholder property sources in the context environment.
    initPropertySources();
    // Validate that all properties marked as required are resolvable:
    // see ConfigurablePropertyResolver#setRequiredProperties
    getEnvironment().validateRequiredProperties();
    // Store pre-refresh ApplicationListeners...
    if (this.earlyApplicationListeners == null) {
      this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
    }
    else {
      // Reset local application listeners to pre-refresh state.
      this.applicationListeners.clear();
      this.applicationListeners.addAll(this.earlyApplicationListeners);
    }

    // Allow for the collection of early ApplicationEvents,
    // to be published once the multicaster is available...
    this.earlyApplicationEvents = new LinkedHashSet<>();
  }

这里我们发现abstrctApplicationContent是我们content的父类,通过idea定位发现initPropertySources其实是在GenericWebApplicationContext类中实现的。

通过定位debug,发现这里就是对一些属性的赋值

代码语言:javascript
复制
    protected void initPropertySources() {
        ConfigurableEnvironment env = this.getEnvironment();
        if (env instanceof ConfigurableWebEnvironment) {
            ((ConfigurableWebEnvironment)env).initPropertySources(this.servletContext, (ServletConfig)null);
        }
    }
代码语言:javascript
复制
    //这里的source就是我们解析的那6个配置文件
    //所以这块显然就是为了将配置文件的属性值来替换这里的name的value了。
    //因为我们在配置文件中并没有设置这两个值,因此这里的逻辑都没有执行
    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));
        }

    }

看完容器刷新的前置操作,那么我们看看obtainFreshBeanFactory();是做什么的。

代码语言:javascript
复制
      // Tell the subclass to refresh the internal bean factory.
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

代码很简洁,但是我们一眼就看的出来这里就是bean工厂呀,按照我们之前的解释,这里的bean工厂就是GenericWebApplicationContext类中的元素吧,那么我们看看是不是这么一回事。

代码语言:javascript
复制
  protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    refreshBeanFactory();
    return getBeanFactory();
  }

通过代码跟踪,这里的refreshBeanFactory调用了还是父类GenericWebApplicationContext方法。而这里的方法只是设置了容器被刷新的标志并没有做其他操作。因为之前已经创建好了bean工厂。如下图所示就是debug的结果,发现我们之前注入的bean还在该方法返回的工厂中。

那么prepareBeanFactory(beanFactory);是做什么工作的?从字面上理解就是对beanFactory做一些前置处理。

代码语言:javascript
复制
prepareBeanFactory(beanFactory);
代码语言:javascript
复制
  protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    //设置类加载器
    beanFactory.setBeanClassLoader(getClassLoader());
    //设置bean的类EL表达式解析器
    beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
    //设置属性解析器
    beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

    // 给beanFactory设置一个aware,用于后期的回调。
    beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
    //设置一些需要忽略的aware接口
    beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
    beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
    beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
    beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

    // BeanFactory interface not registered as resolvable type in a plain factory.
    // 给beanfactory设置一些解析
    beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
    beanFactory.registerResolvableDependency(ResourceLoader.class, this);
    beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
    beanFactory.registerResolvableDependency(ApplicationContext.class, this);

    // 设置一个bean的处理器
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

    // 添加一个代理解析bean
    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()));
    }

    // 注册环境变量
    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());
    }
  }

通过上述的一些操作也就是给beanfactory设置一些必要的功能。我们继续往下看

代码语言:javascript
复制
postProcessBeanFactory(beanFactory);

这里应该就是对哪些后置处理器的调用?

代码语言:javascript
复制
    protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        if (this.servletContext != null) {
        //ServletContextAwareProcessor
            beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext));
            //在注入的时候忽略ServletContextAware接口的bean
            beanFactory.ignoreDependencyInterface(ServletContextAware.class);
        }
//注册scopes的bean
        WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext);
     //注册环境变量的bean
        WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext);
    }

发现上述方法也并没有做过多的处理。我们继续推进。invokeBeanFactoryPostProcessors方法。

这里的getBeanFactoryPostProcessors就是获取我们SpringApplication类中读取spring.facotries类取得的初始化一些初始化类。但是这些类都有一个特点,那就是实现了initialize方法,在调用 this.applyInitializers(context)方法时就会代理产生一个后置处理器。也就是实现了BeanDefinitionRegistryPostProcessor接口的实体并注册到content中。而BeanDefinitionRegistryPostProcessor的类关系如图所示。

也就是说invokeBeanFactoryPostProcessors其实就是来调用这些后置处理器的。

代码语言:javascript
复制
  protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    //执行BeanFactoryPostProcessors
    PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors())
    //添加bean处理器器

    if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
      beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
      beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }
  }
代码语言:javascript
复制
  public static void invokeBeanFactoryPostProcessors(
      ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

    // Invoke BeanDefinitionRegistryPostProcessors first, if any.
    Set<String> processedBeans = new HashSet<>();
    //这里就是我们测试的demo的核心是BeanFactoryPostProcessor的子类。
    //我们测试的demo实现了BeanDefinitionRegistryPostProcessor
    //BeanDefinitionRegistry显然是被beanfactory实现d额接口
    if (beanFactory instanceof BeanDefinitionRegistry) {
      BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
      List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
      List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

      for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
      //如果实现了BeanDefinitionRegistryPostProcessor
        if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
          BeanDefinitionRegistryPostProcessor registryProcessor =
              (BeanDefinitionRegistryPostProcessor) postProcessor;
           //回调一下,然后将其添加熬队列中
          registryProcessor.postProcessBeanDefinitionRegistry(registry);
          registryProcessors.add(registryProcessor);
        }
        else {
        //否则就是实现了BeanFactoryPostProcessor
          regularPostProcessors.add(postProcessor);
        }
      }
      //从容器中拿哪些已经注册的bean
      List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

      // 这里通过迭代beanDefinitionMap去获取实现了BeanDefinitionRegistryPostProcessor接口的类
      String[] postProcessorNames =
          beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
      for (String ppName : postProcessorNames) {
        if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
          currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
          processedBeans.add(ppName);
        }
      }
      //排序
      sortPostProcessors(currentRegistryProcessors, beanFactory);
      registryProcessors.addAll(currentRegistryProcessors);
      //拿到beanDefinitionmap中的实现了BeanDefinitionProcesscors的接口进行调用
      invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
      currentRegistryProcessors.clear();

通过跟踪发现从beanDefinitionMap中获取的实现了BeanDefinitionProcesseor接口的之后一个类ConfigurationClassPostProcessor。这个类就是我们SpringApplication在context = this.createApplicationContext();方法中放到beanDefinitionmap中的。

那么这个类做了哪些工作?通过跟踪,发现该类就是用来解析的。当然解析一定会有很多关联,因此当代码运行完毕之后。代码相关的类都将注册到beanDefinitionMap中。

代码语言:javascript
复制
      //通过上边的运行,beanDefinitionMap中已经有很多用户自定义后置处理器了。这块就是处理这些的
      postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
      for (String ppName : postProcessorNames) {
      //如果有优先级的话加入
        if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
          currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
          processedBeans.add(ppName);
        }
      }
      //执行一下
      sortPostProcessors(currentRegistryProcessors, beanFactory);
      registryProcessors.addAll(currentRegistryProcessors);
      invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
      currentRegistryProcessors.clear();

    //获取所有的实现了接口统一进行执行
      boolean reiterate = true;
      while (reiterate) {
        reiterate = false;
        postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
        for (String ppName : postProcessorNames) {
          if (!processedBeans.contains(ppName)) {
            currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
            processedBeans.add(ppName);
            reiterate = true;
          }
        }
        sortPostProcessors(currentRegistryProcessors, beanFactory);
        registryProcessors.addAll(currentRegistryProcessors);
        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
        currentRegistryProcessors.clear();
      }

      // 执行postProcessBeanFactory
      invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
      //执行一下postProcessBeanDefinitionRegistry
      invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
    }

    else {
      // Invoke factory processors registered with the context instance.
      invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
    }

//获取BeanFactoryPostProcessor接口的类
    String[] postProcessorNames =
        beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
    List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
    List<String> orderedPostProcessorNames = new ArrayList<>();
    List<String> nonOrderedPostProcessorNames = new ArrayList<>();
    for (String ppName : postProcessorNames) {
      if (processedBeans.contains(ppName)) {
        // skip - already processed in first phase above
      }
      else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
       //优先级的处理器
        priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
      }
      else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
      //排序的处理器
        orderedPostProcessorNames.add(ppName);
      }
      else {
      //无须的处理器
        nonOrderedPostProcessorNames.add(ppName);
      }
    }

    // 执行优先级额处理器postProcessBeanFactory
    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

    // Next, invoke the BeanFactoryPostProcessors that implement Ordered.
    List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>();
    for (String postProcessorName : orderedPostProcessorNames) {
      orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    }
    //执行postProcessBeanFactory
    sortPostProcessors(orderedPostProcessors, beanFactory);
    invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

    // Finally, invoke all other BeanFactoryPostProcessors.
    List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
    for (String postProcessorName : nonOrderedPostProcessorNames) {
      nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    }
    // 执行postProcessBeanFactory
    invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
    //清空缓存
    beanFactory.clearMetadataCache();
  }

注:上述介绍均为作者的个人观点,如有不对,请指正。谢谢

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-09-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序员备忘录 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档