🍊
翻译橙
🍊返回主站🤖参与贡献
  • hello,这里是翻译橙
  • spring boot参考文档
    • 1. 法律
    • 2. 寻求帮助
    • 3. 文档概述
    • 4. 入门
    • 5. 升级Spring Boot
    • 6. 使用 Spring Boot 进行开发
      • 6.1. 构建系统
      • 6.2. 构建你的代码
      • 6.3. 配置类
      • 6.4. 自动配置
      • 6.5. Spring Bean 和依赖注入
      • 6.6. 使用@SpringBootApplication注解
      • 6.7. 运行您的应用程序
      • 6.8. 开发者工具
      • 6.9. 打包您的生产应用程序
      • 6.10. 接下来读什么
    • 7.核心特性
      • 7.1. SpringApplication
      • 7.2. 外部化配置
      • 7.3.Profile配置
      • 7.4.日志记录
      • 7.5.国际化
      • 7.6 面向切面的编程
      • 7.7. JSON
      • 7.8. 任务执行与调度
      • 7.9. 单元测试
        • 7.9.1. 测试范围依赖
        • 7.9.2. 测试 Spring 应用程序
        • 7.9.3. 测试 Spring Boot 应用程序
        • 7.9.4. 测试容器
        • 7.9.5. 测试工具
      • 7.10. Docker Compose 支持
      • 7.11. 测试容器支持
      • 7.12. 创建您自己的自动配置
      • 7.13. Kotlin 支持
      • 7.14 SSL
      • 7.15.接下来要读什么
    • 8. 网络
      • 8.1. Servlet Web 应用程序
        • 8.1.1. “Spring Web MVC 框架”
        • 8.1.2. JAX-RS 和Jersey
        • 8.1.3. 嵌入式 Servlet 容器支持
      • 8.2 反应式网络应用程序
        • 8.2.1. “Spring WebFlux 框架”
        • 8.2.2. 嵌入式反应式服务器支持
        • 8.2.3. 反应式服务器资源配置
      • 8.3. 优雅关机
      • 8.4. spring安全
        • 8.4.1. MVC安全
        • 8.4.2. WebFlux 安全
        • 8.4.3. OAuth2
        • 8.4.4. SAML 2.0
      • 8.5. spring 会话
      • 8.6.GraphQL
      • 8.7. Spring HATEOAS
      • 8.8.接下来读什么
    • 9. 数据
      • 9.1. SQL数据库
      • 9.2. 使用 NoSQL 技术
      • 9.3. 接下来读什么
    • 10. 消息
      • 10.1. JMS
      • 10.2. AMQP
      • 10.3. Apache Kafka 支持
      • 10.4. Apache Pulsar 支持
      • 10.5. RSocket
      • 10.6. Spring Integration
      • 10.7. WebSockets
      • 10.8. What to Read Next
    • 11. IO
      • 11.1. 缓存
      • 11.2. Hazelcast
      • 11.3. Quartz 调度程序
      • 11.4. 发送电子邮件
      • 11.5. 验证
      • 11.6. 调用 REST 服务
      • 11.7. web services
      • 11.8. 使用 JTA 进行分布式事务
      • 11.9. 接下来读什么
    • 12. 容器镜像
  • Spring核心功能
    • 1.IOC容器和Bean简介
      • 1.2. 容器概述
      • 1.3. Bean概述
      • 1.4. 依赖项
        • 1.4.1. 依赖注入
        • 1.4.2. 详细的依赖关系和配置
        • 1.4.3. 使用depends-on
        • 1.4.4. 延迟初始化的 Bean
        • 1.4.5. 自动装配协作者
        • 1.4.6. 方法注入
    • 2. Resources
      • 2.1. 介绍
      • 2.2. Resource接口
      • 2.3. 内置Resource实现
      • 2.4. ResourceLoader接口
      • 2.5. ResourcePatternResolver接口
      • 2.6. ResourceLoaderAware接口
      • 2.7. 资源作为依赖
      • 2.8. 应用程序上下文和资源路径
    • 3. 验证、数据绑定和类型转换
      • 3.1. 使用 Spring 的 Validator 接口进行验证
      • 3.2. 将代码解析为错误消息
      • 3.3. Bean 操作和BeanWrapper
      • 3.4. spring类型转换
      • 3.5. spring字段格式
      • 3.6. 配置全局日期和时间格式
      • 3.7. Java Bean 验证
    • 4. SpEL表达式
    • 5. Spring 面向切面编程
      • 5.1. AOP 概念
      • 5.2. Spring AOP 的能力和目标
      • 5.3. AOP 代理
      • 5.4. @AspectJ 支持
        • 5.4.1. 启用@AspectJ 支持
        • 5.4.2. 声明一个切面
        • 5.4.3. 声明切入点
        • 5.4.4. 声明切点
        • 5.4.5. 切面说明
        • 5.4.6. 切面实例化模型
        • 5.4.7. AOP 示例
      • 5.5. 基于模式的 AOP 支持
      • 5.6. 选择要使用的 AOP 声明样式
      • 5.7. 混合切面类型
      • 5.8. 代理机制
      • 5.9. @AspectJ 代理的程序化创建
      • 5.10. 在 Spring 应用程序中使用 AspectJ
      • 5.11.更多资源
    • 6. Spring AOP API
      • 6.1. Spring中的切入点API
      • 6.2. Spring 中的 Advice API
      • 6.3. Spring 中的 Advisor API
      • 6.4. 使用ProxyFactoryBean创建 AOP 代理
      • 6.5. 简洁的代理定义
      • 6.6. 以编程方式创建 AOP 代理ProxyFactory
      • 6.7. 操作切面对象
      • 6.8. 使用“自动代理”工具
      • 6.9. 使用TargetSource实现
      • 6.10. 定义新的切面类型
    • 7. 空指针安全
    • 8. 数据缓冲器和编解码器
    • 9. 日志
    • 10. 附录
      • 10.1. XML 模式
      • 10.2. 自定义XML Schema
        • 10.2.1. 创作 Schema
        • 10.2.2. 编码一个NamespaceHandler
        • 10.2.3. 使用BeanDefinitionParser
        • 10.2.4. 注册处理程序和模式
        • 10.2.5. 在 Spring XML 配置中使用自定义扩展
        • 10.2.6. 更详细的例子
      • 10.3. 应用程序启动步骤
  • 使用redis实现分布式锁
  • Java 安全标准算法名称
  • JDK 9 JEP
  • JDK 10 JEP
  • 人件
    • 《人件》
    • 第一部分 管理人力资源
      • 01 此时此刻,一个项目正在走向失败
      • 02 干酪汉堡,做一个,卖一个
      • 03 维也纳在等你
      • 04 质量——如果时间允许
      • 05 再谈帕金森定律
      • 06 苦杏素
    • 第二部分 办公环境
      • 07 家具警察
      • 08 “朝九晚五在这里啥也完成不了。”
      • 09 在空间上省钱
      • 间奏曲:生产效率度量和不明飞行物
      • 10 大脑时问与身体时间
      • 11 电话
      • 12 门的回归
      • 13 采取保护步骤
    • 第三部分 正确的人
      • 14 霍恩布洛尔因素
      • 15 谈谈领导力
      • 16 雇一名杂耍演员
      • 17 与他人良好合作
      • 18 童年的终结
      • 19 在这儿很开心
      • 20 人力资本
    • 第四部分 高效团队养成
      • 21 整体大于部分之和
      • 22 黑衣团队
      • 23 团队自毁
      • 24 再谈团队自毁
      • 25 竞争
      • 26 一顿意面晚餐
      • 27 敞开和服
      • 28 团队形成的化学反应
    • 第五部分 沃土
      • 29 自我愈复系统
      • 30 与风险共舞
      • 3l 会议、独白和交流
      • 32 终极管理罪恶得主是……
      • 33 “邪恶”电邮
      • 34 让改变成为可能
      • 35 组织型学习
      • 36 构建社区
    • 第六部分 快乐地工作
      • 37 混乱与秩序
      • 38 自由电子
      • 39 霍尔加·丹斯克
