栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

springBoot自动装配原理

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

springBoot自动装配原理

springBoot项目自动装配核心注解就是@SpringBootApplication
我们点击@SpringBootApplication这是一个复合注解里面还有三个重要的注解
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan

@ComponentScan这个我们都知道是开启包扫描的,注入到IOC容器中(扫描的注解包括@Component} {@Repository}, {@Service}{@Autowired} or { @Controller )

我们重点说一下剩下的两个注解

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

}

他的核心类就是AutoConfigurationimportSelector
我们看一下它定义的变量 是不是很熟悉,BeanFactory(Bean工厂),Environment(proerty JVM环境变量)

可以看出,AutoConfigurationimportSelector 类实现了 importSelector接口,也就实现了这个接口中的 selectimports方法,该方法主要用于获取所有符合条件的类的全限定类名,这些类需要被加载到 IoC 容器中。
importSelector实现的处理方式通常与常规@import注释相同,但是,也可以推迟选择导入,直到所有@Configuration类都已处理完毕

这里最重要的方法就是

	protected AutoConfigurationEntry getAutoConfigurationEntry(Annotationmetadata annotationmetadata) {
		if (!isEnabled(annotationmetadata)) {
			return EMPTY_ENTRY;
		}
		AnnotationAttributes attributes = getAttributes(annotationmetadata);
		List configurations = getCandidateConfigurations(annotationmetadata, attributes);
		configurations = removeDuplicates(configurations);
		Set exclusions = getExclusions(annotationmetadata, attributes);
		checkExcludedClasses(configurations, exclusions);
		//移除掉需要排除的配置
		configurations.removeAll(exclusions);
		configurations = getConfigurationClassFilter().filter(configurations);
		fireAutoConfigurationimportEvents(configurations, exclusions);
		return new AutoConfigurationEntry(configurations, exclusions);
	}

我们继续看里面的getCandidateConfigurations方法

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

这里调用 SpringFactoriesLoader.loadFactoryNames方法
使用给定的类加载器从“meta-INF/spring.factories”加载给定类型的工厂实现的完全限定类名。
在这里插入图片描述

总结:
1.!isEnabled(annotationmetadata)判断spring.boot.enableautoconfiguration的属性值默认设置为true,可以自己在yml文件里面设置为false

2. getCandidateConfigurations(annotationmetadata, attributes);
扫描获取“meta-INF/spring.factories”下要加载的自动配置文件(这里是按需加载) 不懂的可以看下我另一篇文章
配置Spring Boot通过@ConditionalOnProperty来控制Configuration是否生效
3.getExclusions(annotationmetadata, attributes);
获取要排除的配置

@AutoConfigurationPackage
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@documented
@Inherited
@import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {

	
	String[] basePackages() default {};

	
	Class[] basePackageClasses() default {};

}

我们来看他的核心方法
我们可以看到他实现了importBeanDefinitionRegistrar接口
registerBeanDefinitions方法是扫描将@Configuration @import注解的类注入到IOC容器中

	static class Registrar implements importBeanDefinitionRegistrar, Determinableimports {

		@Override
		public void registerBeanDefinitions(Annotationmetadata metadata, BeanDefinitionRegistry registry) {
			register(registry, new Packageimports(metadata).getPackageNames().toArray(new String[0]));
		}

		@Override
		public Set determineimports(Annotationmetadata metadata) {
			return Collections.singleton(new Packageimports(metadata));
		}

	}
 


这里你们是不是想到了@compentscan注解不是也是用来扫描包的吗为什么还需要@AutoConfigurationPackage呢?

@compentscan和 @AutoConfigurationPackage的区别

1.@compentscan可以扫描除了根包还可以扫描其他的包但是@AutoConfigurationPackage不能

2.@compentscan和 @AutoConfigurationPackage扫描的范围不同

@compentscan可以扫描含有{@Component} {@Repository}, {@Service}{@Autowired}{
@Controller )

@AutoConfigurationPackage是扫描带有@Configuration @import注解的类

扩展spring yaml配置文件

以redis为例
@ConfigurationProperties
外部化配置的注释。如果要绑定和验证某些外部属性(例如从.Properties文件),请将其添加到@Configuration类中的类定义或@Bean方法中。 绑定可以通过调用带注释类上的setter来执行,如果使用@ConstructorBinding,则可以通过绑定到构造函数参数来执行。 请注意,与@Value相反,由于属性值是外部化的,所以不会计算SpEL表达式。

spring不会全部装配的原因
就是类似@ConditionalOnClass,@ConditionalOnMissingBean之类的注解,有兴趣的可以自己了解一下,我这里就不详细写了

转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号