利用@Import注解加载bean的机制,实现了SpringBoot的自动配置,@Import注解可用ImportSelector这个接口加载相应类型的Bean。
详细原理边看代码边说,另外提前注明,此处用的SpringBoot版本较老,2.1的,后来本人在2.7的版本再看,除了META-INF下的spring.factories文件,还引用了spring目录下的.imports文件;而到了3.0版本后,不再使用spring.factories文件,自动配置类全部从.imports文件中读取了,不过原理类似,这里不再赘述。

起手SpringBootApplication启动类,上面有个@EnableAutoConfiguration注解,点进去:

@Import(AutoConfigurationImportSelector.class),点进去AutoConfigurationImportSelector:

AutoConfigurationImportSelector实现了DeferredImportSelector接口,而DeferredImportSelector接口继承了ImportSelector接口,ImportSelector接口里有一个selectImports方法,这个方法返回需要用@Import注解引入Spring容器的Bean的类全限定名,AutoConfigurationImportSelector实现了这个方法。

接着回去看AutoConfigurationImportSelector如何实现该方法,其中一步就是 getAutoConfigurationEntry方法,点进去:

再点getCandidateConfigurations方法,这个方法读取需要被引入作为配置bean的候选项的类名(“候选项”是因为不一定全都作为配置bean加入容器):

关注loadFactoryNames方法,该方法第一个参数是getSpringFactoriesLoaderFactoryClass方法的返回值,点进去:

发现只是简单地返回了EnableAutoConfiguration这个Class对象,然后再返回上一步,点进loadFactoryNames方法,里面调用了loadSpringFactories方法,FACTORIES_RESOURCE_LOCATION点进去,其实就是spring.factories文件所在路径,loadSpringFactories方法将spring.factories文件作为一个Map返回,然后方法loadFactoryNames中使用getOrDefault方法,根据刚才EnableAutoConfiguration的类名作为key,读出Map中的value:

之所以用Map返回spring.factories文件的内容,看一眼该文件的结构就懂了:

因此上面的Java方法执行后,就可以读到自动配置候选类的全限定名啦,然后由Import注解将它们作为bean加载到Spring容器中就可以完成配置,不过,并不是所有的这些配置类都会被加载,还得看这些配置类自己有没有一些限定条件,以Redis的自动配置类举例:

spring.factories文件中,可以看到RedisAutoConfiguration类,它在EnableAutoConfiguration为key的value中,因此它是作为自动配置候选类的一员的,进入RedisAutoConfiguration类,发现该类果然有加载做Bean的限定条件:

里面两个redisTemplate眼熟得很,就是平时我们直接拿来用的东西,原来是在这里自动引入的。
1万+



被折叠的 条评论
为什么被折叠?



