【问题标题】:Configure Spring to set system properties 'before' a bean is initialised配置 Spring 以在 bean 初始化之前设置系统属性
【发布时间】:2012-12-20 13:26:18
【问题描述】:

在 Spring MVC Web 应用程序中,我在配置文件中配置了一个 bean:

<bean class="com.callback.CallbackService"/>

在服务类中,bean被初始化如下所示:

@Autowired
CallbackService service

上面显示的 CallbackService 通过以下三个调用获取其连接属性(暂时无法更改):

System.getProperty("user");
System.getProperty("password");
System.getProperty("connectionURL");

声明CallbackService实例的服务类可以通过读取属性文件访问上述三个值,如下所示:

@Value("${user}")
protected String userName;

@Value("${password}")
protected String password;

@Value("${connection}")
protected String connectionString;  

我只需要设置 CallbackService 的属性就是设置系统属性(在它们被初始化之后),如下所示:

System.setProperty("user", userName);
System.setProperty("password", password);
System.setProperty("connectionURL", connectionString);

我遇到的问题是初始化对象的顺序。属性正在初始化,但看起来 System.setProperty 调用发生在 Spring 从属性文件中准备好它们之前。

我尝试了几种解决方案,但似乎 CallbackService 对象是在从属性文件中读取值并调用 System.setProperty 之前实例化的。

属性文件最终会被读取,因为如果我从 @Controller 方法之一访问它们,我可以看到这些值。问题在于初始化属性和实例化 CallbackService 实例的点。

经过几个小时的谷歌搜索,我尝试了以下解决方案,但似乎没有一个在 CallbackService 实例的初始化/实例化之前填充系统属性

  1. 实现InitiazingBean 并在 afterPropertiesSet() 方法。
  2. 实现ApplicationListener 并在onApplicationEvent() 方法中设置系统属性。
  3. 为 XML 中的 CallbackService bean 定义设置 lazy-init=true
  4. 按照此处Set System Property With Spring Configuration File 的描述设置系统属性

上面的第 4 点似乎是我想要的,但是当我将以下内容(具有我需要的三个属性)添加到我的上下文文件时,我没有看到任何区别。

<bean id="systemPrereqs"
    class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
    <property name="targetObject" value="#{@systemProperties}" />
    <property name="targetMethod" value="putAll" />
    <property name="arguments">
        <!-- The new Properties -->
        <util:properties>
            <prop key="java.security.auth.login.config">/super/secret/jaas.conf</prop>
        </util:properties>
    </property>
</bean>

如何确保在执行对​​ System.setProperty 的调用之前从属性文件中读取值,然后才应实例化 CallbackService 实例?

谢谢

【问题讨论】:

  • 这里有很多细节但是问题不符合问答格式...问题开头没有明确说明。

标签: java spring jakarta-ee spring-mvc configuration


【解决方案1】:

你可以让CallbackServicedepend on另一个bean初始化系统属性,例如

 class SystemPropertiesInitializer {

      SystemPropertiesInitializer(@Value("${user}") String userName, 
              @Value("${password}") String password, 
              @Value("${connection}" String connectionString) {

          System.setProperty("user", userName);
          System.setProperty("password", password);
          System.setProperty("connectionURL", connectionString);
      }
 }

接下来,

 <bean id="systemPropertiesInitializer" class="com.callback.SystemPropertiesInitializer"/>
 <bean class="com.callback.CallbackService" depends-on="systemPropertiesInitializer"/>

或者,您可以使用@DependsOn 注释:

 @Component
 @DependsOn("systemPropertiesInitializer")
 class CallbackService { 
     // implementation omitted
 }

【讨论】:

  • 谢谢我现在正在尝试这个。如果 SystemPropertiesInitializer 没有无参数构造函数,它将如何被实例化?
  • 你的意思是如果它确实有一个无参数的构造函数(或根本没有构造函数)?只需使用@Value注解分别初始化各个字段,然后可以在init方法上使用@PostConstruct注解,然后调用System.setProperties(...)方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-08-20
  • 2016-12-25
  • 1970-01-01
  • 2012-10-05
  • 1970-01-01
  • 1970-01-01
  • 2021-01-22
相关资源
最近更新 更多