目录
此时tokenService的类上还是有@Component注解的
总结:将security模块当成第三模块引用,结合spi机制就可以理解。
1. springboot 2.7之前
2.7之前大家都是了解的springboot的自动装配原理,是到MENT-INF/spring.factories中扫描,但是可能也不理解为什么去MENT-INF/spring.factories 这里,怎么不去其他地方?又是怎么加载的呢?这就需要看些SPI机制,原文链接SPI机制是什么?_会飞的IT蜗牛的博客-CSDN博客
1.1 spi机制
所以我们一点也不陌生,以前在学习jdbc连接数据库的时候就发现Class.forName("com.mysql.cj.jdbc.driver")写不写都行,那为什么呢?就是因为我们在引入jdbc的jar包时,打开依赖就会发现里面已经给你写好了配置类(自己去看,要动手)。
总结就是:
(1)在引用第三方jar包(mysql)时,会自动加载配置类,至于怎么加载可以去看上面的链接很详细。
(2)这就是为什么springboot引用依赖后,会自动配置
(3) 不理解可以再看看hutool依赖如下图 (引用这个依赖就可以用他的一些配置类,就是使用的spi机制加载的,springboot也一样)
2 springboot2.7 之后
2.1 配置类的位置发生变化
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = new ArrayList<>(
SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader()));
ImportCandidates.load(AutoConfiguration.class, getBeanClassLoader()).forEach(configurations::add);
Assert.notEmpty(configurations,
"No auto configuration classes found in META-INF/spring.factories nor in META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. If you "
+ "are using a custom packaging, make sure that file is correct.");
return configurations;
}
如上图所示:扫描的位置多了一个org.springframework.boot.autoconfigure.AutoConfiguration.imports
2.2 那为什么要多搞一个呢?
打开spring.factories文件发现里面只有springboot自己配置类比如监听器,初始化等。就很好维护,以前是很多配置类放在一起,很不明确。
2.3 这样做的好处是什么呢
在进行微服务开发时一个服务需要调用另外一个A模块的类,但是A模块与它不在一个包且不是子包的情况下,@springbootApplication就无法扫描到A模块的配置类,即使你加了@compent或者其他注解。这时又不能把那个A模块放下来,因为这样就代码耦合了。所以也可以变相的使用SPI机制(请仔细体会,把A模块想象成一个第三方的jar包)。
(1)在服务里面引入A模块的依赖,并且在A模块的sources包下新建一个MENT-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件
(2)把需要被外部使用的配置类的全路径写上去 比如:
(3)这样在启动服务时就会自动加载到这个配置类到ioc中,后面你就可以用@Autowared在开启的服务里注入或者使用了。
3 遇到的问题
知道有的人不信这个所以我测试一下,放几张截图
-
system服务引用了security模块(注意不是服务)
-
security模块里有一个tokenService类需要被扫描到IOC容器,我们先把security的org.springframework.boot.autoconfigure.AutoConfiguration.imports文件里的tokenService全类名注释掉
-
此时tokenService的类上还是有@Component注解的
-
启动system服务 发现报错,在加载的时候找不到tokenService的Bean,也就是上面我们把那个全类名注释掉了,即使你在类上加入了@Component注解也扫描不到。之所以报错是因为这个项目在启动时会进行初始化,用到了tokenService,如果没有用到启动时不会报错,但是在真正调用的时候也会报错。
总结:将security模块当成第三模块引用,结合spi机制就可以理解。
如果有错误请批评指正!!!相互学习,共同进步