一.什么是SpringBoot的自动装配
我们现在提到自动装配的时候,一般会和 Spring Boot 联系在一起。但是,实际上 Spring Framework 早就实现了这个功能。Spring Boot 只是在其基础上,通过 SPI 的方式,做了进一步优化。 SpringBoot 定义了一套接口规范,这套规范规定:SpringBoot 在启动时会扫描外部引用 jar 包中的META-INF/spring.factories
文件,将文件中配置的类型信息加载到 Spring 容器,并执行类中定义的各种操作。对于外部 jar 来说,只需要按照 SpringBoot 定义的标准,就能将自己的功能装置进 SpringBoot。没有 Spring Boot 的情况下,如果我们需要引入第三方依赖,需要手动配置,非常麻烦。但是,Spring Boot 中,我们直接引入一个 starter 即可。比如你想要在项目中使用 redis 的话,直接在项目中引入对应的 starter 即可。
二、SpringBoot 是如何实现自动装配的?
要想了解SpringBoot是如何实现自动装配的我们就需要深入了解一下@SpringBootApplication这个注解,
@ComponentScan 这个注解在Spring中很重要 ,它对应XML配置中的元素。 作用:自动扫描并加载符合条件的组件或者bean , 将这个bean定义加载到IOC容器中;
@SpringBootConfiguration 作用:SpringBoot的配置类 ,标注在某个类上 , 表示这是一个SpringBoot的配置类;
//@SpringBootConfiguration注解内部
//这里的 @Configuration,说明这是一个配置类 ,配置类就是对应Spring的xml 配置文件;
@Configuration
public @interface SpringBootConfiguration {}
//里面的 @Component 这就说明,启动类本身也是Spring中的一个组件而已,负责启动应用
@Component
public @interface Configuration {}
@EnableAutoConfiguration开启自动配置功能 以前我们需要自己配置的东西,而现在SpringBoot可以自动帮我们配置 ;@EnableAutoConfiguration 告诉SpringBoot开启自动配置功能,这样自动配置才能生效;
@Import({AutoConfigurationImportSelector.class}) :给容器导入组件 ;
AutoConfigurationImportSelector :自动配置导入选择器,给容器中导入一些组件
AutoConfigurationImportSelector.class
↓
selectImports方法
↓
this.getAutoConfigurationEntry(annotationMetadata)方法
↓
this.getCandidateConfigurations(annotationMetadata, attributes)方法
↓
方法体: List configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass (), this.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;
↓
在所有包名叫做autoConfiguration的包下面都有META-INF/spring.factories文件
总结原理: @EnableAutoConfiguration 注解内部使用 @Import(AutoConfigurationImportSelector.class)来 加载配置类。 配置文件位置:META-INF/spring.factories,该配置文件中定义了大量的配置类,当 SpringBoot 应用启动时,会自动加载这些配置类,初始化Bean 并不是所有的Bean都会被初始化,在配置类中使用Condition来加载满足条件的Bean
三.@Import注解的用法
@Import
是Spring
基于 Java 注解配置的主要组成部分。@Import
注解提供了@Bean
注解的功能,同时还有原来Spring
基于 xml 配置文件里的<import>
标签组织多个分散的xml文件的功能,当然在这里是组织多个分散的@Configuration
的类。
下面将分别说明@Import
注解的功能。
(1). 引入其他的@Configuration
可以传入配置类的class对象引入其他的配置类
(2). 直接初始化其他类的Bean
在Spring 4.2之后,@Import
可以直接指定实体类,加载这个类定义到context
中。 例如把代码中的ConfigA
的@Import
修改为@Import(Service.class)
,就会生成Service
的Bean
到容器上下文中。
(3). 指定实现ImportSelector
(以及DefferredServiceImportSelector
)的类,用于个性化加载
指定实现ImportSelector
的类,通过AnnotationMetadata
里面的属性,动态加载类。AnnotationMetadata
是Import
注解所在的类属性(如果所在类是注解类,则延伸至应用这个注解类的非注解类为止)。需要实现selectImports
方法,返回要加载的@Configuation
或者具体Bean
类的全限定名的String
数组。
(4).指定实现ImportBeanDefinitionRegistrar
的类,用于个性化加载
与ImportSelector
用法与用途类似,但是如果我们想重定义Bean
,例如动态注入属性,改变Bean
的类型和Scope
等等,就需要通过指定实现ImportBeanDefinitionRegistrar
的类实现。
SpringBoot便是利用指定实现ImportSelector来
加载配置类
四.Conditional
Condition 是在Spring 4.0 增加的条件判断功能,通过这个可以功能可以实现选择性的创建 Bean 操作。
自定义条件:
① 定义条件类:自定义类实现Condition接口,重写 matches 方法,在 matches 方法中进行逻辑判 断,返回 boolean值 。
matches 方法两个参数:
• context:上下文对象,可以获取属性值,获取类加载器,获取BeanFactory等。
• metadata:元数据对象,用于获取注解属性。
② 判断条件: 在初始化Bean时,使用 @Conditional(条件类.class)注解 SpringBoot 提供的常用条件注解:
ConditionalOnProperty:判断配置文件中是否有对应属性和值才初始化Bean
ConditionalOnClass:判断环境中是否有对应字节码文件才初始化Bean
ConditionalOnMissingBean:判断环境中没有对应Bean才初始化Bean
ConditionalOnBean:判断环境中有对应Bean才初始化Bean