Spring Boot自动装配核心源码剖析

课程内容:
1.从spring IOC到springboot的原理
2.DeferredImportSelector对Bean的加载顺序的影响
3.SpringBoot自动配置源码深入分析
4.如何在自定义配置类上进行定制扩展
5.实现自定义starter完成自动配置

可以点击下面有道云笔记链接,格式可能更好看一些

有道云笔记链接

1.Springboot像什么:像一个脚手架
springboot只是帮助我们去配置Bean,也就是帮助我们去集成第三方框架的Bean,但是Bean的管理还是交给Spring
Spring的过程分成两部分:类---BeanDefinition---BeanFactory----Bean
BeanDefinition变成Bean利用的就是反射的原理
2.当每集成一个框架的时候,一般都是EnableXXXX,里面都是@Import
@Import分为三种:@Import(类) @Import(ImportSelector)@Impor(ImportBeanDefinitionRegistry)
3.我们有什么办法能批量注册Bean吗?
@Import(ImportSelector)可以吗?也可以也不可以。
可以。我们可以重写slector方法,返回数组的时候,里面包括类的路径名,Spring可以去扫描并加载
不可以。比如SqlSessionFactory,当我们自定义一个Bean SqlSessionFactory去扩展的时候,按常理是想加载我们自己自定义的,但是我们不能保证加载的顺序,所以就无法保证加载的是我们自定义的
这个时候我们就需要使用到ImportSelector的变种,也就是他的子类:DeferredImportSelector
利用DeferredImportSelector就可以加载自己定义的SqlSessionFactory,当加载到mybatis的时候,因为ConditionalOnBean,就不会去加载mybatis的SqlSessionFactory了
4.DeferredImportSelector是怎么做到的呢?
Deferred是延迟,推迟的意思,当我们都解析了所有的@Compoent@Bean等这些注解后,最后才去解析,就确保了使用的是我们自定义的SqlSessionFactory
5.实现DeferredImportSelector的步骤:
首先调用getImportGroup,如果返回的是null,就调用selectImports
如果返回的是实现了DeferredImportSelector.Group的Group,就调用Group的selectImports
Group组的作用就是SpringBoot在同一个组的Bean,可以实现组内对Bean调整顺序
6.因为SpringBoot中有很有的Bean,这些Bean的路径保存在jar包下Spring.factories中,DeferredImportSelector去读取,然后读取到selectImports的数组中,排序,返回给spring 并让其去加载成BeanDefinition
/***
 * 延迟 特性,  分组特性
 */
public class MyDeferredImportSelector implements DeferredImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{"cn.tulingxueyuan.beans.Person"};
    }

    @Override
    public Predicate<String> getExclusionFilter() {
        return null;
    }



   @Override
    public Class<? extends Group> getImportGroup() {
        // 这个返回值决定调用DeferredImportSelector.selectImports  如果null
        // 还是调用Group.selectImports
        return  MyGroup.class;
    }

    // 如果getImportGroup返回自定义Group , 会调用自定义Group的process方法
    // 如果getImportGroup返回 null,会调用DefaultDeferredImportSelectorGroup的process方法,即调用selectImports
    // 分组利用归类,同一组的bean只影响本组的顺序
    private static class MyGroup
            implements DeferredImportSelector.Group{

        AnnotationMetadata metadata;
        @Override
        public void process(AnnotationMetadata metadata, DeferredImportSelector selector) {
            this.metadata=metadata;
        }

        @Override
        public Iterable<Entry> selectImports() {
            List<Entry> list=new ArrayList<>();
            list.add(new Entry(this.metadata,"cn.tulingxueyuan.beans.Person"));
            return  list;
        }
    }

7.源码

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
}
}

点击@SpringBootApplication

