利用 Spring Boot 的属性支持增强你的应用能力

工程 | Greg L. Turnquist | 2013 年 10 月 30 日 | ...

Spring Boot 正在持续发展壮大。上个月我写了 通过拉取请求贡献 Spring Boot。我深入探讨了 Spring Boot 的各个层面,展示了它令人难以置信的自动配置特性和 CLI 支持。

在这篇文章中,我想深入探讨 Spring Boot 对属性的强大支持。属性虽然看似微不足道,不那么显眼,但却能以非常实际的方式迅速增强你的应用程序。在这篇文章中,我将逐步讲解我是如何为我在上一篇博文中编写的 Spring JMS 支持添加属性支持的。

什么是属性?

属性本质上是将应用程序设置外部化的方式。你可能在应用程序中硬编码了一些信息,但出于多种原因,你希望以后能够更改它。

  • 你的默认配置是基于生产环境的(主机名、端口等),但你需要在测试环境中用不同的主机名覆盖它。
  • 你配置应用程序使用连接池,但想调整连接池的大小。
  • 你需要一个提供给应用程序的“超级秘密”密钥,也许是 OAuth 密钥,并且你绝对不希望在发布的应用程序中放入一个默认密钥。

所有这些用例都强烈需要一种不同的方式来在应用程序启动时提供定制的设置。Spring Boot 帮你解决了这个问题!

Spring JMS 与属性

抽象的用例就到此为止。让我们看看 Spring Boot 如何支持属性的真实示例!我们将更深入地研究 Spring JMS 支持

@Configuration
@ConditionalOnClass({ JmsTemplate.class, ConnectionFactory.class })
@EnableConfigurationProperties(JmsTemplateProperties.class)
public class JmsTemplateAutoConfiguration {

	@Autowired
	private JmsTemplateProperties config;
	. . .
	@ConfigurationProperties(name = "spring.jms")
	public static class JmsTemplateProperties {

		private boolean pubSubDomain = true;

		public boolean isPubSubDomain() {
			return this.pubSubDomain;
		}

		public void setPubSubDomain(boolean pubSubDomain) {
			this.pubSubDomain = pubSubDomain;
		}

	}
	. . .

这段来自 Spring Boot 的 JmsTemplatAutoConfiguration 代码片段展示了几个关键组件。

  • @EnableConfigurationProperties 利用 JmsTemplateProperties 作为属性源,并使其对整个类可用。
  • @ConfigurationProperties(name = "spring.jms") 标记 JmsTemplateProperties 类将成为属性的持有者。以 "spring.jms" 作为前缀,该类的每个属性都成为目标属性。

我只需要创建一个 application.properties 文件并为其赋值即可。

spring.jms.pubSubDomain=true

在该文件的更下方,还有内置连接工厂的属性。

	@Configuration
	@ConditionalOnClass(ActiveMQConnectionFactory.class)
	@ConditionalOnMissingBean(ConnectionFactory.class)
	@EnableConfigurationProperties(ActiveMQConnectionFactoryProperties.class)
	protected static class ActiveMQConnectionFactoryCreator {

		@Autowired
		private ActiveMQConnectionFactoryProperties config;

		@Bean
		ConnectionFactory jmsConnectionFactory() {
			if (this.config.isPooled()) {
				PooledConnectionFactory pool = new PooledConnectionFactory();
				pool.setConnectionFactory(new ActiveMQConnectionFactory(this.config
						.getBrokerURL()));
				return pool;
			}
			else {
				return new ActiveMQConnectionFactory(this.config.getBrokerURL());
			}
		}

	}

	@ConfigurationProperties(name = "spring.activemq")
	public static class ActiveMQConnectionFactoryProperties {

		private String brokerURL = "tcp://localhost:61616";

		private boolean inMemory = true;

		private boolean pooled = false;

		// Will override brokerURL if inMemory is set to true
		public String getBrokerURL() {
			if (this.inMemory) {
				return "vm://localhost";
			}
			else {
				return this.brokerURL;
			}
		}
    . . .

默认情况下,Spring Boot 将创建一个 ActiveMQ 连接工厂,除非你提供自己的

  • ActiveMQConnectionFactoryCreator 已被标记为 @EnableConfigurationProperties
  • 我们可以覆盖 brokerURLinMemorypooled

ActiveMQConnectionFactoryCreator 中,如果设置了 pooled,它会创建一个 PooledConnectionFactory。如果设置了 inMemory,它会使用 vm://localhost。但将其设置为 false 会导致连接工厂切换为使用 brokerURL。

到目前为止,这些属性都是通过各自的 getter 访问的。但这并非唯一的方法。Spring 提供了一个强大的 @Value 注解,可以从包括属性在内的多个源注入数据。

这便是我为 Spring Boot 贡献 Spring JMS 属性支持的主要工作。

让我们看看更多使用 Spring Boot 属性支持的方式。

超级秘密的 GitHub OAuth 数据

我一直在开发一个小应用程序,用于快速列出针对各种入门指南 (Getting Started guides) 的所有未解决问题。它使用 Spring Social GitHub 来查询问题。为了获取我需要的数据,它强大的 GitHubTemplate 需要一个 OAuth 密钥。

@Controller
@Log
class IssueAggregator implements CommandLineRunner {

	/**
	 * This needs to be supplied by application.properties, a file NOT to be put under source control
	 */
	@Value('${token}')
	String githubToken
	
	@Bean
	GitHubTemplate githubTemplate() {
		new GitHubTemplate(githubToken)
	}
	. . .

正如你所猜测的,githubToken 是通过 @Value('${token}') 填充的。如果你仔细观察,会注意到没有默认值。那是因为我不会提供一个默认值。任何需要此应用程序副本的人都必须提供他们自己的秘密 OAuth 密钥,如注释中所述。

注意:这是 Groovy 代码,但相同的注解也适用于 Java(你只需要双引号)。Spring Boot 只是让利用 Spring Framework 的属性支持变得超级容易。

用更多属性覆盖属性

不止如此。我可以在我分发的 JAR 文件中嵌入一个 application.properties 文件,提供默认设置。

但如果我需要覆盖任何设置,我只需创建另一个 application.properties 文件并将其放置在 JAR 文件旁边。Spring Boot 会首先读取内部的 application.properties 文件,然后自动找到外部的文件。

最后,它还会读取使用 Java 的 -Dspring.activemq.inMemory=false 命令行指令提供的属性。这提供了第三种覆盖设置的方式。

附注:对于使用 Windows 的开发者,Spring Boot 提供额外的特殊支持,将诸如 SPRING_ACTIVEMQ_INMEMORYspring-activemq-inmemoryspringActivemqInmemory 等映射到同一个目标:spring.activemq.inMemory。这有助于解决特定平台问题,例如环境变量不支持点号。

总结

希望你现在能够理解 Spring Boot 通过属性设置使我们的应用程序变得灵活和可配置的惊人能力。它可能是一个范围很小的工具,但却非常实用。

编码愉快!

获取 Spring 新闻通讯

订阅 Spring 新闻通讯,保持联系

订阅

领先一步

VMware 提供培训和认证,助你加速前进。

了解更多

获取支持

Tanzu Spring 通过一个简单的订阅,为 OpenJDK™、Spring 和 Apache Tomcat® 提供支持和二进制文件。

了解更多

近期活动

查看 Spring 社区的所有近期活动。

查看全部