由 GitBook 提供支持
在本页

这有帮助吗?

在GitHub上编辑
  1. spring boot参考文档
  2. 7.核心特性

7.12. 创建您自己的自动配置

上一页7.11. 测试容器支持下一页7.13. Kotlin 支持

最后更新于1年前

这有帮助吗?

如果您在一家开发共享库的公司工作,或者如果您在开源或商业库中工作,您可能想要开发自己的自动配置。自动配置类可以捆绑在外部 jar 中,并且仍然可以被 Spring Boot 拾取。

自动配置可以与提供自动配置代码以及您将使用的典型库的“启动器”相关联。我们首先介绍了构建您自己的自动配置所需了解的内容,然后我们继续介绍。 一个可用于展示如何逐步创建启动器。

7.12.1.了解自动配置的 Bean

在幕后,自动配置是通过@AutoConfiguration注解实现的。这个注解本身是用 @Configuration元注解的,可以使自动配置成为标准@Configuration类。添加@Conditional注解用于限制何时应用自动配置。通常,自动配置类使用@ConditionalOnClass和@ConditionalOnMissingBean注解。这确保了自动配置仅在找到相关类并且您没有声明自己的类时适用@Configuration。

您可以浏览源代码以查看@ConfigurationSpring 提供的类(参见文件)。

