- 一、常见注解
- 二、Spring Boot 的自动配置原理
- 2.1、流程分析
- 2.2、总结
# 使用 Spring 快速注册 @ConfigurationProperties 注释的 bean 的便捷方法。
# 无论这个值如何(value属性的值),标准 Spring Beans 也将被扫描(注册进IoC容器中)。
# 默认注册的 bean 的 id 格式为:@ConfigurationProperties属性prefix的值-类名全限定名( student-com.ccbx.pojo.Student )
@EnableConfigurationProperties(value = {Student.class})
#仅仅在当前上下文中存在某个对象时,才会实例化一个Bean
@ConditionalOnBean
#某个class位于类路径上(或引入jar包的根目录下),才会实例化一个Bean
@ConditionalOnClass
#该注解来控制@Configuration是否生效.
# prefix :为application.yml配置文件中的前缀,
# name :为application.yml配置文件中的属性的名字
# havingValue :name属性的值与配置的值对比值,当两个值相同返回true,配置类生效;反之不生效
@ConditionalOnProperty
#当表达式为true的时候,才会实例化一个Bean
@ConditionalOnexpression
#仅仅在当前上下文中不存在某个类型的对象(name属性指定bean的名称)时,
# 该注解修饰的带有@Bean注解的方法才会执行,才会实例化一个Bean
@ConditionalOnMissingBean(name = "exampleBean")
#某个class类路径上不存在的时候,才会实例化一个Bean
@ConditionalOnMissingClass
二、Spring Boot 的自动配置原理
2.1、流程分析
Spring Boot 的启动类
@SpringBootApplication
public class SpringbootDemoApplication {
public static void main(String[] args) {
//作用:可用于从 Java 主方法引导和启动 Spring 应用程序的类。
//默认情况下,类将执行以下步骤来引导您的应用程序:
// 1、创建一个合适的ApplicationContext实例(取决于你的类路径)
// 2、注册CommandLinePropertySource以将命令行参数公开为 Spring 属性
// 3、刷新应用程序上下文,加载所有单例 bean
// 4、触发任何CommandLineRunner bean
SpringApplication.run(SpringbootDemoApplication.class, args);
}
}
@SpringBootApplication 注解源码
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@documented
@Inherited
//表示一个类提供了 Spring Boot 应用程序@Configuration 。
@SpringBootConfiguration
//启用 Spring 应用程序上下文的自动配置,尝试猜测和配置您可能需要的 bean。 自动配置类通常根据您的类路径和您定义的 bean 来应用。
@EnableAutoConfiguration
//配置用于Configuration类的组件扫描指令。
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
//这是一个方便的注解,相当于声明了@Configuration 、 @EnableAutoConfiguration 和 @ComponentScan 。
//@SpringBootApplication注解将主配置类(即@SpringBootApplication标注的类)的所在包及子包里面所有组件扫描加载到Spring容器
//省略属性
}
@EnableAutoConfiguration 注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@documented
@Inherited
//使用AutoConfigurationPackages注册包。 当没有指定base packages或base package classes ,注解类的包被注册。
@AutoConfigurationPackage
@import(AutoConfigurationimportSelector.class)
public @interface EnableAutoConfiguration {
//启用 Spring应用程序上下文的自动配置,尝试猜测和配置您可能需要的 bean。自动配置类通常根据您的类路径和您定义的 bean 来应用。
//省略属性
}
AutoConfigurationimportSelector.java 类中的方法
该类的作用:去spring-boot-autoconfigure 目录下的路径里读取EnableAutoConfiguration 注解所在包及其子包下的需要实现自动加载装配的类,实例化后放入IOC容器中,这个过程也加载了常见的第三方组件的配置类。
public class AutoConfigurationimportSelector implements DeferredimportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
//省略其它部分代码
//得到应该导入的类全限定名称的数组【重点】
@Override
public String[] selectimports(Annotationmetadata annotationmetadata) {
if (!isEnabled(annotationmetadata)) {
return NO_importS;
}
//得到应该导入的自动配置
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationmetadata);
//返回包含类名的数组
//返回需要的类的全类名;是在 spring.factories 配置文件中的 @EnableAutoConfiguration 注解关联的xx自动配置类的全限定名称
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
//得到应该导入的自动配置
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);
}
//得到spring.factories配置中EnableAutoConfiguration 指定的值:即全部的候选自动装配的类的名称列表集合
protected List getCandidateConfigurations(Annotationmetadata metadata, AnnotationAttributes attributes) {
//框架内内部使用的通用工厂加载机制。
//SpringFactoriesLoader从“meta-INF/spring.factories”文件加载和实例化给定类型的工厂,这些文件可能存在于类路径中的多个 JAR 文件中。
//loadFactoryNames():该方法使用给定的类加载器从"meta-INF/spring.factories"加载 给定类型的工厂实现的完全限定类名。
//spring.factories文件必须是Properties格式,其中 key 是接口或抽象类的完全限定名称,value 是逗号分隔的实现类名称列表。
List configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
getBeanClassLoader());
//Assert :帮助验证参数的断言实用程序类。
//notEmpty(参数1,参数2) :参数1是要检查的集合;参数2是断言失败时使用的异常消息(也就是说如果集合为null或size=0,就抛出的异常消息)
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;
}
//省略其它部分代码
}
加载并装配的目标文件 meta-INF/spring.factories 的位置如下:
在Spring Boot的启动类中,有一个main方法运行了一个SpringApplication.run(SpringbootDemoApplication.class, args);方法,在run方法中必须要传入一个被@SpringBootApplication注解的类。
随后解析@SpringBootApplication 注解,该注解启用了上下文bean的自动装配注解@EnableAutoConfiguration,随后解析该注解;该注解通过@import注解引入了一个类AutoConfigurationimportSelector 类;该类的一个主要方法 selectimports() 该方法的作用是通过去spring-boot-autoconfigure 目录下的路径里读取EnableAutoConfiguration 注解所在包及其子包下的需要实现自动加载装配的类(xxxAutoConfiguration 可自动装配类)的全限定类名,然后通过反射创建所需自动装配的类,并在实例化后放入IOC容器中,这个过程也加载了常见的第三方组件的配置类。



