SpringBoot自动配置

一、入口

@SpringBootApplication  // 自动装配注解
public class AutoConfigurationApplication {

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

}
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited  // 用来修饰注解,代表可继承
@SpringBootConfiguration  // 标识配置类,套用了Spring @Configuration 
@EnableAutoConfiguration  // 自动配置核心
@ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
...
}
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})  //关键类
public @interface EnableAutoConfiguration {
    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

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

    String[] excludeName() default {};
}
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import({Registrar.class})  // 关键类
public @interface AutoConfigurationPackage {
    String[] basePackages() default {};

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

二、Registrar

item --> @Component标识
demoConfig --> @Configuration标识
myTest --> @Bean标识
在这里插入图片描述

	// 就是包名.类名
	private static final String BEAN = AutoConfigurationPackages.class.getName();

	// 没有则注册
	public static void register(BeanDefinitionRegistry registry, String... packageNames) {
        if (registry.containsBeanDefinition(BEAN)) {
            AutoConfigurationPackages.BasePackagesBeanDefinition beanDefinition = (AutoConfigurationPackages.BasePackagesBeanDefinition)registry.getBeanDefinition(BEAN);
            beanDefinition.addBasePackages(packageNames);
        } else {
            registry.registerBeanDefinition(BEAN, new AutoConfigurationPackages.BasePackagesBeanDefinition(packageNames));
        }

    }

注册Bean的方法,随便点一个实现类看
用Map管理的,没有就put一个

	/**
		并发安全集合,put操作算是添加了
		以下是gpt回答:
		beanDefinitionMap 是 Spring 容器中存储 Bean 定义信息的一个数据结构,
		它是一个 ConcurrentHashMap 对象,用于存储 BeanDefinition 对象,
		其中键为 Bean 的名称,值为 Bean 的定义。Spring 容器会在启动时扫描所有的配置类,
		解析其中的 Bean 定义信息,并将其存储到 beanDefinitionMap 中,以便后续的实例化
		和依赖注入。通过 beanDefinitionMap,Spring 容器可以快速地查找 Bean 的定义信息,
		比如是否存在、是否是单例、是否延迟初始化等等。
	*/ 
	private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap(64);

在这里插入图片描述

三、AutoConfigurationImportSelector

核心方法

    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        if (!this.isEnabled(annotationMetadata)) {
            return NO_IMPORTS;
        } else {
        	// getAutoConfigurationEntry 点进去断点
            AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(annotationMetadata);
            return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
        }
    }

在这里插入图片描述

    protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
        if (!this.isEnabled(annotationMetadata)) {
            return EMPTY_ENTRY;
        } else {
            AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
            // 加载系统配置类
            List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
            // 配置类集合去重
            configurations = this.removeDuplicates(configurations);
            // exclude声明的类排除
            Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
            // 可以点进去看看,没必要断点了,configurations去掉排除的类
            this.checkExcludedClasses(configurations, exclusions);
            configurations.removeAll(exclusions);
            // 去除不必要的配置类,见四解析
            configurations = this.getConfigurationClassFilter().filter(configurations);
            /**
            	gpt对此方法解释:
            	这段代码的作用是通知所有的AutoConfigurationImportListener,
            	即自动配置导入监听器,当前应用程序已经导入了哪些自动配置类以及排除了哪些
            	自动配置类。这个方法会创建一个AutoConfigurationImportEvent事件,
            	然后通过调用每个监听器的onAutoConfigurationImportEvent方法,将该事件
            	传递给监听器。在事件传递之前,该方法还会通过调用invokeAwareMethods方法,
            	将当前的BeanFactory和ClassLoader等信息注入到每个监听器中。
            */
            this.fireAutoConfigurationImportEvents(configurations, exclusions);
            return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);
        }
    }
    protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
    	// 断点进去,读取META-INF/spring.factories文件
        List<String> configurations = new ArrayList(SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader()));
        /**
        	load()断点进去
        	读取META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件
        */  
        ImportCandidates.load(AutoConfiguration.class, this.getBeanClassLoader()).forEach(configurations::add);
        Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories nor in META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. If you are using a custom packaging, make sure that file is correct.");
        return configurations;
    }

META-INF/spring.factories
在这里插入图片描述
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
在这里插入图片描述