7.12.2. 定位自动配置候选

Spring Boot 检查发布的 jar中是否存在META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件。该文件应列出您的配置类,如以下示例所示:

com.mycorp.libx.autoconfigure.LibXAutoConfiguration
com.mycorp.libx.autoconfigure.LibXWebAutoConfiguration

您可以通过在此文件中使用#注释。 自动配置只能 以这种方式加载。确保它们是在特定的包空间中定义的,并且它们永远不是组件扫描的目标。此外,自动配置类不应启用组件扫描以查找其他组件。应该使用 特定的 @Import来代替。

如果您的配置需要按特定顺序应用,您可以使用或注解。例如,如果您提供特定于 Web 的配置,您的WebMvcAutoConfiguration类可能需要在.

如果您使用注解,则可以使用before、 beforeName、after和afterName属性别名来代替专用注解。 如果您想订购某些彼此不应该有任何直接了解的自动配置,您也可以使用@AutoConfigureOrder. 该注解与常规注解具有相同的语义,但@Order为自动配置类提供了专用顺序。

与标准@Configuration类一样,应用自动配置类的顺序只影响定义它们的 bean 的顺序。随后创建这些 bean 的顺序不受影响,由每个 bean 的依赖关系和任何@DependsOn定义的关系决定。

7.12.3. 条件注解

您几乎总是希望@Conditional在您的自动配置类中包含一个或多个注解。注解是一个常见的@ConditionalOnMissingBean例子,如果开发人员对你的默认设置不满意,它可以让他们覆盖自动配置。

Spring Boot 包含许多注解,您可以通过注解类或单个方法@Conditional在自己的代码中重用它们。这些注解包括:@Configuration @Bean

7.12.3.1.class条件

此机制不适用于@Bean通常返回类型是条件目标的方法:在方法上的条件适用之前,JVM 将加载类和可能处理的方法引用,如果类不是,则这些方法引用将失败当下。

为了处理这种情况,可以使用一个单独的@Configuration类来隔离条件,如下例所示:

@AutoConfiguration
// Some conditions ...
public class MyAutoConfiguration {
​
    // Auto-configured beans ...
​
    @Configuration(proxyBeanMethods = false)
    @ConditionalOnClass(SomeService.class)
    public static class SomeServiceConfiguration {
​
        @Bean
        @ConditionalOnMissingBean
        public SomeService someService() {
            return new SomeService();
        }
​
    }
​
}

如果您使用@ConditionalOnClass或@ConditionalOnMissingClass作为元注解的一部分来组成您自己的组合注解,则必须name在不处理这种情况下使用 as 引用类。

7.12.3.2. bean条件

