一、springboot的简单理解
springboot是spring快速开发脚手架,通过约定大于配置的方式,快速构建和启动spring项目。springboot根据我们项目中所引入的依赖,比如引入了springmvc构件,就会判断出是要进行springmvc的web开发,就会把springmvc的相关的基本配置自动配置好,不需要我们在xml中配置。 比如配置前端控制器DispatcherServlet、配置视图解析器、配置静态资源访问、处理器映射器、处理器适配器等一系列组件。spring boot优化了混乱的依赖管理和复杂的配置,让我们用java -jar方式,运行启动java web项目。二、springboot自动配置原理
springboot的自动配置使得开发者使用注解实现bean的注入及代替繁琐的配置文件编写,使springboot项目变的无比简单,那些繁杂的配置都消失不见了,这些都是从springboot启动器开始的,注解@SpringBootApplication标注该类为启动类。@SpringBootApplication
进入注解@SpringBootApplication所在源码,可以发现其本质是一个组合注解,该类的元信息主要包含三个注解,分别是@SpringBootConfiguration、@EnableAutoConfiguration和@ComponentScan。
@SpringBootConfiguration
@SpringBootConfiguration其源码实际上封装了@Configuration并改名为@SpringBootConfiguration,@Configuration标注在某个类上,表示这是一个 springboot的配置类,可以向容器中注入组件。
@EnableAutoConfiguration
@EnableAutoConfiguration见名知意,此注解的作用为开启自动导入配置,是自动装配的核心注解。其源码如下:其中的@AutoConfigurationPackage注解实现自动导入配置包,@Import注解导入的类AutoConfigurationImportSelector.class实现自动配置导入选择。
@AutoConfigurationPackage
其注解源码如下:实现自动导入配置类导包。此注解也是一个组合注解,其中最重要的注解是@Import(AutoConfigurationPackages.Registrar.class),它是spring框架的底层注解,它的作用就是给容器中导入某个组件类,例如@Import(AutoConfigurationPackages.Registrar.class),它就是将Registrar这个组件类导入到容器中,可查看Registrar类中registerBeanDefinitions方法,这个方法就是导入组件类的具体实现。
@Import({AutoConfigurationPackages.Register.class})
@Import({AutoConfigurationPackages.Register.class})源码如下:实现自动配置包下所有bean的定义和注册。
在registerBeanDefinitions方法上设置断点,debug运行可得,注解@AutoConfigurationPackage 将主配置类即@SpringBootApplication 标注的类所在的包下面所有的组件都扫描注册到 spring 容器中。
@Import(AutoConfigurationImportSelector.class)
@Import(AutoConfigurationImportSelector.class)此注解开启自动配置类的导包选择器,即要导入哪些类,有选择性的导入。即实现自动配置类的导入选择器,有选择地导入配置类。该注解所在类通过方法selectImports和getAutoConfigurationEntry分别选择需要导入的组件和根据导入的@Configuration类的AnnotationMetadata返回AutoConfigurationImportSelector.AutoConfigurationEntry。
将AutoConfigurationImportSelector这个类导入到spring容器中,AutoConfigurationImportSelector可以帮助springboot应用将所有符合条件的@Configuration配置都加载到当前SpringBoot创建并使用的IOC容器(ApplicationContext)中。
getCandidateConfigurations()方法中断言在 META-INF/spring.factories 中没有找到自动配置类。如果您使用自定义包装,请确保该文件是正确的。
接着,this.getSpringFactoriesLoaderFactoryClass()返回的是EnableAutoConfiguration.class这个注解。这个注解和@SpringBootApplication下标识注解是同一个注解。目的是获取一个能加载自动配置类的类,即SpringBoot默认自动配置类为EnableAutoConfiguration。
loadFactoryNames()方法:先是将 EnableAutoConfiguration.class 传给了 factoryType,然后String factoryTypeName = factoryType.getName(); 所以factoryTypeName 值为 org.springframework.boot.autoconfigure.EnableAutoConfiguration。
loadSpringFactories()方法作用是加载所有依赖的路径META-INF/spring.factories文件,通过map结构保存,key为标识工厂类,value是能自动配置的工厂实现的类。
总的来说,loadSpringFactories()该方法从“META-INF/spring.factories”中加载给定类型的工厂实现的完全限定类名放到map中。loadFactoryNames()根据SpringBoot的启动生命流程,当需要加载自动配置类时,传入org.springframework.boot.autoconfigure.EnableAutoConfiguration参数,从map中查找key为org.springframework.boot.autoconfigure.EnableAutoConfiguration的值,这些值通过反射加到容器中,之后用它们来做自动配置,这就是Springboot自动配置开始的地方。只有这些自动配置类进入到容器中以后,接下来这个自动配置类才开始进行启动。
@ComponentScan
@ComponentScan注解用于包扫描。该配置用于 Configuration 类的组件扫描指令,提供与 Spring XML的context:component-scan元素并行的支持,可以basePackageClasses 或basePackages 来定义要扫描的特定包,如果没有定义特定的包,将从声明该注解的类的包开始扫描。
三、总结
springboot底层实现自动配置的步骤是:
springboot应用启动;@SpringBootApplication起作用;@EnableAutoConfiguration;接着是@AutoConfigurationPackage:这个组合注解主要是@Import(AutoConfigurationPackages.Registrar.class),它通过将Registrar类导入到容器中,而Registrar类作用是扫描主配置类同级目录以及子包,并将相应的组件导入到springboot创建管理的容器中;再接着是@Import(AutoConfigurationImportSelector.class):它通过将AutoConfigurationImportSelector类导入到容器中,AutoConfigurationImportSelector类作用是通过selectImports方法实现将配置类信息交给SpringFactory加载器进行一系列的容器创建过程。