我创建了许多常见的小bean定义容器(@Configuration
),我用它来快速开发Spring Boot应用程序,如:
@Import({
FreemarkerViewResolver.class, // registers freemarker that auto appends <#escape etc.
ConfigurationFromPropertiesFile.class, // loads conf/configuration.properties
UtfContentTypeResponse.class, // sets proper Content-language and Content-type
LocaleResolverWithLanguageSwitchController // Locale resolver + switch controller
);
class MySpringBootApp ...
例如,其中一个@Configuration
可以设置语言环境cookie的会话存储,Web控制器可以切换到所选语言等。
使用和重用它们非常有趣,但将它设置为参数化真的很棒,这可以允许更多的重用。我的意思是:
伪码:
@Imports( imports = {
@FreemarkerViewResolver( escapeHtml = true, autoIncludeSpringMacros = true),
@ConfigurationFromProperties( path = "conf/configuration.properties" ),
@ContentTypeResponse( encoding = "UTF-8" ),
@LocaleResolver( switchLocaleUrl = "/locale/{loc}", defaultLocale = "en"
})
所以,我的意思是“可配置的@Configurations
”。 以这种方式进行配置的最佳方式是什么?
也许更像这样的东西(再次,伪代码):
@Configuration
public class MyAppConfiguration {
@Configuration
public FreemarkerConfiguration freemarkerConfiguration() {
return FreemarkerConfigurationBuilder.withEscpeAutoAppend();
}
@Configuration
public ConfigurationFromPropertiesFile conf() {
return ConfigurationFromPropertiesFile.fromPath("...");
}
@Configuration
public LocaleResolverConfigurator loc() {
return LocaleResolverConfigurator.trackedInCookie().withDefaultLocale("en").withSwitchUrl("/switchlocale/{loc}");
}
答案 0 :(得分:10)
让我引用Spring Boot Reference Guide - Externalized Configuration:
“Spring Boot允许您外部化配置,以便在不同环境中使用相同的应用程序代码。”
在我看来,自定义不是在导入时通过注释参数完成的,例如在你的第二个伪代码块中,而是在运行时进行自定义,例如在配置类中。让我调整你的第三个代码块(只有一个函数):
@Configuration
public class MyAppConfiguration {
@Autowired
private Environment env;
// Provide a default implementation for FreeMarkerConfigurer only
// if the user of our config doesn't define her own configurer.
@Bean
@ConditionalOnMissingBean(FreeMarkerConfigurer.class)
public FreeMarkerConfigurer freemarkerConfig() {
FreeMarkerConfigurer result = new FreeMarkerConfigurer();
result.setTemplateLoaderPath("/WEB-INF/views/");
return result;
}
...
@Bean
public LocaleResolverConfigurator loc() {
String defaultLocale = env.getProperty("my.app.config.defaultlocale", "en");
String switchLocale = env.getProperty("my.app.config.switchlocale", "/switchlocale/{loc}");
return LocaleResolverConfigurator.trackedInCookie().withDefaultLocale(defaultLocale).withSwitchUrl(switchLocale);
}
对于LocaleResolverConfigurator
,从环境中读取配置,定义了有意义的默认值。通过以任何支持的方式(在第一个链接中记录)为配置参数提供不同的值 - 通过命令行或yaml文件,可以轻松更改默认值。注释参数的优点是您可以在运行时而不是编译时更改行为。
您还可以注入配置参数(如果您希望将它们作为实例变量)或使用许多其他条件,例如@ConditionalOnMissingBean
,@ConditionalOnClass
,@ConditionalOnExpression
和so on。例如,使用@ConditionalOnClass
,您可以检查特定类是否在类路径上,并为此类标识的库提供设置。使用@ConditionalOnMissingClass
,您可以提供替代实施。在上面的示例中,我使用ConditionalOnMissingBean
为FreeMarkerConfigurer
提供了默认实现。此实现仅在没有FreeMarkerConfigurer
bean可用时使用,因此可以轻松覆盖。
看看Spring Boot或社区提供的初学者。好的阅读也是blog entry。我从spring-boot-starter-batch-web学到了很多,他们在德国Java杂志上有一篇文章系列,但部分也在线,请参阅Boot your own infrastructure – Extending Spring Boot in five steps(必读),特别是段落“通过使用属性“。
使您的启动器可配置答案 1 :(得分:2)
虽然我喜欢将导入参数化的想法,但我认为现在使用@Import
和@Configuration
并不合适。
我可以想到两种使用动态配置的方法,它们不依赖于PropertySource
样式配置。
@ImportConfig
注释和注释处理器,该处理器接受硬编码到生成的源文件中的配置属性。BeanFactoryPostProcessor
或BeanPostProcessor
分别添加或操作包含的bean。两者都不是特别简单的IMO,但因为看起来你有一种特殊的工作方式。所以投入的时间可能是值得的。