SpringBoot自动自动装配原理

1.默认启动类:

@SpringBootApplication //注解
public class SpringbootDemo02Application {

    public static void main(String[] args) {
         //启动了一个服务
        SpringApplication.run(SpringbootDemo02Application.class, args);
    }

}

2.进入@SpringBootApplication;下面是主要的注解,序号是自己加的方便理解。

1. @SpringBootConfiguration
2. @EnableAutoConfiguration
3. @ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
    // ......
}

2.1 @SpringBootConfiguration

作用:SpringBoot的配置类 ,标注在某个类上 ,表示这是一个SpringBoot的配置类;

看源码:点进@SpringBootConfiguration看到源码

1.//先点入@SpringBootConfiguration
@Configuration //表明是一个配置
@Indexed
public @interface SpringBootConfiguration {
    @AliasFor(
        annotation = Configuration.class
    )
    boolean proxyBeanMethods() default true;
}


2.//点进@Configuration ---->

 @Component //是spring的一个组件
public @interface Configuration {
    @AliasFor(
        annotation = Component.class
    )
    String value() default "";

    boolean proxyBeanMethods() default true;
}

(1)这里的 @Configuration,说明这是一个配置类 ,配置类就是对应Spring的xml 配置文件;

(2)里面的 @Component 这就说明,启动类本身也是Spring中的一个组件,负责启动应用!

2.2 @EnableAutoConfiguration

作用:开启自动配置功能

以前我们需要自己配置的东西,而现在SpringBoot可以自动帮我们配置 ;@EnableAutoConfiguration告诉SpringBoot开启自动配置功能,这样自动配置才能生效。

看源码:

@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

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

    String[] excludeName() default {};
}



//点击@AutoConfigurationPackage --->

@Import({Registrar.class})
public @interface AutoConfigurationPackage {
    String[] basePackages() default {};

    Class<?>[] basePackageClasses() default {};
}

@AutoConfigurationPackage:自动配置包

(1)点进:@AutoConfigurationPackage

                @Import({Registrar.class}): 给spring容器导入一个组件;

                Registrar.class : 将主启动类中的所有子包中的组件扫描到spring容器中;

(2)@Import({AutoConfigurationImportSelector.class}):

                  @Import({Registrar.class}): 给spring容器导入一个组件;

                  AutoConfigurationImportSelector.class :自动导入选择器

  (3)   AutoConfigurationImportSelector.class选择器中的一个类

        (a)getCandidateConfigurations类

  protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
        List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.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;
    }

        (b)getCandidateConfigurations类调用了loadFactoryNames类

public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
        ClassLoader classLoaderToUse = classLoader;
        if (classLoader == null) {
            classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
        }

        String factoryTypeName = factoryType.getName();
        return (List)loadSpringFactories(classLoaderToUse).getOrDefault(factoryTypeName, Collections.emptyList());
    }

        (c):loadFactoryNames类 去调用了 loadSpringFactories类;getResources("META-INF/spring.factories")得到了spring.factories

 private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) {
        Map<String, List<String>> result = (Map)cache.get(classLoader);
        if (result != null) {
            return result;
        } else {
            HashMap result = new HashMap();

            try {
                Enumeration urls = classLoader.getResources("META-INF/spring.factories");

                while(urls.hasMoreElements()) {
                    URL url = (URL)urls.nextElement();
                    UrlResource resource = new UrlResource(url);
                    Properties properties = PropertiesLoaderUtils.loadProperties(resource);
                    Iterator var6 = properties.entrySet().iterator();

                    while(var6.hasNext()) {
                        Entry<?, ?> entry = (Entry)var6.next();
                        String factoryTypeName = ((String)entry.getKey()).trim();
                        String[] factoryImplementationNames = StringUtils.commaDelimitedListToStringArray((String)entry.getValue());
                        String[] var10 = factoryImplementationNames;
                        int var11 = factoryImplementationNames.length;

                        for(int var12 = 0; var12 < var11; ++var12) {
                            String factoryImplementationName = var10[var12];
                            ((List)result.computeIfAbsent(factoryTypeName, (key) -> {
                                return new ArrayList();
                            })).add(factoryImplementationName.trim());
                        }
                    }
                }

                result.replaceAll((factoryType, implementations) -> {
                    return (List)implementations.stream().distinct().collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList));
                });
                cache.put(classLoader, result);
                return result;
            } catch (IOException var14) {
                throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var14);
            }
        }
    }

        (d):查找spring.factories文件

      (f):我们根据源头打开spring.factories , 看到了很多自动配置的文件;这就是自动配置根源。

2.3 @ComponentScan:

这个注解在Spring中,它对应XML配置中的元素。

作用:自动扫描并加载符合条件的组件或者bean , 将这个bean定义加载到IOC容器中

3.结论:

  1. SpringBoot在启动的时候从类路径下的META-INF/spring.factories中获取EnableAutoConfiguration指定的值

  2. 将这些值作为自动配置类导入容器 , 自动配置类就生效 , 帮我们进行自动配置工作;

  3. 整个J2EE的整体解决方案和自动配置都在springboot-autoconfigure的jar包中;

  4. 它会给容器中导入非常多的自动配置类 (xxxAutoConfiguration), 就是给容器中导入这个场景需要的所有组件 , 并配置好这些组件 ;

  5. 有了自动配置类 , 免去了我们手动编写配置注入功能组件等的工作;

资料来源(狂神说博客)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值