Spring Boot 自动装配

Spring Boot 自动装配

理论基础

从启动类上的 @SpringBootApplication 开始。

@EnableAutoConfiguration -> @Import(AutoConfigurationImportSelector.class)

查看 AutoConfigurationImportSelector#getAutoConfigurationEntry

// 导入配置类
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
    if (!isEnabled(annotationMetadata)) {
        return EMPTY_ENTRY;
    }
    AnnotationAttributes attributes = getAttributes(annotationMetadata);
    
    // 导入 spring.factories 里的配置类
    List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
    // 移除重复的配置类
    configurations = removeDuplicates(configurations);
    // 获取 exclude 的配置类
    Set<String> exclusions = getExclusions(annotationMetadata, attributes);
    checkExcludedClasses(configurations, exclusions);
    // 移除 exclude 的配置类
    configurations.removeAll(exclusions);
    // 过滤配置类
    configurations = getConfigurationClassFilter().filter(configurations);
    fireAutoConfigurationImportEvents(configurations, exclusions);
    return new AutoConfigurationEntry(configurations, exclusions);
}
  1. Spring 会将 META-INF/spring.factories 下的配置类注册到容器中(参考 SPI)
  2. Spring 会根据 META-INF/spring-autoconfigure-metadata.properties 的配置进行过滤
  3. application.properties 的提示来自于 META-INF/additional-spring-configuration-metadata.json

断点调试

导入配置类

一、引入 spring-boot-starter ,下断点 debug 启动

image-20220220225310161

image-20220220233509052

二、查看 spring-boot-autoconfigure.jarspring.factories

image-20220220225958293

三、再引入 mybatis-plus-boot-starter,查看 mybatis-plus-boot-starter.jarspring.factories

image-20220220233824766

四、再次 debug 启动

image-20220220230439105

127 + 3 = 130 127+3=130 127+3=130 对上

排除配置类

一、到 126 行

image-20220220235028857

没有排除任何配置类

二、再到启动类,排除一些配置类

image-20220220235520390

三、再次调试

image-20220220235640453

image-20220220235929895

四、跳到 128 行,移除完被排除的配置类

image-20220220235749734

image-20220220235814210

130 130 130 变到 129 129 129 排除了一个配置类

五、跳到 129 行,过滤完配置类

image-20220221003639337

image-20220221001100734

最后还剩下 31 个

过滤配置类

image-20220221002343532

image-20220221002507619

image-20220221002526363

一、当前是没有引入 spring-boot-starter-data-mongodb 的 。所以自然没有 MongoDataAutoConfiguration

image-20220221003035633

二、查看 spring-boot-autoconfigure.jarspring-autoconfigure-metadata.propertiesMongoAutoConfiguration

image-20220221003232486

image-20220221004904468

ConditionOnClass 只要存在后面跟着的类,就会加载 AutoConfigureAfter 后面跟着的类

三、创建一个 com.mongodb.client.MongoClientorg.springframework.data.mongodb.core.MongoTemplate

image-20220221003424490

四、再次调试,过滤完配置类

image-20220221003609490

image-20220221003752240

有了 MongoDataAutoConfiguration

自动装配流程

从上述可知,读入配置类是通过 getAutoConfigurationEntry,在这下入断点,反向推出流程。

一、118 行下断点,debug

image-20220221104014120

二、熟悉的 refresh

image-20220221104153648

image-20220221104253629

这就和 Spring 源码连起来了

自定义 starter

创建 user-boot-starter

image-20220221183608481

一、建配置类、属性类、Bean

@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties({UserProperties.class})
@ConditionalOnClass(User.class)
public class UserAutoConfiguration {
    private final UserProperties properties;

    public UserAutoConfiguration(UserProperties properties) {
        this.properties = properties;
    }

    @Bean
    @ConditionalOnMissingBean
    public User user() {
        User user = new User();
        user.setId(properties.getId());
        user.setName(properties.getName());
        return user;
    }
}

@ConfigurationProperties(prefix = "user.info")
public class UserProperties {
    private String name;
    private Integer id;

    // 省略 getter/setter、toString
}


public class User {
    private String name;
    private Integer id;
    
    // 省略 getter/setter、toString
}

二、配置 spring.factories

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  com.wang.user.autoconfigure.UserAutoConfiguration

三、配置 spring-autoconfigure-metadata.properties

com.wang.user.autoconfigure.UserAutoConfiguration=
com.wang.user.autoconfigure.UserAutoConfiguration.AutoConfigureAfter=com.wang.user.autoconfigure.UserAutoConfiguration
com.wang.user.autoconfigure.UserAutoConfiguration.ConditionalOnClass=com.wang.user.bean.User

四、配置 additional-spring-configuration-metadata.json

{
  "groups": [
    {
      "sourceType": "com.wang.user.autoconfigure.UserProperties",
      "name": "user.info",
      "type": "com.wang.user.autoconfigure.UserProperties"
    }
  ],
  "properties": [
    {
      "name": "user.info.id",
      "type": "java.lang.Integer",
      "description": "用户ID.",
      "sourceType": "com.wang.user.autoconfigure.UserProperties"
    },
    {
      "name": "user.info.name",
      "type": "java.lang.String",
      "description": "用户名.",
      "sourceType": "com.wang.user.autoconfigure.UserProperties"
    }
  ],
  "hints": []
}

五、添加依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-autoconfigure</artifactId>
    <scope>compile</scope>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>

测试 user-boot-starter

一、测试类

@RunWith(SpringRunner.class)
@SpringBootTest
public class UserTest {
    @Autowired
    private User user;
    @Test
    public void test01() {
        System.out.println(user);
    }
}

二、写 application.yml

image-20220221183948689

有提示

三、启动测试类

image-20220221184035616

自动配置成功

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值