- 前言
- SpringBoot是一个脚手架,通常喜欢拿SpringBoot和Spring做比较,SpringBoot只是对于SSM框架开发时候的配置项做了一个默认配置,将开发中约定大于配置进行了实现,大大节约了开发时间写各种繁琐的配置文件环节,达到了开箱即用的便捷体验
- SpringBoot入口
// 源码入口就是 @SpringBootApplication注解publicclassBootDemoApplication { publicstaticvoidmain(String[] args) { SpringApplication.run(BootDemoApplication.class, args); } }
- 查看@SpringBootApplication注解
// 自动装配原理的核心注解excludeFilters= { (type=FilterType.CUSTOM, classes=TypeExcludeFilter.class), (type=FilterType.CUSTOM, classes=AutoConfigurationExcludeFilter.class) }) (public@interfaceSpringBootApplication {
- 查看@EnableAutoConfiguration注解
/*** 自动装配的时候使用的是@Import注解* 作用是导入一个或者多个组件搭配@Configuration注解使用,交给spring容器管理* 该注解有三种方式* 1.@import:指定导入一个或者多个类* 2.ImportSelector:定义一个类实现该接口,重写selectImports方法* 3.* 扩展:@ImportResource:指定导入一个或者多个xml文件*/AutoConfigurationImportSelector.class) (public@interfaceEnableAutoConfiguration {
- AutoConfigurationImportSelector类源码解析
// 重写来自于DeferredImportSelector.Group#processpublicvoidprocess(AnnotationMetadataannotationMetadata, DeferredImportSelectordeferredImportSelector) { Assert.state(deferredImportSelectorinstanceofAutoConfigurationImportSelector, () ->String.format("Only %s implementations are supported, got %s", AutoConfigurationImportSelector.class.getSimpleName(), deferredImportSelector.getClass().getName())); // 获取自动装配信息AutoConfigurationEntryautoConfigurationEntry= ((AutoConfigurationImportSelector) deferredImportSelector) .getAutoConfigurationEntry(annotationMetadata); this.autoConfigurationEntries.add(autoConfigurationEntry); for (StringimportClassName : autoConfigurationEntry.getConfigurations()) { this.entries.putIfAbsent(importClassName, annotationMetadata); } } // 获取自动装配信息protectedAutoConfigurationEntrygetAutoConfigurationEntry(AnnotationMetadataannotationMetadata) { if (!isEnabled(annotationMetadata)) { returnEMPTY_ENTRY; } AnnotationAttributesattributes=getAttributes(annotationMetadata); // 加载所有在META-INF/spring.factories中配置的类 跳到①List<String>configurations=getCandidateConfigurations(annotationMetadata, attributes); configurations=removeDuplicates(configurations); Set<String>exclusions=getExclusions(annotationMetadata, attributes); checkExcludedClasses(configurations, exclusions); configurations.removeAll(exclusions); // 经过condition注解过滤后的自动配置类configurations=getConfigurationClassFilter().filter(configurations); fireAutoConfigurationImportEvents(configurations, exclusions); returnnewAutoConfigurationEntry(configurations, exclusions); } // ① META-INF/spring.factories中读取所有的候选的自动配置类名称protectedList<String>getCandidateConfigurations(AnnotationMetadatametadata, AnnotationAttributesattributes) { // 通过SpringFactoriesLoader读取所有的候选的自动配置类名称// ② 加载配置候选的类List<String>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."); returnconfigurations; } // ③ 加载配置候选的类protectedClass<?>getSpringFactoriesLoaderFactoryClass() { returnEnableAutoConfiguration.class; } // 所以如果想要将一个外部(第三方)的类交给spring容器管理,可以把这个类配置添加到META-INF/spring.factories文件中。// 例如自定义starter场景启动器
- 总结:SpringBoot的自动装配原理本质上就是读取项目中所有的META-INF/spring.factories的配置类信息
- @Import之 ImportSelector/ImportBeanDefinitionRegistrar扩展
// ImportSelector (重要!SpringBoot底层使用这种方式,但是又有区别)publicclassMyImportSelectorimplementsImportSelector { publicString[] selectImports(AnnotationMetadataimportingClassMetadata) { // 返回值String[]中值依旧是要导入类的全限定名,注意,返回值可以是空数组但是不能为nullreturnnewString[]{"com.fun.bootdemo.custome.Demo1"}; } } /*** SpringBoot底层使用的是:* org.springframework.boot.autoconfigure.AutoConfigurationImportSelector* 该类实现的是DeferredImportSelector接口,该接口包含有额外功能:* gruop 该分组可以用来进行排序和过滤时同时DeferredImportSelector是优先级比较低的,* 需要等到其他bean注册完了。才注册该接口导入的bean。这个功能很好的结合了@Conditon等条件注解* 实现了用户自定义配置覆盖默认配置*/// ImportBeanDefinitionRegistrarpublicclassMyImportBeanDefinitionRegistrarimplementsImportBeanDefinitionRegistrar { publicvoidregisterBeanDefinitions(AnnotationMetadataimportingClassMetadata, BeanDefinitionRegistryregistry) { // 指定注册bean定义信息RootBeanDefinitionrootBeanDefinition=newRootBeanDefinition(Demo3.class); // demo3 是beanNameregistry.registerBeanDefinition("demo3", rootBeanDefinition); } } // 测试 (在配置类上)MyImportSelector.class, MyImportBeanDefinitionRegistrar.class}) ({