⾯试题:SpringBoot⾃动装配原理
1. @SpringBootApplication注解
⾸先,我们都知道SpringBoot程序的⼊⼝是通过@SpringBootApplication注解修饰的⼀个类,例如:
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args){
SpringApplication.run(ConfigApplication.class, args);
}
}
那么这个⾃动装配的过程肯定就是通过@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 {
....
}
@SpringBootApplication这个注解其实是⼀个复合注解,主要由以下⼏个部分组成:
@Target⽤于设定注解使⽤范围,这⾥表明@SpringBootApplication注解可⽤于类或者接⼝上。@Retention表明是运⾏时注解,@Documented表明这个注解应该被 javadoc⼯具记录,@Inherited表明继承类也可以使⽤该注解;
@SpringBootConfiguraion表⽰要加载SpringBoot相关的⼀些配置;
@EnableAutoConfiguration注解⽤于⾃动装配,下⾯细讲;
@ComponentScan表明需要扫描的包;
2. @EnableAutoConfiguration注解
这⾥重点就是这个@EnableAutoConfiguration注解,它也是⼀个复合注解。看⼀下它的源码:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
....
}
(1)其中@Import(AutoConfigurationImportSelector.class)这个注解就是⽤于⾃动导⼊AutoConfigurationImportSelector这个类。
(2)然后AutoConfigurationImportSelector的selectImports()⽅法通过SpringFactoriesLoader.loadFactoryNames()扫描所有具有META-
INF/spring.factories的jar包。其实每⼀个可以⾃动装配的jar⾥都有⼀个这样的spring.factories⽂件。
(3)接着就根据这个spring.factories⽂件⾥配置的所有JavaConfig⾃动配置类的全限定名,到所有
对应的class,然后将所有⾃动配置类加载到Spring容器中。spring.factories⽂件⽰例如下:
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\springboot aop
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.cloud.CloudAutoConfiguration,\
org.springframework.t.ConfigurationPropertiesAutoConfiguration
....
3. l 配置加载
此外,我们通过l配置⽂件配置的<key,value>键值对属性是通过相关联的某个AutoConfiguration类,
(1)⽐如l中的server.port=8000这个配置,就是通过ServletWebServerFactoryAutoConfiguration类加载的,这个类就是专门加载Servlet相关配置的⼀个⾃动装配类。看⼀下它的源码:
@Configuration
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@ConditionalOnClass(ServletRequest.class)
@ConditionalOnWebApplication(type = Type.SERVLET)
@EnableConfigurationProperties(ServerProperties.class)
@Import({ ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class,
ServletWebServerFactoryConfiguration.EmbeddedTomcat.class,
ServletWebServerFactoryConfiguration.EmbeddedJetty.class,
ServletWebServerFactoryConfiguration.EmbeddedUndertow.class})
public class ServletWebServerFactoryAutoConfiguration {
......
}
(2)然后这个ServletWebServerFactoryAutoConfiguration类通过@EnableConfigurationProperties({ServerProperties.class})这个注解来将配置⽂件中的属性注⼊到ServerProperties中:
@ConfigurationProperties(prefix ="server", ignoreUnknownFields =true)
public class ServerProperties {
private Integer port;
......
}
(3)这个ServerProperties类的属性注⼊完成之后,⼜加载到了ServletWebServerFactoryAutoConfiguration类中,然后在SpringBoot启动时就可以获取到配置的端⼝号了。
THE END.

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。