自动装配
源码分析
SpringBootApplication注解分析
@Target({ElementType.TYPE}) //标注位置: 类 接口 @Retention(RetentionPolicy.RUNTIME) // 保留策略 运行时代码 @Documented // 生成JavaDoc @Inherited //运行被继承 @SpringBootConfiguration // 相当于@Configuration 表示这是一个配置类 @EnableAutoConfiguration // 借助@Import的支持,将所有符合自动配置条件的bean定义加载到IoC容器 @ComponentScan(...) // 注解扫描 扫描的是当前类所在包及其子包中类中的注解 public @interface SpringBootApplication {}
@EnableAutoConfiguration注解分析
@AutoConfigurationPackage // 获取注解扫描的包路径 @Import({AutoConfigurationImportSelector.class})// 选择所有符合自动配置条件的bean,然后将其加载到IoC容器 public @interface EnableAutoConfiguration {}
Registrar类分析
//@AutoConfigurationPackage包中使用了@Import导入了Registrar.class @Import({Registrar.class}) public @interface AutoConfigurationPackage {}
static class Registrar...{ //加载启动类所在的包下的主类与子类的所有组件注册到spring容器,这就是springboot默认扫描启动类所在的包下的主类与子类的所有组件。 public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) { AutoConfigurationPackages.register(registry, (new AutoConfigurationPackages.PackageImport(metadata)).getPackageName()); } }
AutoConfigurationImportSelector类分析
public class AutoConfigurationImportSelector...{ ... public String[] selectImports(AnnotationMetadata annotationMetadata) { if (!this.isEnabled(annotationMetadata)) { return NO_IMPORTS; } else { AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader); AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata); return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations()); } } protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata, AnnotationMetadata annotationMetadata) { if (!this.isEnabled(annotationMetadata)) { return EMPTY_ENTRY; } else { AnnotationAttributes attributes = this.getAttributes(annotationMetadata); List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes); configurations = this.removeDuplicates(configurations); Set<String> exclusions = this.getExclusions(annotationMetadata, attributes); this.checkExcludedClasses(configurations, exclusions); configurations.removeAll(exclusions); configurations = this.filter(configurations, autoConfigurationMetadata); this.fireAutoConfigurationImportEvents(configurations, exclusions); return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions); } } protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) { //从所有的jar包中读取META-INF/spring.factories文件信息。 List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader()); Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories...."); return configurations; } }
下面是spring-boot-autoconfigure这个jar中spring.factories文件部分内容,其中有一个key为org.springframework.boot.autoconfigure.EnableAutoConfiguration的值定义了需要自动配置的bean,通过读取这个配置获取一组@Configuration类。
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\ org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\ org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\ org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration,\ org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,\ org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration,\ org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\ org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration,\ org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration,\ org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration,\ org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration,\ org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\ ......省略了很多
DispatcherServletAutoConfiguration
@AutoConfigureOrder(-2147483648) @Configuration( proxyBeanMethods = false ) @ConditionalOnWebApplication( type = Type.SERVLET ) @ConditionalOnClass({DispatcherServlet.class}) //只有JVM中有DispatcherServlet这个类的字节码时,当前类才有效 @AutoConfigureAfter({ServletWebServerFactoryAutoConfiguration.class}) public class DispatcherServletAutoConfiguration { public static final String DEFAULT_DISPATCHER_SERVLET_BEAN_NAME = "dispatcherServlet"; public static final String DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME = "dispatcherServletRegistration"; @Configuration( proxyBeanMethods = false ) @Conditional({DispatcherServletAutoConfiguration.DefaultDispatcherServletCondition.class}) @ConditionalOnClass({ServletRegistration.class}) @EnableConfigurationProperties({HttpProperties.class, WebMvcProperties.class}) protected static class DispatcherServletConfiguration { protected DispatcherServletConfiguration() { } //创建DispatcherServlet的对象并放入容器 @Bean( name = {"dispatcherServlet"} ) public DispatcherServlet dispatcherServlet(HttpProperties httpProperties, WebMvcProperties webMvcProperties) { DispatcherServlet dispatcherServlet = new DispatcherServlet(); dispatcherServlet.setDispatchOptionsRequest(webMvcProperties.isDispatchOptionsRequest()); dispatcherServlet.setDispatchTraceRequest(webMvcProperties.isDispatchTraceRequest()); dispatcherServlet.setThrowExceptionIfNoHandlerFound(webMvcProperties.isThrowExceptionIfNoHandlerFound()); dispatcherServlet.setPublishEvents(webMvcProperties.isPublishRequestHandledEvents()); dispatcherServlet.setEnableLoggingRequestDetails(httpProperties.isLogRequestDetails()); return dispatcherServlet; } @Bean @ConditionalOnBean({MultipartResolver.class}) @ConditionalOnMissingBean( name = {"multipartResolver"} ) public MultipartResolver multipartResolver(MultipartResolver resolver) { return resolver; } } }
条件装配
* 并不是读取META-INF/spring.factories所有的Bean都会被初始化,在配置类中使用@Condition来加载满足条件的Bean - ConditionalOnClass: 判断环境中是否有对应字节码文件才初始化Bean - ConditionalOnProperty: 判断配置文件中是否有对应属性和值才初始化Bean - ConditionalOnMissingBean:判断环境中没有对应Bean才初始化Bean