```java
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
      @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {

点击@EnableAutoConfiguration

@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
点击@Import(AutoConfigurationImportSelector.class)
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
      ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
我们看到AutoConfigurationImportSelector实现了DeferredImportSelector
找getImportGroup,发现返回的是Group
@Override
public Class<? extends Group> getImportGroup() {
   return AutoConfigurationGroup.class;
}

点击AutoConfigurationGroup,找到process

@Override
public void process(AnnotationMetadata annotationMetadata, DeferredImportSelector deferredImportSelector) {
   Assert.state(deferredImportSelector instanceof AutoConfigurationImportSelector,
         () -> String.format("Only %s implementations are supported, got %s",
               AutoConfigurationImportSelector.class.getSimpleName(),
               deferredImportSelector.getClass().getName()));
   AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector)
         .getAutoConfigurationEntry(annotationMetadata);
   this.autoConfigurationEntries.add(autoConfigurationEntry);
   for (String importClassName : autoConfigurationEntry.getConfigurations()) {
      this.entries.putIfAbsent(importClassName, annotationMetadata);
   }
}

点击getAutoConfigurationEntry

protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
   if (!isEnabled(annotationMetadata)) {
      return EMPTY_ENTRY;
   }
   AnnotationAttributes attributes = getAttributes(annotationMetadata);
   List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
   configurations = removeDuplicates(configurations);
   Set<String> exclusions = getExclusions(annotationMetadata, attributes);
   checkExcludedClasses(configurations, exclusions);
   configurations.removeAll(exclusions);
   configurations = getConfigurationClassFilter().filter(configurations);
   fireAutoConfigurationImportEvents(configurations, exclusions);
   return new AutoConfigurationEntry(configurations, exclusions);
}

点击getCandidateConfigurations (作用获取所有的自动配置类)

获取的过程:

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
   List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
         getBeanClassLoader());
   Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you "
         + "are using a custom packaging, make sure that file is correct.");
   return configurations;
}

点击loadFactoryNames

public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
   String factoryTypeName = factoryType.getName();
   return loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
}

点击loadSpringFactories

private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
   MultiValueMap<String, String> result = cache.get(classLoader);
   if (result != null) {
      return result;
   }
   try {
      Enumeration<URL> urls = (classLoader != null ?
            classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
            ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
      result = new LinkedMultiValueMap<>();
      while (urls.hasMoreElements()) {
         URL url = urls.nextElement();
         UrlResource resource = new UrlResource(url);
         Properties properties = PropertiesLoaderUtils.loadProperties(resource);
         for (Map.Entry<?, ?> entry : properties.entrySet()) {
            String factoryTypeName = ((String) entry.getKey()).trim();
            for (String factoryImplementationName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
               result.add(factoryTypeName, factoryImplementationName.trim());
            }
         }
      }
      cache.put(classLoader, result);
      return result;
   }
   catch (IOException ex) {
      throw new IllegalArgumentException("Unable to load factories from location [" +
            FACTORIES_RESOURCE_LOCATION + "]", ex);
   }
}

在这里插入图片描述

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
   List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
         getBeanClassLoader());
   Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you "
         + "are using a custom packaging, make sure that file is correct.");
   return configurations;
}

点击getSpringFactoriesLoaderFactoryClass( )发现,只要key为EnableAutoConfiguration的value信息

protected Class<?> getSpringFactoriesLoaderFactoryClass() {
   return EnableAutoConfiguration.class;
}

在这里插入图片描述

public @interface EnableAutoConfiguration {

   String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

   Class<?>[] exclude() default {};
   String[] excludeName() default {};

}

第11行的内容:
去除的内容类似与
在这里插入图片描述

protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {if (!isEnabled(annotationMetadata)) {return EMPTY_ENTRY;}AnnotationAttributes attributes = getAttributes(annotationMetadata);List configurations = getCandidateConfigurations(annotationMetadata, attributes);configurations = removeDuplicates(configurations);Set exclusions = getExclusions(annotationMetadata, attributes);checkExcludedClasses(configurations, exclusions);configurations.removeAll(exclusions);configurations = getConfigurationClassFilter().filter(configurations);fireAutoConfigurationImportEvents(configurations, exclusions);return new AutoConfigurationEntry(configurations, exclusions);}

在这里插入图片描述

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值