Java PropertyPlaceHolderConfigurer的初始化顺序(Spring 3)
在基于Spring的web应用程序中,我需要将加密值存储在属性文件中。为此,我对Spring的“PropertyPlaceHolderConfigure”类进行了子类化,并重写了它的“convertProperties”方法,以便在从文件加载属性后,它对加密的属性进行解密。这很有效 现在,这个PPC依赖于Spring上下文中处理加密/解密任务的另一个bean。目前,这个bean必须在Spring上下文XML文件中配置“硬编码”的值。我希望通过PPC从属性文件中提取这些值,但这样做会创建一个循环依赖关系(解密程序无法从PPC接收需要解密程序执行其工作的信息…) 所以。。。我想我要做的是创建两个属性文件:一个用于加密内容,另一个用于明文内容。然后,我将创建两个PPC—一个是普通PPC,另一个是我的子类设计,用于处理加密内容。这样,我就可以将解密程序的配置选项放入明文属性文件中 不幸的是,我似乎对Spring初始化项目的顺序有问题。以下是我的XML设置示例:Java PropertyPlaceHolderConfigurer的初始化顺序(Spring 3),java,spring,properties,Java,Spring,Properties,在基于Spring的web应用程序中,我需要将加密值存储在属性文件中。为此,我对Spring的“PropertyPlaceHolderConfigure”类进行了子类化,并重写了它的“convertProperties”方法,以便在从文件加载属性后,它对加密的属性进行解密。这很有效 现在,这个PPC依赖于Spring上下文中处理加密/解密任务的另一个bean。目前,这个bean必须在Spring上下文XML文件中配置“硬编码”的值。我希望通过PPC从属性文件中提取这些值,但这样做会创建一个循环依
<bean id="clearTextPlaceholder" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="ignoreUnresolvablePlaceholders" value="true" />
<property name="location" value="clear.properties" />
</bean>
<bean id="encryptedPlaceholder" class="com.mycompany.EncryptedPlaceholderConfigurer">
<property name="ignoreUnresolvablePlaceholders" value="true" />
<property name="location" value="encrypted.properties" />
<property name="encryption" ref="encrypter" />
</bean>
<bean id="encrypter" class="com.mycompany.Encrypter">
<property name="someOption" value="${plain-text-property}" />
</bean>
所以在本例中,我希望Spring首先初始化“clearTextPlaceholder”bean。然后,使用它读入的属性初始化“encrypter”bean。最后,使用它初始化“encryptedPlaceholder”bean,以供上下文中的所有其他项使用
然而,真正发生的事情是,在启动时,“encrypter”bean会被传递一个文本“${plain text property}”字符串,然后,两个PPC都会初始化(或者尝试初始化,直到由于配置不正确的encrypter bean而失败)
我尝试将“dependens”属性添加到相关bean以强制执行初始化顺序,但没有效果。似乎Spring希望一次创建所有已定义的PPC,因为其中一个依赖于另一个bean,这意味着它们都必须等待另一个bean初始化
这有意义吗?我能在这里做些什么(除了使用上下文感知的东西)来实现这一点,还是这只是Spring的一个限制?当我这么做的时候,有没有更好的方法来解决这个问题,而我却没有看到
谢谢
道格我再现了你的情况——是的,它完全按照你描述的那样工作。您的两个PropertyPlaceHolderConfiguration都是BeanPostProcessor。在启动期间,Spring创建所有BeanPostProcessor bean。然后它调用它们。您可以通过设置
order
属性来更改调用顺序。然而,它总是在调用任何处理器之前完成所有处理器的创建,甚至是最低优先级的处理器
通过将加密机
bean的引用添加到encryptedPlaceHolder
中,您将加密机
移到了这个早期阶段encrypter
是在BeanPostProcessor创建阶段创建的,该阶段发生在调用任何处理器之前,也就是说,在解析任何属性之前
就我所见,您不能让PropertyPlaceHolderConfigure处理作为另一个PropertyPlaceHolderConfigure的依赖项的bean的属性
当我这么做的时候,有没有更好的方法来解决这个问题,而我却没有看到
[更新]
一种解决方案是使加密机足够智能,可以直接读取属性文件。一种更“依赖注入友好”的方法是创建一个定制的工厂bean。有关参考信息,请参见
即使您必须创建一个新的专用工厂bean,也不需要对现有的encrypter类进行任何更改 好吧,考虑到结果,我想一定是这样的。我只是希望我错了!我会像你说的那样,使“encrypter”bean足够智能,可以处理属性,只是它目前是一个哑加密/解密管道,用于许多其他事情,我不想对它进行太多专门化。虽然。。。如果我找不到更好的方法,我最终可能会这样做。
<bean id="encrypter" factory-bean="encrypterFactory" factory-method="createInstance">
</bean>
<bean id="encrypterFactory" class="com.mycompany.EncrypterFactory" init-method="init">
<property name="location" value="clear.properties"/>
</bean>
public class EncrypterFactory
{
Properties properties;
File file;
public void setLocation(String fileName)
{
this.file = new File(fileName);
}
public void init() throws IOException
{
properties = new Properties();
properties.load(new FileReader(file));
}
public Encrypter createInstance()
{
Encrypter encrypter = new Encrypter();
encrypter.setSomeOption(properties.getProperty("plain-text-property"));
return encrypter;
}
}