【面试必问】彻底搞懂Spring Boot自动装配原理及自定义starter

掘金链接:https://juejin.cn/post/7177731868471590968/

一  Spring boot 组件自动装配

      在Spring boot框架中,我们可以不必配置xml文件,就能完成Bean注入IOC的动作。这在之前的Spring是通过xml配置来说明要装配的组件,Spring boot为了简化开发人员的配置工作,遵循"约定大于配置,配置大于编码"原则,

通过约定来实现IOC的注入,通过默认配置来代替常规的配置,从而简化了开发人员的配置和开发过程,提升研发效率。

二 Spring boot 如何实现自动装配

      整体流程是@EnableAutoConfiguration中的实现类扫描“classpath下即Pom依赖”中所有包含/META-INF/spring.factories的包,并根据其xxxAutoConfiguration和/META-INF/spring-autoconfigure-metadata.properties中的条件判断来决定是否进行自动装配。

主类设置如下

@SpringBootApplication(exclude={DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class})
@EnableScheduling
@EnableConfigurationProperties({GlobalConfig.class})
public class ProxyApplication {
    public static void main(String[] args) {
        SpringApplication.run(ProxyApplication.class, args);
    }
}

我们知道,注解SpringBootApplication是一系列注解的组合,其中包含@EnableAutoConfiguration注解

@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 {}

而根据@Enable模块驱动设计模式即Import的类被@Configuration注解或实现ImportSelector接口,可实现注入),@EnableAutoConfiguration必然Import了“实现ImportSelector接口的实现类”,并实现其selectImport方法

// 1. Import了AutoConfigurationImportSelector类
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)  
public @interface EnableAutoConfiguration {
}

//2. 实现了DeferredImportSelector接口,并重写selectImports方法
public class AutoConfigurationImportSelector
		implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware,
		BeanFactoryAware, EnvironmentAware, Ordered {
}


//3. 继承ImportSelector接口
public interface DeferredImportSelector extends ImportSelector {}

基于@Enable和selectImports装配的方式我们知道,通过selectImports方法返回需要装配的对象数组,整个搜索流程如下:

	@Override
	public String[] selectImports(AnnotationMetadata annotationMetadata) {
		if (!isEnabled(annotationMetadata)) {
			return NO_IMPORTS;
		}
		AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
				.loadMetadata(this.beanClassLoader);//1. 获取classpath下自动加载配置的元数据
		AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(
				autoConfigurationMetadata, annotationMetadata);
		return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
	}

    protected AutoConfigurationEntry getAutoConfigurationEntry(
			AutoConfigurationMetadata autoConfigurationMetadata,
			AnnotationMetadata annotationMetadata) {
		if (!isEnabled(annotationMetadata)) {
			return EMPTY_ENTRY;
		}
		AnnotationAttributes attributes = getAttributes(annotationMetadata);//2.获取注解的属性信息
		List<String> configurations = getCandidateConfigurations(annotationMetadata,
				attributes);//3. 获取classpath下所有enable的候装配组件
		configurations = removeDuplicates(configurations); //4. 组件去重
		Set<String> exclusions = getExclusions(annotationMetadata, attributes);//5. exclude去重
		checkExcludedClasses(configurations, exclusions);//6. 组件去exclude
		configurations.removeAll(exclusions);//6. 组件去exclude
		configurations = filter(configurations, autoConfigurationMetadata);//7. 组件过滤
		fireAutoConfigurationImportEvents(configurations, exclusions);//8. 触发自动装配监听
		return new AutoConfigurationEntry(configurations, exclusions);
	}

整体流程:

1. 获取自动加载配置的元数据:主要是获取classpath下所有META-INF/spring-autoconfigure-metadata.properties中的配置信息,该文件里面配置的作用等同于在xxxAutoConfiguration上面的@ConditionalOnClass等注解,这么做的好处就是参考官网说明(Spring Boot uses an annotation processor to collect the conditions on auto-configurations in a metadata file (META-INF/spring-autoconfigure-metadata.properties). If that file is present, it is used to eage

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值