java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Spring Boot 自动装配

Spring Boot 自动装配原理及 Starter 实现原理解析

作者:Jerry.ZZZ

SpringBoot通过@SpringBootApplication注解简化了依赖引入和配置,该注解包括@SpringBootConfiguration、@EnableAutoConfiguration和@ComponentScan三部分,感兴趣的朋友跟随小编一起看看吧

1、Situation

传统 Spring 引入依赖时需要用 XML 或 Java 显式配置,非常繁琐。

2、Target

方便快捷地引入依赖或者配置属性。

3、Action

3.1 @SpringBootApplication源码解析

@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 {
	@AliasFor(annotation = EnableAutoConfiguration.class)
	Class<?>[] exclude() default {};
	@AliasFor(annotation = EnableAutoConfiguration.class)
	String[] excludeName() default {};
	@AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
	String[] scanBasePackages() default {};
	@AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
	Class<?>[] scanBasePackageClasses() default {};
	@AliasFor(annotation = ComponentScan.class, attribute = "nameGenerator")
	Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;
	@AliasFor(annotation = Configuration.class)
	boolean proxyBeanMethods() default true;
}
--------------------------------------------------------
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
@Indexed
public @interface SpringBootConfiguration {
    @AliasFor(
        annotation = Configuration.class
    )
    boolean proxyBeanMethods() default true;
}
-------------------------------------------------------
@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 {};
}

主要有SpringBootConfiguration、EnableAutoConfiguration、ComponentScan三个注解构成。

3.2 AutoConfigurationImportSelector 源码

public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
	@Override
	public String[] selectImports(AnnotationMetadata annotationMetadata) {
		//1.判断自动装配开关是否打开
		if (!isEnabled(annotationMetadata)) {
			return NO_IMPORTS;
		}
		//2.获取所有需要装配的bean
		AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
		return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
	}
	protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
		//1.再次判断自动装配开关是否打开
		if (!isEnabled(annotationMetadata)) {
			return EMPTY_ENTRY;
		}
		//2.获取EnableAutoConfiguration注解中的 exclude 和 excludeName
		AnnotationAttributes attributes = getAttributes(annotationMetadata);
		//3.获取需要自动装配的所有配置类,读取META-INF/spring.factories
		//(不止读取当前项目中的META-INF文件,所有的依赖中的META-INF文件都会被读取)
		List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
		//4.删除重复依赖、过滤 exclude 的依赖
		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);
	}
	...
}
------------------------------------------------------
public interface DeferredImportSelector extends ImportSelector {
}
-------------------------------------------------------
public interface ImportSelector {
    String[] selectImports(AnnotationMetadata var1);
}

AutoConfigurationImportSelector 实现了 ImportSelector 的selectImports 方法,顾名思义就是筛选引入的依赖,那么就需要加载所有的依赖,以及条件,再根据条件对依赖进行筛选。

4、Result

通过 Spring Boot 启动类上的 @SpringBootApplication 注解,Spring 就可以遍历所有 META-INF 的 spring.factories 文件中的配置类,并根据 @EnableAutoConfiguration 的条件选择是否将其注册为 bean。

5、面试回答

启动类的@SpringBootApplication注解由@SpringBootConfiguration,@EnableAutoConfiguration,@ComponentScan三个注解组成,三个注解共同完成自动装配;

6、实现 Starter 的步骤

创建 Spring Boot 工程,添加项目需要的依赖,Spring Configuration Processor 这个依赖可以帮助开发者自动生成配置的的代码提示。

删除 pom.xml 的 build 部分

创建 Config 文件

在 resources 文件夹下新建 META-INF 文件夹,然后新建 spring.factories 文件,编写配置项为自动引入配置的类。

之后可以对这个项目打包,在其他的项目中通过pom.xml文件的坐标引入这个项目

在 AutoConfigurationImportSelector 中也可以发现com.example.demo.DemoConfiguration 类已经被成功加载了。

到此这篇关于Spring Boot 自动装配原理及 Starter 实现的文章就介绍到这了,更多相关Spring Boot 自动装配内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文