Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java PropertyPlaceHolderConfigurer的初始化顺序(Spring 3)_Java_Spring_Properties - Fatal编程技术网

Java PropertyPlaceHolderConfigurer的初始化顺序(Spring 3)

Java PropertyPlaceHolderConfigurer的初始化顺序(Spring 3),java,spring,properties,Java,Spring,Properties,在基于Spring的web应用程序中,我需要将加密值存储在属性文件中。为此,我对Spring的“PropertyPlaceHolderConfigure”类进行了子类化,并重写了它的“convertProperties”方法,以便在从文件加载属性后,它对加密的属性进行解密。这很有效 现在,这个PPC依赖于Spring上下文中处理加密/解密任务的另一个bean。目前,这个bean必须在Spring上下文XML文件中配置“硬编码”的值。我希望通过PPC从属性文件中提取这些值,但这样做会创建一个循环依

在基于Spring的web应用程序中,我需要将加密值存储在属性文件中。为此,我对Spring的“PropertyPlaceHolderConfigure”类进行了子类化,并重写了它的“convertProperties”方法,以便在从文件加载属性后,它对加密的属性进行解密。这很有效

现在,这个PPC依赖于Spring上下文中处理加密/解密任务的另一个bean。目前,这个bean必须在Spring上下文XML文件中配置“硬编码”的值。我希望通过PPC从属性文件中提取这些值,但这样做会创建一个循环依赖关系(解密程序无法从PPC接收需要解密程序执行其工作的信息…)

所以。。。我想我要做的是创建两个属性文件:一个用于加密内容,另一个用于明文内容。然后,我将创建两个PPC—一个是普通PPC,另一个是我的子类设计,用于处理加密内容。这样,我就可以将解密程序的配置选项放入明文属性文件中

不幸的是,我似乎对Spring初始化项目的顺序有问题。以下是我的XML设置示例:

<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;
   }
}