四、filter(configurations)

        List<String> filter(List<String> configurations) {
            long startTime = System.nanoTime();
            String[] candidates = StringUtils.toStringArray(configurations);
            boolean skipped = false;
            Iterator var6 = this.filters.iterator();

            int i;
            while(var6.hasNext()) {
                AutoConfigurationImportFilter filter = (AutoConfigurationImportFilter)var6.next();
                // 核心方法
                boolean[] match = filter.match(candidates, this.autoConfigurationMetadata);

                for(i = 0; i < match.length; ++i) {
                    if (!match[i]) {
                        candidates[i] = null;
                        skipped = true;
                    }
                }
            }

            if (!skipped) {
                return configurations;
            } else {
                List<String> result = new ArrayList(candidates.length);
                String[] var12 = candidates;
                int var14 = candidates.length;

                for(i = 0; i < var14; ++i) {
                    String candidate = var12[i];
                    if (candidate != null) {
                        result.add(candidate);
                    }
                }

                if (AutoConfigurationImportSelector.logger.isTraceEnabled()) {
                    int numberFiltered = configurations.size() - result.size();
                    AutoConfigurationImportSelector.logger.trace("Filtered " + numberFiltered + " auto configuration class in " + TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime) + " ms");
                }

                return result;
            }
        }
    }
    public boolean[] match(String[] autoConfigurationClasses, AutoConfigurationMetadata autoConfigurationMetadata) {
    	// report 记录用的
        ConditionEvaluationReport report = ConditionEvaluationReport.find(this.beanFactory);
        // 核心方法
        ConditionOutcome[] outcomes = this.getOutcomes(autoConfigurationClasses, autoConfigurationMetadata);
        boolean[] match = new boolean[outcomes.length];

        for(int i = 0; i < outcomes.length; ++i) {
            match[i] = outcomes[i] == null || outcomes[i].isMatch();
            if (!match[i] && outcomes[i] != null) {
                this.logOutcome(autoConfigurationClasses[i], outcomes[i]);
                if (report != null) {
                    report.recordConditionEvaluation(autoConfigurationClasses[i], this, outcomes[i]);
                }
            }
        }

        return match;
    }

OnClassCondition类

    protected final ConditionOutcome[] getOutcomes(String[] autoConfigurationClasses, AutoConfigurationMetadata autoConfigurationMetadata) {
        // 准备多线程判断了
        if (autoConfigurationClasses.length > 1 && Runtime.getRuntime().availableProcessors() > 1) {
            return this.resolveOutcomesThreaded(autoConfigurationClasses, autoConfigurationMetadata);
        } else {
            OnClassCondition.OutcomesResolver outcomesResolver = new OnClassCondition.StandardOutcomesResolver(autoConfigurationClasses, 0, autoConfigurationClasses.length, autoConfigurationMetadata, this.getBeanClassLoader());
            return outcomesResolver.resolveOutcomes();
        }
    }
	// 两个线程开搞
    private ConditionOutcome[] resolveOutcomesThreaded(String[] autoConfigurationClasses, AutoConfigurationMetadata autoConfigurationMetadata) {
        int split = autoConfigurationClasses.length / 2;
        OnClassCondition.OutcomesResolver firstHalfResolver = this.createOutcomesResolver(autoConfigurationClasses, 0, split, autoConfigurationMetadata);
        OnClassCondition.OutcomesResolver secondHalfResolver = new OnClassCondition.StandardOutcomesResolver(autoConfigurationClasses, split, autoConfigurationClasses.length, autoConfigurationMetadata, this.getBeanClassLoader());
        // 核心方法,最后一层,不套娃了
        ConditionOutcome[] secondHalf = secondHalfResolver.resolveOutcomes();
        ConditionOutcome[] firstHalf = firstHalfResolver.resolveOutcomes();
        ConditionOutcome[] outcomes = new ConditionOutcome[autoConfigurationClasses.length];
        System.arraycopy(firstHalf, 0, outcomes, 0, firstHalf.length);
        System.arraycopy(secondHalf, 0, outcomes, split, secondHalf.length);
        return outcomes;
    }

OnClassCondition类

在这里插入图片描述

五、常用的Conditional注解:

@ConditionalOnClass : classpath中存在该类时起效
@ConditionalOnMissingClass : classpath中不存在该类时起效
@ConditionalOnBean : DI容器中存在该类型Bean时起效
@ConditionalOnMissingBean : DI容器中不存在该类型Bean时起效
@ConditionalOnSingleCandidate : DI容器中该类型Bean只有一个或@Primary的只有一个时起效
@ConditionalOnExpression : SpEL表达式结果为true时
@ConditionalOnProperty : 参数设置或者值一致时起效
@ConditionalOnResource : 指定的文件存在时起效
@ConditionalOnJndi : 指定的JNDI存在时起效
@ConditionalOnJava : 指定的Java版本存在时起效
@ConditionalOnWebApplication : Web应用环境下起效
@ConditionalOnNotWebApplication : 非Web应用环境下起效

总结

1,先从
META-INF/spring.factories
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 加载配置类
2,再找到排除掉的类
3,排除掉没引入依赖的类
(反射jar包类全路径,引入了就装配,没引入的不装配)
4,加载的顺序是要被记录的

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码style

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值