我希望用我自己的实现替换Spring使用的Environment bean.这是不好的做法,如果没有,我怎么能干净利落地做到这一点?目前我已经创建了一个实现Environment接口并使用现有Environment bean的bean,但这意味着需要Environment bean的所有配置代码现在必须使用我的自定义Environment bean.我认为用我自己的方法替换Springs Environment bean会更干净,然后没有需要改变的配置.目前我能想到的唯一方法是创建我自己的ApplicationContext,从而将环境设置为我自己的环境,或者创建一些ApplicationContextAware并在那里设置环境.这两件事对我来说似乎都有些笨拙.
约束:
>我使用的是最新版本的Spring3.
>我使用的是基于Java的配置;不是XML
谢谢.
编辑:背景
我想我应该解释为什么我想这样做,以防我的想法有缺陷.我避免这种情况是为了避免非建设性的“你为什么要那样做?”响应.
Spring Environment bean在查找属性值时使用一组属性源.典型的堆栈看起来像这样(但不限于):
> JNDI
>系统属性(通过-Dmyprop = foo设置)
>环境变量
> ……
出于安全原因,有必要加密其中一些属性(例如数据库密码).解决方案是使用Jasypt进行属性加密.但是,Spring / Jasypt只提供了一种将新属性源插入环境的方法.所以:
>具有潜在加密值的属性文件
> JNDI
>系统属性(通过-Dmyprop = foo设置)
>环境变量
> ……
但是,这并不理想,因为这意味着属性只能存储在单个文件中以供操作组维护,或者属性将分布在属性文件,环境变量等中.此外,我觉得属性有无论其财产来源如何,都有可能被加密.
所以这让我想到,无论我在哪里尝试从环境中访问它们,我都需要解密代码中的属性,或者我需要创建自己的环境bean来为我做这件事.
我很乐意听取建设性意见和备选方案.
public class EnvironmentbeanfactoryPostProcessor implements beanfactoryPostProcessor {
private static final String CONfigURATION_PROPERTY_PBE_ALGORITHM = "PBE_ALGORITHM";
private static final String CONfigURATION_PROPERTY_PBE_PASSWORD = "PBE_PASSWORD";
@Override
public void postProcessbeanfactory(ConfigurableListablebeanfactory beanfactory) throws BeansException {
StandardEnvironment environment = (StandardEnvironment) beanfactory.getBean("environment");
if (environment != null) {
StringEncryptor encryptor = this.getEncryptor(environment);
MutablePropertySources mutablePropertySources = environment.getPropertySources();
for (PropertySource> propertySource : mutablePropertySources) {
mutablePropertySources.replace(
propertySource.getName(),new EncryptablePropertySourcePropertySource(propertySource.getName(),propertySource,encryptor));
}
}
}
private StringEncryptor getEncryptor(Environment environment) {
StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
String algorithm = environment.getProperty(CONfigURATION_PROPERTY_PBE_ALGORITHM);
if (algorithm != null) {
encryptor.setAlgorithm(algorithm);
}
String password = environment.getProperty(CONfigURATION_PROPERTY_PBE_PASSWORD);
if (password != null) {
encryptor.setPassword(password);
}
return encryptor;
}
private class EncryptablePropertySourcePropertySource extends PropertySource.source.getProperty(name);
if (value != null && value instanceof String) {
value = this.decode((String) value);
}
return value;
}
private String decode(String encodedValue) {
if (!PropertyValueEncryptionUtils.isEncryptedValue(encodedValue)) {
return encodedValue;
}
if (this.stringEncryptor != null) {
return PropertyValueEncryptionUtils.decrypt(encodedValue,this.stringEncryptor);
}
if (this.textEncryptor != null) {
return PropertyValueEncryptionUtils.decrypt(encodedValue,this.textEncryptor);
}
throw new EncryptionoperationNotPossibleException(
"Neither a string encryptor nor a text encryptor exist "
+ "for this instance of EncryptableProperties. This is usually "
+ "caused by the instance having been serialized and then "
+ "de-serialized in a different classloader or virtual machine,"
+ "which is an unsupported behavIoUr (as encryptors cannot be "
+ "serialized themselves)");
}
}
}
However,the Spring/Jasypt only provide a means of inserting a new property source into the environment.
实际上,这是你错了,你也可以替换PropertySources.请参阅javadoc的javadoc.这也是Spring在内部使用,首先添加一些虚拟PropertySources并在以后替换它们.
你可以做的是创建一个PropertySource,它委托给另一个PropertySource并动态解密该值.这样你可以用一个包裹原始的PropertySources替换所有的PropertySources.
MutablePropertySources mps = env.getgetPropertySources();
for (PropertySource ps : env.getgetPropertySources()) {
EncryptablePropertySource eps = new EncryptablePropertySource(ps.getName(),ps,encryptor);
mps.replace(ps.getName(),eps);
}
您可以使用EncryptablePropertiesPropertySource
作为示例,您基本上需要做的是用PropertySource替换Properties.
如果修复SPR-8928将更容易,因为只允许注册EncryptedPropertySourcesPlaceholderConfigurer并且所有属性都将被转换,您不需要这些黑客.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。