0
点赞
收藏
分享

微信扫一扫

springboot自动装配详解



文章目录

  • @SpringBootApplication
  • @SpringBootConfiguration
  • @EnableAutoConfiguration
  • @AutoConfigurationPackage
  • @Import(AutoConfigurationImportSelector.class)
  • AutoConfigurationImportSelector流程分析


@SpringBootApplication

这个注解是springboot的启动注解,配置了这个注解的方法就是springboot项目的入口;
一般springboot项目的启动类:

@SpringBootApplication
public class SpringBootPlusApplication {

  public static void main(String[] args) {
    ConfigurableApplicationContext context = SpringApplication.run(SpringBootPlusApplication.class, args);
    // 打印项目信息
    PrintApplicationInfo.print(context);
  }

}

我们看看SpringBootApplication注解:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
		@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
@ConfigurationPropertiesScan
public @interface SpringBootApplication {

}


@ComponentScan表示包扫描,FilterType.CUSTOM表示自定义扫描;可以看一下TypeExcludeFilter这类,实现TypeFilterl类,重写match方法进行判断是否加入spring容器中;这里不做过多详解,主要讲@SpringBootConfiguration、@EnableAutoConfiguration这两个注解;

@SpringBootConfiguration

源码:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration(proxyBeanMethods = false)
public @interface SpringBootConfiguration {
    @AliasFor(
        annotation = Configuration.class
    )
    boolean proxyBeanMethods() default true;
}

这个注解就一个@Configuration注解,就相当于把当前标注了@SpringBootConfiguration注解的类标记为配置类;
@Configuration类里面有@Component注解…

@EnableAutoConfiguration

EnableAutoConfiguration这个注解从名字上面来看,这个注解应该是跟自动装配相关的注解了;
先看看enableAutoCOnfiguration注解的源码:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {

}

前四个是元注解,就不提了,后面两个@AutoConfigurationPackage和导入了入AutoConfigurationImportSelector这个类;

@AutoConfigurationPackage

这个类从名字上面看应该是自配配置包的:
先看看源码:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {

}

这里主要导入了AutoConfigurationPackages.Registrar.class类:

static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {

		@Override
		public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
			register(registry, new PackageImport(metadata).getPackageName());
		}

		@Override
		public Set<Object> determineImports(AnnotationMetadata metadata) {
			return Collections.singleton(new PackageImport(metadata));
		}

	}

这个类获取到了使用这个注解的包路径,然后扫描注册对应包路径下所有组件,注册到spring容器中;

@Import(AutoConfigurationImportSelector.class)

先看AutoConfigurationImportSelector实现的接口:

public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
		ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
		}

实现的aware接口,就是在类中获取spring容器的组件,这里获取的是:beanFactory,environment,beanClassLoader,resourceLoader;
最主要的接口是DeferredImportSelector,这个接口继承了ImportSelector接口,

  • ImportSelector这个接口在调用地方是在,spring容器处理Import注解的时候,如果@import注解导入的类实现了ImportSelector接口,则会调用selectImports方法获取Import的类:

基于被引入的Configuration类的AnnotationMetadata信息选择并返回需要引入的类名列表;
ImportSelector的实现和@import通常在处理方式上是一致的,可以在所以的配置类,就是@Configuration标记的类处理完成后在进行筛选;

  • DeferredImportSelector接口实现了ImportSelector接口,表明他们作用差不多,DeferredImportSelector接口在所有的@Configuration处理完成之后才会调用,在需要筛选的引入类型具备@Conditional(条件注入指定类的时候)非常有用;最后会执行selectImports方法;
AutoConfigurationImportSelector流程分析

DeferredImportSelector会通过getImportGroup返回执行的类,然后执行内部类AutoConfigurationGroup方法的process方法,然后执行getAutoConfigurationEntry方法,我们就从AutoConfigurationImportSelector的process开始:

通过process的getAutoConfigurationEntry来获取自动装配的Entry对象:

springboot自动装配详解_spring


然后进到getCandidateConfigurations方法,getCandidateConfigurations就加载出了spring-boot-autuator-atoconfig包下META-INF\spring,factories文件,第一次的时候cache里面是空的,就会通过classloader加载META-INF/spring.factories文件,通过配置的key/vlaue保存到缓存中.给后面使用:

springboot自动装配详解_spring_02

springboot自动装配详解_加载_03


springboot自动装配详解_加载_04


springboot自动装配详解_spring_05


springboot自动装配详解_自动装配_06


然后spring通过加载这些类,将这些配置类加入到spring容器中,可以看ConfigurationClassParser的processGroupImports方法,通过执行getImports方法,点进去就看见是执行DeferredImportSelector的selectImports方法;

springboot自动装配详解_加载_07


springboot自动装配详解_spring_08


这时候通过加载meta-inf文件夹下的spring.factories文件配置的配置类路径,进行加载对应的类,这时候自动装配就基本完成了,剩下的就是这些配置类可以通过@ConditionalOnBean等一系列注解来判断加不加载当前类:

举个例子:HttpEncodingAutoConfiguration类

springboot自动装配详解_spring_09

springboot自动装配详解_自动装配_10


可通过是否配置了spring.http.encoding来进行判断是否加载当前配置类…

更多@ConditionalOnBean详解


举报

相关推荐

0 条评论