springboot自动装配

从主启动类开始

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MainApplication {
    public static void main(String[] args) {
        SpringApplication.run(MainApplication.class, args);
    }
}

上述代码,是一个springboot的web应用程序的入口类,想要了解springboot是如何装配的,我们需要了解@SpringBootApplication这个注解。

1.@SpringBootApplication

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
		@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {

1.1.@ComponentScan

指定扫描的包路径,value是一个数组,可以同时指定多个包路径,详细说明略。

1.2.@SpringBootConfiguration

@Configuration
public @interface SpringBootConfiguration {

其实就是一个配置类,也就是说,入口类本身就被标识为一个配置类,没什么可说的。

1.3.@EnableAutoConfiguration

这个注解,表面意思为:开启自动配置。顾名思义,springboot的自动装配机制应该与这个注解有关。

@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {

点开这个注解我们可以看到,注解头上有含义的两行,做了两件事情:

  • @AutoConfigurationPackage:扫描并注册我们自己写的java类到spring容器
  • @Import(AutoConfigurationImportSelector.class):注册springboot提供的自动配置类到spring容器

1.3.1.@AutoConfigurationPackage

@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {

可以看到,@AutoConfigurationPackage注解其实是向容器中导入了一个AutoConfigurationPackages.Registrar的实例对象,那么这个实例对象有哪些作用呢?接着看。

1.3.1.1.AutoConfigurationPackages.Registrar

static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
		@Override
		public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
			register(registry, new PackageImports(metadata).getPackageNames().toArray(new String[0]));
		}
		...
	}

其中

register(registry, new PackageImports(metadata).getPackageNames().toArray(new String[0]));

这个代码中,其实就是完成了我们自己写的类的扫描。
new PackageImports(metadata).getPackageNames().toArray(new String[0])获取到的是指定扫描包的路径,如果未明确指定,默认为主启动类所在的包名。
在debug模式下就可以轻松看到。
在这里插入图片描述
具体的注册细节暂时不深究。

1.3.2.@Import(AutoConfigurationImportSelector.class)

这个注解,很明显,作用是向spring容器中注入了一个AutoConfigurationImportSelector的对象。

1.3.2.3.AutoConfigurationImportSelector

这个类所做的,是将springboot提供好的自动配置装载进spring容器。
这个类中有一个方法:

protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {

这个方法是获取所有的自动配置类的实体,debug看一下,实际上就是获取了springboot写好的127个自动配置类实体。
在这里插入图片描述
这127个类是在spring-boot-autoconfigure模块下定义的,如下图所示

在这里插入图片描述
spring-boot在启动时,默认就装载了这些自动配置类,但是并没有启用,只有在引入相关依赖包的时候,这些自动配置才真正被启用,这种按需加载的原理是基于条件注解实现的,如下图所示:
在这里插入图片描述
条件注解功能强大,这里不详细展开,请自行探索或参阅其它文章。


版权声明:本文为weixin_42425970原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。