SpringBoot自动装配原理

SpringBoot自动装配原理

一、什么是自动装配

SpringBoot定义了一套接口规范,在这套规范中SpringBoot启动的时候会扫描外部导入的各种start中的META-INF/spring.factories文件,将文件中的配置信息加载到Spring容器中。即可以理解为:通过注解或者一些简单的配置就能在Spring Boot的帮助下实现某块功能

二、如何实现SpringBoot的自动装配

  1. 首先从SpringBoot的核心注解@SpringBootApplication入手
  2. 点击@SpringBootApplication可知该注解有以下注解组成:
//前四个是java的元注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited

//后三个是spring的注解
@SpringBootConfiguration  //类似于@Configuration表示该类是配置类
@EnableAutoConfiguration  //启用SpringBoot 的自动配置机制(核心)
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
		@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })  //扫描组件
  1. 重点分析@EnableAutoConfiguration注解:
    3.1@EnableAutoConfiguration组成:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage //将main包下所有组件注册到容器中
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {...}

3.2 重点分析AutoConfigurationImportSelector:自动加载配置类

public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
		ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered 

该类实现了DeferredImportSelector接口,因此实现了selectImports()方法,该方法主要用于获取所有符合条件的类的全限定类名,这些类需要被加载到 IoC 容器中。

public String[] selectImports(AnnotationMetadata annotationMetadata) {
		//判断自动装配开关是否打开
		if (!isEnabled(annotationMetadata)) {
			return NO_IMPORTS;
		}
		//获取所有需要装配的bean
		AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
		return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
	}

因此分析getAutoConfigurationEntry(annotationMetadata)方法

protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
	//1.判断是否可以自动装配(默认是true)
	if (!isEnabled(annotationMetadata)) {
		return EMPTY_ENTRY;
	}
	//2.获取EnableAutoConfiguration注解中的 exclude 和 excludeName
	AnnotationAttributes attributes = getAttributes(annotationMetadata);
	//3.从各个META-INF/spring.factories文件中获取到所有配置类
	List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
	configurations = removeDuplicates(configurations);
	Set<String> exclusions = getExclusions(annotationMetadata, attributes);
	checkExcludedClasses(configurations, exclusions);
	configurations.removeAll(exclusions);
	4.
	configurations = getConfigurationClassFilter().filter(configurations);
	fireAutoConfigurationImportEvents(configurations, exclusions);
	return new AutoConfigurationEntry(configurations, exclusions);

对以上2、3、4步dubug图示:
第二步:用于获取EnableAutoConfiguration注解中的 exclude 和 excludeName
在这里插入图片描述
第三步:从各个META-INF/spring.factories文件中获取到所有配置类
在这里插入图片描述
第四步:根据注解@ConditionalOnXXX进行过滤,满足条件的类才会生效
在这里插入图片描述
4. SpringBoot中常见的条件注解:

@ConditionalOnBean:当容器里有指定 Bean 的条件下
@ConditionalOnMissingBean:当容器里没有指定 Bean 的情况下
@ConditionalOnSingleCandidate:当指定 Bean 在容器中只有一个,或者虽然有多个但是指定首选Bean
@ConditionalOnClass:当类路径下有指定类的条件下
@ConditionalOnMissingClass:当类路径下没有指定类的条件下
@ConditionalOnProperty:指定的属性是否有指定的值
@ConditionalOnResource:类路径是否有指定的值
@ConditionalOnExpression:基于 SpEL 表达式作为判断条件
@ConditionalOnJava:基于 Java 版本作为判断条件
@ConditionalOnJndi:在 JNDI 存在的条件下差在指定的位置
@ConditionalOnNotWebApplication:当前项目不是 Web 项目的条件下
@ConditionalOnWebApplication:当前项目是 Web 项 目的条件下

三、实现自定义start

  1. 创建一个mycustomer-spring-boot-start模块,定义好Person类,PersonService、MyConfig这三个类
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  2. 在resources目录下创建一个META-INF目录,并创建一个spring.factories文件,仿照spring-boot-autoconfigure中的spring.factories文件去定义。
    在这里插入图片描述
  3. 通过maven中的install命令将模块进行打包,发布到本地仓库中。
  4. 测试,创建一个模块进行测试,引入刚才打成jar包的坐标。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值