与Spring使用'application.properties'文件的模式相比,我们设计的系统使用非常规方式获取属性值。在没有详细介绍的情况下,我们使用的属性管理器使用远程键值存储来获取多个数据中心的属性。
目标是我们希望能够使用 @Value("${prop.from.propMan}") ,这通常可以通过覆盖 {来实现{3}} 即可。这是在Spring中获取属性的一种非常方便的方法,如果我们可以使用它从我们的PropMan获取属性,那将是很好的。
以下是我尝试这样做的一个例子:
@Bean
public PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
PropertySourcesPlaceholderConfigurer pspc = new PropertySourcesPlaceholderConfigurer();
MutablePropertySources ps = env.getPropertySources();
pspc.setIgnoreUnresolvablePlaceholders(Boolean.TRUE);
pspc.setIgnoreUnresolvablePlaceholders(true);
ps.addFirst(new PropManPropertySource("propMan", propMan()));
pspc.setPropertySources(ps);
return pspc;
}
我尝试过的另一件事是添加 PropertyPlaceholderConfigurer ,将新的PropManPropertySource添加到 ApplicationContextInitializer < / em> 初始化应用程序上下文时。这是一个更完整的示例,显示了应用程序类:
@SpringBootApplication
public class Application {
public static void main(String[] args) {
Application app = new Application();
app.start(args);
}
private void start(String[] args) {
SpringApplication app = new SpringApplicationBuilder(Application.class)
.initializers(new AppContextInitializer()).build().run(args);
}
/**
* We need to have an initializer for the ApplicationContext, or else there's no way to have the PropertySource
* added.
*
* One problem I see here is the way the PropMan object is added is that it's not Autowired, so I'm calling the
* method directly propMan(). Ideally it would be autowired and would use simply propMan. When autowiring in
* this class there is an exception "PropertySource cannot be null".
*
* One other thing I've tried was adding PropertyPlaceholderConfiguration, which adds the PropertySource.
**/
@Configuration
public class AppContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext ac) {
ConfigurableEnvironment env = ac.getEnvironment();
MutablePropertySources propertySources = env.getPropertySources();
PropManPropertySource propManPropertySource = new PropManPropertySource("propMan", propMan());
propertySources.addLast(propManPropertySource);
env.addActiveProfile("app");
}
}
@Bean
public PropMan propMan() {
PropManImpl propMan = new PropManImpl();
propMan.init();
return propMan;
}
}
以下是 PropManPropertySource ,它扩展了 PropertySources 。这是调用PropMan的get方法从键/值存储中检索值的地方。
public class PropManPropertySource extends PropertySource<PropMan> {
PropMan propMan;
public PropManPropertySource(String name) {
super(name);
}
public PropManPropertySource(String name, PropMan propMan) {
super(name, propMan);
this.propMan = propMan;
}
@Override
public Object getProperty(String key) {
return propMan.get(key);
}
}
虽然其中任何一个似乎都覆盖了PropertySource,但它似乎也希望获得依赖于PropMan的自动配置的所有属性。例如,尝试检查我们的PropMan以获取 spring.boot.enableautoconfiguration 等值。我们的PropMan使http请求返回每个这样的404。返回值为null,这将使我假设它应该查看下一个PropertySource。理想情况下,它应该看到它不在PropMan中并继续检查PropertySources中的另一个PropertySource:
这是我运行时可执行jar的日志快照:
...
2017-02-18 14:31:49,214 INFO [main] c.h.c.LifecycleService [StandardLoggerFactory.java:49] [localhost]:5653 [dev] [3.5.5] Address[localhost]:5653 is STARTED
2017-02-18 14:31:49,265 INFO [main] c.g.a.s.a.m.PropManImpl [PropManImpl.java:271] get(String key=spring.profiles.active)
2017-02-18 14:31:49,270 INFO [main] c.h.p.InternalPartitionService [StandardLoggerFactory.java:49] [localhost]:5653 [dev] [3.5.5] Initializing cluster partition table first arrangement...
2017-02-18 14:31:49,302 INFO [main] c.g.a.s.a.m.PropManImpl [PropManImpl.java:291] URI: http://localhost:8500/v1/kv/com/myco/spring/profiles/active
2017-02-18 14:31:49,464 ERROR [main] c.g.a.s.a.m.PropManImpl [PropManImpl.java:298] Request to Consul recieved status code 404.
2017-02-18 14:31:49,467 INFO [main] c.g.a.s.c.Application [StartupInfoLogger.java:48] Starting Application on LOCALHOST with PID 8362
2017-02-18 14:31:49,467 INFO [main] c.g.a.s.c.Application [SpringApplication.java:641] The following profiles are active: app
2017-02-18 14:31:49,467 DEBUG [main] o.s.b.SpringApplication [SpringApplication.java:665] Loading source class com.myco.Application
2017-02-18 14:31:49,539 DEBUG [main] o.s.b.c.c.ConfigFileApplicationListener [DeferredLog.java:172] Loaded config file 'jar:file:myapp/build/libs/myapp-0.0.0.jar!/BOOT-INF/classes!/application.properties' (classpath:/application.properties)
2017-02-18 14:31:49,539 DEBUG [main] o.s.b.c.c.ConfigFileApplicationListener [DeferredLog.java:172] Skipped (empty) config file 'jar:file:myapp/build/libs/myapp-0.0.0.jar!/BOOT-INF/classes!/application.properties' (classpath:/application.properties) for profile default
2017-02-18 14:31:49,540 INFO [main] o.s.b.c.e.AnnotationConfigEmbeddedWebApplicationContext [AbstractApplicationContext.java:582] Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@1e9e725a: startup date [Sat Feb 18 14:31:49 EST 2017]; root of context hierarchy
2017-02-18 14:31:49,543 DEBUG [main] o.s.b.c.e.AnnotationConfigEmbeddedWebApplicationContext [AbstractApplicationContext.java:616] Bean factory for org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@1e9e725a: org.springframework.beans.factory.support.DefaultListableBeanFactory@6107227e: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.event.internalEventListenerProcessor,org.springframework.context.event.internalEventListenerFactory,application]; root of factory hierarchy
2017-02-18 14:31:49,703 INFO [main] c.g.a.s.a.m.PropManImpl [PropManImpl.java:271] get(String key=spring.boot.enableautoconfiguration)
2017-02-18 14:31:49,704 INFO [main] c.g.a.s.a.m.PropManImpl [PropManImpl.java:291] URI: http://localhost:8500/v1/kv/com/myco/spring/boot/enableautoconfiguration
2017-02-18 14:31:49,795 ERROR [main] c.g.a.s.a.m.PropManImpl [PropManImpl.java:298] Request to Consul recieved status code 404.
2017-02-18 14:31:49,935 INFO [main] c.g.a.s.a.m.PropManImpl [PropManImpl.java:271] get(String key=spring.messages.basename)
2017-02-18 14:31:49,936 INFO [main] c.g.a.s.a.m.PropManImpl [PropManImpl.java:291] URI: http://localhost:8500/v1/kv/com/myco/spring/messages/basename
2017-02-18 14:31:50,045 ERROR [main] c.g.a.s.a.m.PropManImpl [PropManImpl.java:298] Request to Consul recieved status code 404.
2017-02-18 14:31:50,108 INFO [main] c.g.a.s.a.m.PropManImpl [PropManImpl.java:271] get(String key=server.error.whitelabel.enabled)
2017-02-18 14:31:50,109 INFO [main] c.g.a.s.a.m.PropManImpl [PropManImpl.java:291] URI: http://localhost:8500/v1/kv/com/myco/server/error/whitelabel/enabled
2017-02-18 14:31:50,203 ERROR [main] c.g.a.s.a.m.PropManImpl [PropManImpl.java:298] Request to Consul recieved status code 404.
2017-02-18 14:31:50,203 INFO [main] c.g.a.s.a.m.PropManImpl [PropManImpl.java:271] get(String key=server.error.whitelabel.ENABLED)
2017-02-18 14:31:50,204 INFO [main] c.g.a.s.a.m.PropManImpl [PropManImpl.java:291] URI: http://localhost:8500/v1/kv/com/myco/server/error/whitelabel/ENABLED
2017-02-18 14:31:50,306 ERROR [main] c.g.a.s.a.m.PropManImpl [PropManImpl.java:298] Request to Consul recieved status code 404.
2017-02-18 14:31:50,307 INFO [main] c.g.a.s.a.m.PropManImpl [PropManImpl.java:271] get(String key=server_error_whitelabel_enabled)
2017-02-18 14:31:50,309 INFO [main] c.g.a.s.a.m.PropManImpl [PropManImpl.java:291] URI: http://localhost:8500/v1/kv/com/myco/server_error_whitelabel_enabled
2017-02-18 14:31:50,404 ERROR [main] c.g.a.s.a.m.PropManImpl [PropManImpl.java:298] Request to Consul recieved status code 404.
2017-02-18 14:31:50,405 INFO [main] c.g.a.s.a.m.PropManImpl [PropManImpl.java:271] get(String key=server_error_whitelabel_ENABLED)
2017-02-18 14:31:50,406 INFO [main] c.g.a.s.a.m.PropManImpl [PropManImpl.java:291] URI: http://localhost:8500/v1/kv/com/myco/server_error_whitelabel_ENABLED
2017-02-18 14:31:50,498 ERROR [main] c.g.a.s.a.m.PropManImpl [PropManImpl.java:298] Request to Consul recieved status code 404.
2017-02-18 14:31:50,499 INFO [main] c.g.a.s.a.m.PropManImpl [PropManImpl.java:271] get(String key=serverErrorWhitelabel.enabled)
2017-02-18 14:31:50,500 INFO [main] c.g.a.s.a.m.PropManImpl [PropManImpl.java:291] URI: http://localhost:8500/v1/kv/com/myco/serverErrorWhitelabel/enabled
2017-02-18 14:31:50,612 ERROR [main] c.g.a.s.a.m.PropManImpl [PropManImpl.java:298] Request to Consul recieved status code 404.
2017-02-18 14:31:50,613 INFO [main] c.g.a.s.a.m.PropManImpl [PropManImpl.java:271] get(String key=serverErrorWhitelabel.ENABLED)
2017-02-18 14:31:50,614 INFO [main] c.g.a.s.a.m.PropManImpl [PropManImpl.java:291] URI: http://localhost:8500/v1/kv/com/myco/serverErrorWhitelabel/ENABLED
... this goes on seemingly forever.
是否有人能够使用其他属性来源?如何使用PropMan作为PropertySource?