从源码中理解Spring Boot自动装配原理(springboot自动装配原理简单)

  本篇文章为你整理了从源码中理解Spring Boot自动装配原理(springboot自动装配原理简单)的详细内容,包含有springboot自动装配原理简言之 springboot自动装配原理简单 springboot自动装配和自动配置 springboot自动装配流程图 从源码中理解Spring Boot自动装配原理,希望能帮助你了解 从源码中理解Spring Boot自动装配原理。

  个人博客:槿苏的知识铺

  一、什么是自动装配

  SpringBoot 定义了一套接口规范,这套规范规定:SpringBoot在启动时会扫描外部引用jar包中的META-INF/spring.factories文件,将文件中配置的类型信息加载到Spring容器,并执行类中定义的各种操作。对于外部jar包来说,只需要按照SpringBoot定义的标准,就能将自己的功能装配到SpringBoot中。

  二、自动装配的实现原理

  自动装配的实现,离不开SpringBootApplication这个核心注解。查看这个注解的源码,我们会发现在SpringBootApplication注解上,存在着几个注解,其中SpringBootConfiguration、EnableAutoConfiguration、ComponentScan这三个注解是需要我们注意的。

  

@SpringBootConfiguration

 

  @EnableAutoConfiguration

  @ComponentScan(excludeFilters = {

   @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),

   @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })

  public @interface SpringBootApplication {

  

 

  (1) ComponentScan

  扫描被@Component 、@Service注解的bean,该注解默认会扫描启动类所在的包下所有的类 ,可以自定义不扫描某些 bean。如SpringBootApplication注解源码所示,容器中将排除TypeExcludeFilterh和AutoConfigurationExcludeFilter。

  (2) EnableAutoConfiguration

  启用 SpringBoot 的自动配置机制

  (3) Configuration

  允许在上下文中注册额外的 bean 或导入其他配置类

  2.1 EnableAutoConfiguration详解

  @EnableAutoConfiguration是实现自动装配的重要注解,在这个注解上存在以下两个注解:AutoConfigurationPackage、Import。

  

@AutoConfigurationPackage

 

  @Import(AutoConfigurationImportSelector.class)

  public @interface EnableAutoConfiguration {

  

 

  2.1.1 AutoConfigurationPackage

  表示对于标注该注解的类的包,应当使用AutoConfigurationPackages注册。实质上,它负责保存标注相关注解的类的所在包路径。使用一个BasePackage类,保存这个路径。然后使用@Import注解将其注入到ioc容器中。这样,可以在容器中拿到该路径。

  

static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {

 

   @Override

   public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {

   register(registry, new PackageImport(metadata).getPackageName());

  

 

  查看AutoConfigurationPackages中的Registrar这个类的源码,在Registrar#registerBeanDefinitions方法中有这样一句代码new PackageImport(metadata).getPackageName(),查看PackageImport的构造器后不难发现,这里获取的是StandardAnnotationMetadata这个实例所在的包名。

  

/**

 

   * metadata: 实际上是 StandardAnnotationMetadata 实例。

   * metadata#getClassName(): 获取标注 @AutoConfigurationPackage 注解的类的全限定名。

   * ClassUtils.getPackageName(…): 获取其所在包。

  PackageImport(AnnotationMetadata metadata) {

   this.packageName = ClassUtils.getPackageName(metadata.getClassName());

  

 

  此时再回去看Registrar#registerBeanDefinitions中调用的AutoConfigurationPackages#register方法

  

public static void register(BeanDefinitionRegistry registry, String... packageNames) {

 

   // BEAN:AutoConfigurationPackages类的全限定名

   // 此时判断BeanDefinitionRegistry中是否存在以BEAN作为beanName的BeanDefinition对象

   // 如果不存在,走else方法,构造了一个BackPackages实例,进行注册

   if (registry.containsBeanDefinition(BEAN)) {

   BeanDefinition beanDefinition = registry.getBeanDefinition(BEAN);

   ConstructorArgumentValues constructorArguments = beanDefinition

   .getConstructorArgumentValues();

   constructorArguments.addIndexedArgumentValue(0,

   addBasePackages(constructorArguments, packageNames));

   } else {

   GenericBeanDefinition beanDefinition = new GenericBeanDefinition();

   beanDefinition.setBeanClass(BasePackages.class);

   beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(0, packageNames);

   beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);

   registry.registerBeanDefinition(BEAN, beanDefinition);

  

 

  2.1.2 Import(AutoConfigurationImportSelector.class)

  它是利用AutoConfigurationImportSelector机制再来给容器中批量导入一些配置东西的,接下来带大家了解究竟导入了哪些内容。

  

/**

 

   * AutoConfigurationImportSelector类中存在一个叫selectImports的方法,就是我们到底要向容器中导入哪些

   * 内容,都会在这里进行扫描并导入。

  @Override

  public String[] selectImports(AnnotationMetadata annotationMetadata) {

   // 判断EnableAutoConfiguration是否开启默认开启true

   if (!isEnabled(annotationMetadata)) {

   return NO_IMPORTS;

   // 1.加载META-INF/spring-autoconfigure-metadata.properties 文件

   // 2.从中获取所有符合条件的支持自动装配的类

   // 自动配置类全名.条件=条件的值

   AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader

   .loadMetadata(this.beanClassLoader);

   // 获取AutoConfigurationEntry

   AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata,annotationMetadata);

   return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());

  

 

  接下来重点看getAutoConfigurationEntry(annotationMetadata)方法,利用这个方法向容器中批量导入一些默认支持自动配置的类,当你理解了这部分内容之后,就基本了解了Spring Boot是如何进行自动装配的,废话不多说,让我们进入正题。

  

protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {

 

   // 判断EnableAutoConfiguration是否开启默认开启true

   if (!isEnabled(annotationMetadata)) {

   return EMPTY_ENTRY;

   // 获取注解属性

   AnnotationAttributes attributes = getAttributes(annotationMetadata);

   // 调用getCandidateConfigurations(annotationMetadata, attributes),利用loadSpringFactories(ClassLoader classLoader)加载当前系统所有的META-INF/spring.factories文件,得到默认支持的自动配置的类的列表

   List String configurations = getCandidateConfigurations(annotationMetadata, attributes);

   // 去除重复的 configuration

   configurations = removeDuplicates(configurations);

   // 获取到SpringBootApplication上exclude和excludeName配置的需要排除的类

   Set String exclusions = getExclusions(annotationMetadata, attributes);

   // 检查configurations是否含有exclusions中的类

   checkExcludedClasses(configurations, exclusions);

   // 将exclusions中的类从configurations中排除

   configurations.removeAll(exclusions);

   // 对所有候选的自动配置类进行筛选,

   // 比如ConditionalOnProperty 当属性存在时

   // ConditionalOnClass 当class存在

   // ConditionalOnMissingClass 当这个clas不存在时才去配置

   // 过滤器

   configurations = getConfigurationClassFilter().filter(configurations);

   // 将自动配置的类,导入事件监听器,并触发fireAutoConfigurationImportEvents事件

   // 加载META-INF\spring.factories中的AutoConfigurationImportListener

   fireAutoConfigurationImportEvents(configurations, exclusions);

   // 创建AutoConfigurationEntry对象

   return new AutoConfigurationEntry(configurations, exclusions);

  

 

  以上就是从源码中理解Spring Boot自动装配原理(springboot自动装配原理简单)的详细内容,想要了解更多 从源码中理解Spring Boot自动装配原理的内容,请持续关注盛行IT软件开发工作室。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: