SpringBoot2自动装配


title: SpringBoot2.StartProcess.自动装配

自动装配提纲

  • 自动装配BeanDefinetions
  • 自动配置

这里的主要逻辑其实还是在SpringFrame里面实现
并没有多少特殊的地方
咱们继续进入到AbstarctApplicationContext的refresh方法中去看看
SpringBoot的这一块具体加载BeanDefinetions主要在invokeBeanFactoryPostProcessors该方法中
加载完了之后进行实例化就实现了自动化配置
所以咱们主要看加载BeanDefinetions
并且Spring代码的执行都是一环扣一环,相当的紧凑不会出现两个毫无关联的逻辑放在一个方法里面的情况

自动装配BeanDefinetions

说到自动装配咱们就得看看
invokeBeanFactoryPostProcessors方法
这方法看上去很长其实做的事情很简单大过程其实就做了两步
1.处理Spring.factories中加载进来的process,将ConfigurationClassPostProcessor注册。当然还有一些其他的操作,不过可以先不管那些。
2.使用ConfigurationClassPostProcessor去parse解析注解类

看下具体的代码

//这里是第一步
if (beanFactory instanceof BeanDefinitionRegistry) {
      BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
      List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
      List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

      for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
        if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
          BeanDefinitionRegistryPostProcessor registryProcessor =
              (BeanDefinitionRegistryPostProcessor) postProcessor;
          //主要逻辑注册ConfigurationClassPostProcessor,这个bean是在SpringApplication的构造函数中初始化进去的。
          registryProcessor.postProcessBeanDefinitionRegistry(registry);
          registryProcessors.add(registryProcessor);
        }
        else {
          regularPostProcessors.add(postProcessor);
        }
      }

//这里是第二步,执行ConfigurationClassPostProcessor
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);

上面的代码就完成了具体的两个步骤咱们继续进入到process里面看看具体怎么加载

  /**
   * Invoke the given BeanDefinitionRegistryPostProcessor beans.调用bean的方法
   * 咱们看下postProcessBeanDefinitionRegistry方法里面的具体执行逻辑processConfigBeanDefinitions方法
   */
  private static void invokeBeanDefinitionRegistryPostProcessors(
      Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {

    for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
      postProcessor.postProcessBeanDefinitionRegistry(registry);
    }
  }

在processConfigBeanDefinitions这个方法里面首先做的一件事情其实就是通过
SpringBoot的启动配置类进行解析,里面有一个具体的实现方法parse。该方法实现类在ConfigurationClassParser
咱们进去看一眼

  public void parse(Set<BeanDefinitionHolder> configCandidates) {
    this.deferredImportSelectors = new LinkedList<>();

    for (BeanDefinitionHolder holder : configCandidates) {
      BeanDefinition bd = holder.getBeanDefinition();
      try {
        if (bd instanceof AnnotatedBeanDefinition) {
          //解析注解配置类,从启动类里面配置的那个配置类开始。一直循环直到结束。
          parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
        }
        else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
          parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
        }
        else {
          parse(bd.getBeanClassName(), holder.getBeanName());
        }
      }
      catch (BeanDefinitionStoreException ex) {
        throw ex;
      }
      catch (Throwable ex) {
        throw new BeanDefinitionStoreException(
            "Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
      }
    }
    //传说中的SpringBoot八爪鱼,通过SPI去获取各个自动配置具体实现类。
    processDeferredImportSelectors();
  }


上面的方法分为两步
1.加载项目中的注解beanDefiniton
2.加载自动配置的beanDefiniton

第一步的实现代码
在doProcessConfigurationClass里面
具体做了下面三件事
1.处理PropertySource注解
2.处理ComponentScan注解
3.处理Import注解
做完上面三件事,咱们项目里面的bean以及import进来的class就都将信息注册到了BeanDefinitons,可以用于后面的实例化

咱们再看一眼
processDeferredImportSelectors这个方法加载外部配置类,实现自动配置。
其实就是通过EnableAutoConfiguration注解中import进来的AutoConfigurationImportSelector类去处理
执行里面的selectImports方法,然后去Spring.factories中加载EnableAutoConfiguration的配置类。还是通过Springle中实现的SPI。

做完上面这些操作基本整个流程就结束了

##自动配置

咱们看一个mybatis-plus的配置类的代码

@Configuration//标明这是一个配置类
@ConditionalOnClass({SqlSessionFactory.class, SqlSessionFactoryBean.class})//存在上面两个classs的时候执行
@ConditionalOnSingleCandidate(DataSource.class)//datasource是单例
@EnableConfigurationProperties(MybatisPlusProperties.class)//配置类
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
public class MybatisPlusAutoConfiguration {

//其实就是通过上面这些注解的使用执行相应的逻辑,所以如果咱们觉得自带的配置不好用
//完全可以自己覆盖,然后实现一个自己的

欢迎扫码加入知识星球继续讨论
avatar

你可能感兴趣的:(SpringBoot2自动装配)