Java 使用运行时参数创建单例bean
我是Spring框架的新手,无法找到实现以下目标的方法: 我使用的类的属性都是私有的,没有设置器。使用该类对象的预期方法是使用构造函数设置一次属性——我将其称为首选项。我还有几个类,每个类都具有与属性相同的首选项实例。首选项旨在包含某些属性,其中一些属性只能在运行时解析,例如由用户提供 在我的.xml文件中,我将写一些如下内容:Java 使用运行时参数创建单例bean,java,spring,dependency-injection,Java,Spring,Dependency Injection,我是Spring框架的新手,无法找到实现以下目标的方法: 我使用的类的属性都是私有的,没有设置器。使用该类对象的预期方法是使用构造函数设置一次属性——我将其称为首选项。我还有几个类,每个类都具有与属性相同的首选项实例。首选项旨在包含某些属性,其中一些属性只能在运行时解析,例如由用户提供 在我的.xml文件中,我将写一些如下内容: <bean id="preferenes" class="Preferences" scope="singleton"> <construct
<bean id="preferenes" class="Preferences" scope="singleton">
<constructor-arg index="0" value="defaultAttrOne" />
<constructor-arg index="1" value="defaultAttrTwo" />
<constructor-arg index="2" value="defaultAttrThree" />
</bean>
<bean id="someOtherBean" class="SomeOtherClass" scope="singleton">
<constructor-arg index="0" ref="preferences" />
</bean>
也就是说,我可以提供默认值,并在运行时用自定义值替换其中的一些值。由于我无法修改现有首选项实例的属性,因此我必须构造一个新对象,并以某种方式使其他类的实例指向该新对象。这是否可以通过bean机制实现
相反,在实例化任何bean之前,我会将所需的运行时构造函数参数传递给preferences bean。在第一次调用ApplicationContext的构造函数之前,这些参数是已知的。我知道getBean方法有一种风格,它将varargs作为初始化参数,尽管它只适用于原型bean。在这种情况下,我想初始化Preferenes一次,并让所有助手类都引用该实例
谢谢您的提示。这几乎就是Spring默认为您做的事情,因此您无需做任何特殊的事情:如果您创建名为preferences的单例bean引用,您将能够像您所期望的那样将其注入任何其他bean 对于具有默认值的属性,有几种方法可以实现这一点: 常规XML配置 如果需要,可以保留纯粹基于XML的配置,并使用默认值配置PropertyPlaceHolderConfigure。比如:
<bean class="org.s.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="prefrences.properties"/>
</bean>
<bean id="preferenes" class="Preferences" scope="singleton">
<constructor-arg index="0" value="$[preferences.one:12]" />
<constructor-arg index="1" value="$[preferences.two:AUTO]" />
<constructor-arg index="2" value="$[preferences.three:false]" />
</bean>
菜豆
由于您已经在使用XML,您可以使用一个创建Preferences实例的
<bean id="preferences" class="org.myproject.PreferencesFactoryBean"/>
使用属性解析。您介意再详细说明一下吗?使用属性占位符${somePropertyName}并配置PropertyPlaceHolderConfigure。然后在运行时添加属性,然后再刷新ApplicationContext。感谢您的帮助,尽管这还不是我的目标。我想传递给Preferences bean的参数不在属性文件中,可能是我在问题中误用了“属性”一词。相反,它们是在代码级别提供的,可以是一些自定义类的实例。按照注释约定,我将有一个@Value${myClass}注释的myClass myClass字段,由preferences bean使用,如上面的示例所示。在config类之外,我想先设置myClass字段,然后调用getBeanReferences.class。你不能这样做。这就像你想管理一个对象状态,然后让Spring来处理它。这就是为什么这样的东西通常是通过声明性的方式提供的,比如属性文件,因为容器管理它。也就是说,我上面提供给你的任何东西都没有问题。您可以创建FactoryBean并在getObject中拥有所需的所有逻辑。对于Java配置第三个示例,您可以调用首选项中需要的任何内容,并删除@Value字段
<bean id="preferences" class="org.myproject.PreferencesFactoryBean"/>
@Configuration
@PropertySource("classpath:preferences.properties")
public class AppConfig {
@Value("${preferences.one}")
private int preferenceOne = 12;
@Value("${preferences.two}")
private MyEnum preferenceTwo = MyEnum.AUTO;
@Value("${preferences.three}")
private boolean preferenceThree;
@Bean
public static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
@Bean
public Preferences preferences() {
return new Preferences(preferenceOne, preferenceTwo, preferenceThree);
}
}