SpringBoot 自动装配原理是什么?

2 个回答

  • 云说
    为了击碎你伪装的表面,我只能用尽全身力气挥出那惊鸿的半月弧光。
    ### Spring Boot 自动装配原理 自动配置主要由@EnableAutoConfiguration实现,添加了@EnableAutoConfiguration注解,会导入AutoConfigurationImportSelector类,里面的selectImports方法通过SpringFactoriesLoader.loadFactoryNames()扫描所有含有META-INF/spring.factories的jar包,将对应key为@EnableAutoConfiguration注解全名对应的value类全部装配到IOC容器中。 Spring Boot 自动装配是 Spring Boot 提供的一种自动配置机制,简化了 Spring 应用的配置过程。下面我们从以下几个方面详细介绍 Spring Boot 的自动装配原理: 1. 什么是 Spring Boot 自动装配? 2. Spring Boot 如何实现自动装配?如何实现按需加载? 3. 如何实现一个 Starter? ### 1. 什么是 Spring Boot 自动装配? 自动装配可以理解为:通过注解或者一些简单的配置,Spring Boot 帮助我们自动配置并加载相关的组件。 在没有 Spring Boot 的情况下,我们需要手动配置大量的 XML 或 Java 配置文件,而在 Spring Boot 中,只需要引入相应的 Starter 依赖,然后通过少量的注解和配置,就能使用第三方组件提供的功能。 例如,在项目中使用 Redis,只需要引入 Redis 的 Starter 依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> ``` 然后进行简单配置,就可以使用 Redis。 ### 2. Spring Boot 如何实现自动装配? #### 核心注解 @SpringBootApplication ```java @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @SpringBootConfiguration @ComponentScan @EnableAutoConfiguration public @interface SpringBootApplication { } ``` 这个注解包含了三个重要注解: 1. **@SpringBootConfiguration**:实际上是一个 @Configuration,允许在上下文中注册额外的 bean 或导入其他配置类。 2. **@ComponentScan**:扫描被 @Component、@Service、@Controller 等注解标记的 bean。 3. **@EnableAutoConfiguration**:启用 Spring Boot 的自动配置机制。 #### @EnableAutoConfiguration 这个注解是实现自动装配的核心,通过 @Import 导入了 AutoConfigurationImportSelector 类。 ```java @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage @Import({AutoConfigurationImportSelector.class}) public @interface EnableAutoConfiguration { String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration"; Class<?>[] exclude() default {}; String[] excludeName() default {}; } ``` #### AutoConfigurationImportSelector 类 这个类实现了 ImportSelector 接口,通过 selectImports 方法获取所有符合条件的类的全限定类名,这些类需要被加载到 IoC 容器中。 ```java public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered { @Override public String[] selectImports(AnnotationMetadata annotationMetadata) { if (!isEnabled(annotationMetadata)) { return NO_IMPORTS; } else { AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader); AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata); return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations()); } } private AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata, AnnotationMetadata annotationMetadata) { if (!isEnabled(annotationMetadata)) { return EMPTY_ENTRY; } else { AnnotationAttributes attributes = getAttributes(annotationMetadata); List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes); configurations = removeDuplicates(configurations); Set<String> exclusions = getExclusions(annotationMetadata, attributes); checkExcludedClasses(configurations, exclusions); configurations.removeAll(exclusions); configurations = filter(configurations, autoConfigurationMetadata); fireAutoConfigurationImportEvents(configurations, exclusions); return new AutoConfigurationEntry(configurations, exclusions); } } } ``` 1. **判断自动装配开关是否打开**: 默认情况下,`spring.boot.enableautoconfiguration=true`。 2. **获取 `EnableAutoConfiguration` 注解中的 `exclude` 和 `excludeName`**: 3. **获取需要自动装配的所有配置类**: 读取 `META-INF/spring.factories` 文件中定义的自动配置类。 4. **筛选自动配置类**: 通过 `@ConditionalOnClass`、`@ConditionalOnMissingBean` 等注解进行条件筛选,按需加载配置类。 ```java @Configuration @ConditionalOnClass({ RabbitTemplate.class, Channel.class }) @EnableConfigurationProperties(RabbitProperties.class) @Import(RabbitAnnotationDrivenConfiguration.class) public class RabbitAutoConfiguration { } ``` #### 条件注解 Spring Boot 提供了一系列条件注解,用于按需加载配置: 1. **@ConditionalOnBean**:当容器里有指定 Bean 的条件下。 2. **@ConditionalOnMissingBean**:当容器里没有指定 Bean 的情况下。 3. **@ConditionalOnSingleCandidate**:当指定 Bean 在容器中只有一个,或者虽然有多个但是指定首选 Bean。 4. **@ConditionalOnClass**:当类路径下有指定类的条件下。 5. **@ConditionalOnMissingClass**:当类路径下没有指定类的条件下。 6. **@ConditionalOnProperty**:指定的属性是否有指定的值。 7. **@ConditionalOnResource**:类路径是否有指定的值。 8. **@ConditionalOnExpression**:基于 SpEL 表达式作为判断条件。 9. **@ConditionalOnJava**:基于 Java 版本作为判断条件。 10. **@ConditionalOnJndi**:在 JNDI 存在的条件下查找指定的位置。 11. **@ConditionalOnNotWebApplication**:当前项目不是 Web 项目的条件下。 12. **@ConditionalOnWebApplication**:当前项目是 Web 项目的条件下。 ### 3. 如何实现一个 Starter? 创建一个 Spring Boot Starter 的步骤如下: 1. **创建一个新的 Maven 项目**。 2. **定义自动配置类**: 创建一个自动配置类,并使用条件注解按需加载。 ```java @Configuration @ConditionalOnClass(MyService.class) @EnableConfigurationProperties(MyServiceProperties.class) public class MyServiceAutoConfiguration { private final MyServiceProperties properties; public MyServiceAutoConfiguration(MyServiceProperties properties) { this.properties = properties; } @Bean @ConditionalOnMissingBean public MyService myService() { return new MyService(properties.getConfig()); } } ``` 3. **定义属性类**: ```java @ConfigurationProperties(prefix = "my.service") public class MyServiceProperties { private String config; // getters and setters } ``` 4. **创建 `META-INF/spring.factories` 文件**: 在 `src/main/resources/META-INF` 目录下创建 `spring.factories` 文件,并添加自动配置类的全限定名。 ```properties org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.example.MyServiceAutoConfiguration ``` 5. **打包发布**: 将项目打包成 Jar 包,并发布到 Maven 仓库。 6. **使用 Starter**: 在其他 Spring Boot 项目中引入这个 Starter。 ```xml <dependency> <groupId>com.example</groupId> <artifactId>my-service-spring-boot-starter</artifactId> <version>1.0.0</version> </dependency> ``` 通过以上步骤,可以创建一个自定义的 Spring Boot Starter,并在其他项目中方便地使用它。
    编辑于 2022-08-24 15:04 •IP属地 美国
    举报
    评论
    收藏

  • 夜太
    明知不可为而为之就是我最大的诚意
    ![image.png](https://images.codewd.com/65da66eb49f743e9ef23881623df4c36.png)
    编辑于 2022-12-16 20:25 •IP属地 西藏
    举报
    评论
    收藏