springBoot 自动装配

247 阅读2分钟

springBoot自动装配做什么?

把 java bean 注册到 spring Ioc 容器中,但不是程序员自己写 @Bean 等方式进行注册,而是整合了 springBoot 组件框架后,会把一些约定好的 java bean , 在程序项目启动(服务启动)时候自行进行注册,如数据库配置 。

不同的模块定义一些自动的启动类,这些启动类结合 application.yml 配置文件生效,实现 java bean 的注册到 spring Ioc 。 注册之后在程序中可以直接注入使用(如采用 @Autowired 注入)。

定制的组件,也可以采用此种方式进行注册 。

实现方式,采用 spring-boot-xxx-start 方式。

springBoot的思想

约定优于配置

实现方式

形式 : 启动类(@EnableXxx) + 配置( application.yml 、XxxAutoConfiguration 配置类)+ spring.factory 。

原理 : spring 的 java bean 注册,@Bean 、 @Import 注解形式、 @Selector 等8种 方式。把要自动装配的 XxxAutoConfiguration 放到 spring.factory 中。项目启动时候 spring Ioc 会自动处理 spring.factory 中指定的自动装配类。

spring boot 组件,提供了很多自动装配的注解, 结合 spring 的 java bean 注入方式完成对配置类进行自动注册。spring 和 spring boot 提供的如下如下(部分):

// 如下是 spring 的注解
org.springframework.context.annotation.Configuration // srping 配置类 注解

org.springframework.context.annotation.Conditional // spring 条件注入 注解

org.springframework.context.annotation.Import // spring 注入 java bean 注解

// 如下是 spring boot 提供的注解

org.springframework.boot.autoconfigure.condition.ConditionalOnClass

org.springframework.boot.context.properties.EnableConfigurationProperties

org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean 

org.springframework.boot.context.properties.EnableConfigurationPropertiesRegistrar

案例分析:

spring cloud feign start

具体实现原理

@EnableConfigurationProperties

1、 org.springframework.boot.context.properties.EnableConfigurationProperties 注解

该注解的作用就是让要注入到 spring Ioc 容器中的 java bean (假设这个 java bean 是 T) 取到配置文件中的配置的属性值。注解源码如下 :

package org.springframework.boot.context.properties;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(EnableConfigurationPropertiesRegistrar.class)
public @interface EnableConfigurationProperties {

   String VALIDATOR_BEAN_NAME = "configurationPropertiesValidator";
   
   Class<?>[] value() default {}; // 

}

2、 取到配置文件中(application.ympl)的属性赋值给 java bean ,然后借助 @Import 注解把需要 EnableConfigurationPropertiesRegistrar 注册到 spring Ioc 容器 。

3、EnableConfigurationPropertiesRegistrar 类,它实现了 spring 的 ImportBeanDefinitionRegistrar 接口,源码如下:


package org.springframework.boot.context.properties;

class EnableConfigurationPropertiesRegistrar implements ImportBeanDefinitionRegistrar {

   @Override
   public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
      registerInfrastructureBeans(registry);
      ConfigurationPropertiesBeanRegistrar beanRegistrar = new ConfigurationPropertiesBeanRegistrar(registry);
      getTypes(metadata).forEach(beanRegistrar::register);
   }

   private Set<Class<?>> getTypes(AnnotationMetadata metadata) {
      return metadata.getAnnotations().stream(EnableConfigurationProperties.class)
            .flatMap((annotation) -> Arrays.stream(annotation.getClassArray(MergedAnnotation.VALUE)))
            .filter((type) -> void.class != type).collect(Collectors.toSet());
   }

   @SuppressWarnings("deprecation")
   static void registerInfrastructureBeans(BeanDefinitionRegistry registry) {
      ConfigurationPropertiesBindingPostProcessor.register(registry);
      ConfigurationPropertiesBeanDefinitionValidator.register(registry);
      ConfigurationBeanFactoryMetadata.register(registry);
   }

}

@Import 注解

@Import 注解是将 java bean 注册到 spring Ioc 容器中。

@Import 注解有一个作用(还有其他注册方式),可以把实现了 ImportBeanDefinitionRegistrar 接口的类注册到 spring Ioc 容器中。

@Import 注解的几个导入方式如下:
1、类导入
最简单的注入方式,直接指定要注入的类,如下:

@Import(T.class)

2、ImportSelector 导入
要注入的类有很多,如果按照类导入方式,要写很多。可以把要注入的这些类都放到 XxxSelector 中,这样会把在 XxxSelector 中的类都注册到 spring Ioc 容器。

public class XxxSelector implements ImportSelector {
     //
}

3、ImportBeanDefinitionRegistrar 导入 1和2 java bean 的创建都是 spring Ioc 容器完成,如果要注册的 java bean 有一些业务逻辑,则可以使用 ImportBeanDefinitionRegistrar 导入。

让application.ympl在配置时候能给一些提示

// TODO 2022-6-10