@ConditionalOnBean和注解允许根据@ConditionalOnMissingBean特定 bean 的存在或不存在来包含 bean。您可以使用该value属性按类型name指定bean 或按名称指定bean。该search属性允许您限制ApplicationContext在搜索 bean 时应考虑的层次结构。

放置在@Bean方法上时,目标类型默认为方法的返回类型,如下例所示:

@AutoConfiguration
public class MyAutoConfiguration {
​
    @Bean
    @ConditionalOnMissingBean
    public SomeService someService() {
        return new SomeService();
    }
​
}

在前面的示例中,someService如果.SomeService``ApplicationContext 您需要非常小心添加 bean 定义的顺序,因为这些条件是根据到目前为止已处理的内容进行评估的。出于这个原因,我们建议仅在自动配置类上使用@ConditionalOnBean和@ConditionalOnMissingBean注解(因为保证在添加任何用户定义的 bean 定义后加载这些注解)。 @ConditionalOnBean并且@ConditionalOnMissingBean不要阻止@Configuration创建类。在类级别使用这些条件和用@Bean注解标记每个包含的方法之间的唯一区别是,如果条件不匹配 ,前者会阻止将类注册为 bean。@Configuration 声明@Bean方法时,在方法的返回类型中提供尽可能多的类型信息。例如,如果你的 bean 的具体类实现了一个接口,那么 bean 方法的返回类型应该是具体类而不是接口。在使用 bean 条件时,在方法中提供尽可能多的类型信息@Bean尤为重要,因为它们的评估只能依赖于方法签名中可用的类型信息。

7.12.3.3. 属性条件

@ConditionalOnProperty注解允许基于 Spring Environment 属性包含配置。使用prefix和name属性指定应检查的属性。默认情况下,匹配任何存在但不等于false的属性。您还可以使用havingValue和matchIfMissing属性创建更高级的检查。

7.12.3.4.资源条件

@ConditionalOnResource注解允许仅在存在特定资源时才包含配置。可以使用通常的 Spring 约定来指定资源,如下例所示:file:/home/user/test.dat

7.12.3.5.网络应用条件

@ConditionalOnWebApplication和注解允许根据@ConditionalOnNotWebApplication应用程序是否为“Web 应用程序”来包含配置。基于 servlet 的 Web 应用程序是任何使用 Spring WebApplicationContext、定义session范围或具有ConfigurableWebEnvironment. 反应式 Web 应用程序是任何使用ReactiveWebApplicationContext或具有ConfigurableReactiveWebEnvironment.

注解允许根据@ConditionalOnWarDeployment应用程序是否是部署到容器的传统 WAR 应用程序来包含配置。对于使用嵌入式服务器运行的应用程序,此条件将不匹配。

7.12.3.6.SpEL 表达条件

在表达式中引用 bean 将导致该 bean 在上下文刷新处理中很早就被初始化。结果,bean 将不适合进行后处理(例如配置属性绑定),并且其状态可能不完整。

7.12.4.测试您的自动配置

自动配置可能受到许多因素的影响:用户配置(定义@Bean和定制Environment)、条件评估(特定库的存在)等。具体来说,每个测试都应该创建一个定义良好ApplicationContext的,代表这些定制的组合。 ApplicationContextRunner提供了实现这一目标的好方法。

ApplicationContextRunner通常被定义为测试类的一个字段,用于收集基本的、通用的配置。以下示例确保始终调用MyServiceAutoConfiguration:

private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
        .withConfiguration(AutoConfigurations.of(MyServiceAutoConfiguration.class));

如果必须定义多个自动配置,则无需对它们的声明进行排序,因为它们的调用顺序与运行应用程序时完全相同。 每个测试都可以使用运行器来表示特定的用例。例如,下面的示例调用了用户配置 ( UserConfiguration) 并检查自动配置是否正确退出。调用run 方法提供可与 AssertJ 一起使用的回调上下文。

@Test
void defaultServiceBacksOff() {
    this.contextRunner.withUserConfiguration(UserConfiguration.class).run((context) -> {
        assertThat(context).hasSingleBean(MyService.class);
        assertThat(context).getBean("myCustomService").isSameAs(context.getBean(MyService.class));
    });
}
​
@Configuration(proxyBeanMethods = false)
static class UserConfiguration {
​
    @Bean
    MyService myCustomService() {
        return new MyService("mine");
    }
​
}

