Spring Boot自动配置原理,解决方案如下方案一:
Spring Boot自动配置原理,解决方案如下方案一:
当想尝试使用第三方工具包依赖时在项目中如果第三方工具包文件不在Spring Boot项目包及其子包下则这个工具包所声明的Bean对象和配置类并不会被Spring Boot扫描到,就不能使用。解决方案如下
方案一:在Spring Boot启动类添加@ComponentScan注解组件扫描,手动声明要扫描的包的位置(使用繁琐,性能低)
方案二:通过@Import注解导入,被@Import导入的类会被Spring Boot加载到IOC容器中成为Bean对象
使用形式主要有三种:1.导入普通类,2.导入配置类,3.导入ImportSelector接口实现类(在ImportSelect接口中有一个selectImports方法,他的作用是将要管理的类通过全类名的形式给IOC容器进行管理,成为IOC容器中的Bean),4 .通过EnableXXX注解封装@Import注解
缺陷:在导入第三方依赖时要知道导入哪些配置类和Bean对象,比较繁琐用户体验不好,在导入第三方依赖时只有第三方最清楚需要导入哪些配置类和Bean对象。这时候一般由第三方依赖自己提供一个注解,一般以Enable开头,用EnableXXX注解封装@Import注解。这时只需要在启动类上添加这个注解即可
第四个方法也是SpringBoot采用的方法
源码跟踪解析SpringBoot自动配置原理:
在启动类中有一个@SpringBootApplication注解这是Spring Boot最重要的注解,进去会发现封装了很多注解,主要关心@SpringBootConfiguration,@EnableAutoConfiguration,@ComponentScan 三个注解
在Spring Boot中具备包扫描作用,默认扫描当前包及其子类,原因就是@SpringBootApplication注解封装了@ComponentScan注解,@ComponentScan是组件扫描的注解
@SpringBootConfiguration中封装了@Configuration注解,这个注解作用是用来声明当前类也是一个配置类,所以才能做到在启动类中声明Bean对象
@EnableAutoConfiguration前面提到Enable开头的注解一般都封装了@Import注解,通过@Import注解导入指定的Bean对象或配置类。点进@EnableAutoConfiguration注解发现@impact注解导入的是AutoConfigurationImportSelector.class,这是一个ImportSelector接口的实现类
点进去发现AutoConfigurationImportSelector实现了DeferredImportSelector接口,而这个DeferredImportSelector继承了ImportSelector接口。
前面提到ImportSelector中有个selectImports方法,这个方法会以全类名的形式将需要的类导入到IOC容器中进行管理。
也就是说,我们需要在AutoConfigurationImportSelector中找到这个selectImports方法看哪些类被加载到IOC容器,这样就能知道在启动Spring Boot项目时哪些类会被自动导入到IOC容器中
首先 selectImports 方法中要返回这个 autoConfigurationEntry.getConfigurations()这个参数,这就是要给IOC管理的Bean对象或配置类,那么我们需要关心这个参数里是什么东西。
由图可知他是通过这个 this.getAutoConfigurationEntry() 方法给 autoConfigurationEntry.getConfigurations() 赋值,所以点进去这个方法看
在 this.getAutoConfigurationEntry() 这个方法中他创建了一个 configurations 集合通过 this.getCandidateConfigurations(annotationMetadata, attributes); 方法来给autoConfigurationEntry.getConfigurations() 参数赋值,所以需要关心这个方法在做什么,点进方法去看看
方法如图所示,他调用了SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader()); 这个方法给 configurations 赋值 并调用了断言判空 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.");
版本不同提示的信息不同,以下图片是Spring Boot 2.7.5提示的信息
也许我们不知道这个赋值的方法在做什么但是通过断言提示的报错内容可以猜到他的功能,如果 configurations 为空则提示没有找到这个自动配置类在这个文件里,也就是说这个方法会去加载这份文件里所配置的信息。找到文件打开后会发现里面都是写好的全类名,这样这些全类名就会被加载到IOC容器中
这样就能解释在Spring Boot项目中当我们引入某些依赖时通过@Autowired注入就可以直接使用这个类对象,是因为Spring Boot在启动时就帮我们加载好这个依赖的配置类或Bean对象给IOC容器管理。
但是不是所有的Bean都会被加载到IOC容器中Spring Boot会根据@Conditional注解条件去加载Bean,在声明Bean对象时能看到@ConditionalOnClass、@ConditionalOnMissingBean,@ConditionalOnProerty,这些都是@Conditional衍生出的常用的子注解,
@ConditionalOnClass判断环境中是否有对应字节码文件,有才注册Bean到IOC容器
@ConditionalOnMissingBean判断环境中没有对应的Bean(根据类型或名称),才注册Bean到IOC容器 (这个通常用于声明默认的Bean,意思是如果用户已经声明了这个Bean,则使用用户自己的,如果没有则Spring Boot自动声明这个Bean)
@ConditionalOnProerty判断配置文件中有对应属性和值,才注册Bean到容器。
用户点评