也可以轻松自定义Environment,如以下示例所示:

@Test
void serviceNameCanBeConfigured() {
    this.contextRunner.withPropertyValues("user.name=test123").run((context) -> {
        assertThat(context).hasSingleBean(MyService.class);
        assertThat(context.getBean(MyService.class).getName()).isEqualTo("test123");
    });
}

Runner也可用于显示ConditionEvaluationReport. 报告可以在INFO或DEBUG水平打印。以下示例显示了如何使用ConditionEvaluationReportLoggingListener打印自动配置测试中的报告。

class MyConditionEvaluationReportingTests {
​
    @Test
    void autoConfigTest() {
        new ApplicationContextRunner()
            .withInitializer(new ConditionEvaluationReportLoggingListener(LogLevel.INFO))
            .run((context) -> {
                    // Test something...
            });
    }
​
}

7.12.4.1.模拟 Web 上下文

如果您需要测试仅在 servlet 或响应式 Web 应用程序上下文中运行的自动配置,请分别使用WebApplicationContextRunner或ReactiveWebApplicationContextRunner。

7.12.4.2. 重写类路径

还可以测试在运行时不存在特定类和/或包时会发生什么。Spring Boot 附带一个runner 可以轻松使用的FilteredClassLoader。在以下示例中,我们断言如果MyService不存在,则自动配置被正确禁用:

@Test
void serviceIsIgnoredIfLibraryIsNotPresent() {
    this.contextRunner.withClassLoader(new FilteredClassLoader(MyService.class))
            .run((context) -> assertThat(context).doesNotHaveBean("myService"));
}

7.12.5.创建自己的启动器(starter)

一个典型的 Spring Boot 启动器包含自动配置和自定义给定技术的基础设施的代码,我们称之为“acme”。为了使其易于扩展,可以将专用命名空间中的许多配置键暴露给环境。最后,提供了一个“starter”依赖项来帮助用户尽可能轻松地开始。

具体来说,自定义启动器可以包含以下内容:

  • 包含“acme”的自动配置代码的autoconfigure模块。

  • 提供对starter模块的依赖关系的autoconfigure模块以及“acme”和通常有用的任何其他依赖关系。简而言之,添加启动器应该提供开始使用该库所需的一切。

两个模块中的这种分离绝不是必要的。如果“acme”有多种风格、选项或可选功能,那么最好将自动配置分开,因为您可以清楚地表达某些功能是可选的事实。此外,您还可以制作一个启动器来提供有关这些可选依赖项的意见。同时,其他人只能依靠autoconfigure模块,制作自己的不同意见的starter。

如果自动配置相对简单并且没有可选功能,那么在启动器中合并两个模块绝对是一种选择。

7.12.5.1.命名

您应该确保为您的启动器提供适当的命名空间。即使您使用不同的 Maven groupId,也不要使用以spring-boot开头的模块名称。以便我们将来可能会为您自动配置的内容提供官方支持。

根据经验,您应该在启动器之后命名组合模块。例如,假设您正在为“acme”创建一个启动器,并且您命名自动配置模块acme-spring-boot和启动器acme-spring-boot-starter。如果您只有一个模块将两者结合起来,请将其命名为acme-spring-boot-starter.

7.12.5.2. 配置键(ConfigurationProperties)

如果您的启动器提供配置键,请为它们使用唯一的命名空间。特别是,不要将您的键包含在 Spring Boot 使用的命名空间中(例如server、management、spring等)。如果您使用相同的命名空间,我们将来可能会以破坏您的模块的方式修改这些命名空间。根据经验,在所有键前面加上您自己的命名空间(例如acme)。

确保通过为每个属性添加字段 javadoc 来记录配置键,如以下示例所示:

@ConfigurationProperties("acme")
public class AcmeProperties {
​
    /**
     * Whether to check the location of acme resources.
     */
    private boolean checkLocation = true;
​
    /**
     * Timeout for establishing a connection to the acme server.
     */
    private Duration loginTimeout = Duration.ofSeconds(3);
​
    // getters/setters ...
​
}

您应该只使用带有@ConfigurationProperties字段的纯文本Javadoc ,因为它们在添加到 JSON 之前不会被处理。

以下是我们在内部遵循的一些规则,以确保描述一致:

  • 不要以“The”或“A”开始描述。

  • 对于boolean类型,以“Whether”或“Enable”开始描述。

  • 对于基于集合的类型,以“Comma-separated list”开始描述

  • 如果默认单位与毫秒不同,则使用java.time.Duration而不是long描述默认单位,例如“If a duration suffix is not specified, seconds will be used”。

  • 除非必须在运行时确定,否则不要在描述中提供默认值。

7.12.5.3.“自动配置”模块

autoconfigure模块包含开始使用该库所需的一切。它还可能包含配置键定义(例如@ConfigurationProperties)和任何回调接口,可用于进一步自定义组件的初始化方式。

您应该将库的依赖项标记为可选,以便您可以更轻松地将autoconfigure模块包含在项目中。如果您这样做,则不会提供该库,并且默认情况下,Spring Boot 会退出。 Spring Boot 使用注解处理器来收集元数据文件 ( META-INF/spring-autoconfigure-metadata.properties) 中的自动配置条件。如果该文件存在,它将用于急切地过滤不匹配的自动配置,这将缩短启动时间。建议在包含自动配置的模块中添加以下依赖项:

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

如果您在应用程序中直接定义了自动配置,请确保配置了spring-boot-maven-plugin以防止repackage目标将依赖项添加到 fat jar 中:

<project>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.springframework.boot</groupId>
                            <artifactId>spring-boot-autoconfigure-processor</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

对于 Gradle 4.5 及更早版本,应在compileOnly配置中声明依赖项,如以下示例所示:

dependencies {
    compileOnly "org.springframework.boot:spring-boot-autoconfigure-processor"
}

对于 Gradle 4.6 及更高版本,应在annotationProcessor配置中声明依赖项,如下例所示:

dependencies {
    annotationProcessor "org.springframework.boot:spring-boot-autoconfigure-processor"
}

7.12.5.4.Starter模块

启动器实际上是一个空罐子。它的唯一目的是提供必要的依赖项以使用该库。您可以将其视为对入门所需内容的固执己见。

不要对添加启动器的项目做出假设。如果您要自动配置的库通常需要其他启动器,请同时提及它们。如果可选依赖项的数量很高,则提供一组适当的默认依赖项可能会很困难,因为您应该避免包含对于库的典型使用而言不必要的依赖项。换句话说,您不应该包含可选依赖项。 无论哪种方式,您的 starter 都必须直接或间接引用核心 Spring Boot starter ( spring-boot-starter)(如果您的 starter 依赖于另一个 starter,则无需添加它)。如果仅使用您的自定义启动器创建项目,则 Spring Boot 的核心功能将因核心启动器的存在而受到尊重。

@ConditionalOnClass和@ConditionalOnMissingClass注解允许根据@Configuration特定类的存在与否来包含类。由于注解元数据是使用解析的,因此您可以使用该value属性来引用真实的类,即使该类实际上可能不会出现在正在运行的应用程序类路径中。name如果您更喜欢使用值指定类名,也可以使用该属性String。

@ConditionalOnExpression注解允许基于的结果包含配置。

确保,以便您的密钥也可以使用 IDE 帮助。您可能需要查看生成的元数据 ( META-INF/spring-configuration-metadata.json) 以确保正确记录您的密钥。在兼容的 IDE 中使用您自己的启动器也是验证元数据质量的好主意。

创建自定义启动器所需的典型步骤
演示项目
spring-boot-autoconfigure
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@AutoConfigureAfter
@AutoConfigureBefore
@AutoConfiguration
类条件
bean条件
属性条件
资源条件
网络应用条件
SpEL 表达式条件
ASM
SpEL 表达式
触发元数据生成