java - 从子上下文引用在父上下文中创建的 Spring Singletons

标签 java spring dependency-injection

很难想出这个标题!我有一个在 spring 容器中初始化的 bean。它加载类,这些类也使用 Spring 类加载器从文件创建对象。其中一些对象可能依赖于昂贵的对象,我希望这些对象在父对象中初始化。好吧,我无法用文字来解释一个简单的例子:

public class MainLoader {
    public static void main(String[] args) {
        XmlBeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("top-context.xml"));

        ChildLoader childLoader = (ChildLoader)beanFactory.getBean("childLoader");

        childLoader.loadChildAndDoSomething("message1.xml");
        childLoader.loadChildAndDoSomething("message2.xml");        
    }
}

public class ChildLoader {

    public void loadChildAndDoSomething(String childContextfile){       
        XmlBeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource(childContextfile));
        ClassThatDoesStuff classThatDoesStuff = (ClassThatDoesStuff)beanFactory.getBean("classThatDoesStuff");  
        classThatDoesStuff.saySomething();
    }

}

public class ClassThatDoesStuff {
private ReallyExpensiveService reallyExpensiveService;  
private String messageStart;

public void saySomething(){
    System.out.println(messageStart + reallyExpensiveService.getName());
}

    // .. field setters removed for brevity
}

public class ReallyExpensiveService {
public String getName(){
    return "Joe";
}
}

这些在文件中有以下 bean:

top-context.xml:

<bean id="childLoader" class="com.mark.test.ChildLoader" />

message1.xml(message2.xml 类似):

<bean id="classThatDoesStuff" class="com.mark.test.ClassThatDoesStuff">
    <property name="messageStart" value = "Hello! " />  
    <property name ="reallyExpensiveService" ref="theExpensiveserviceReference" />  
</bean>
<bean id="theExpensiveserviceReference" class="com.mark.test.ReallyExpensiveService" />

当这些运行时你得到预期的:

Hello! Joe
Goodbye! Joe

这里唯一的问题是“ReallyExpensiveService”每次都由 Spring 创建和缓存。这是由日志验证的。最好在初始化 MainLoader 时加载“ClassThatDoesStuff”类(假设它是一个接口(interface))可能需要的任何服务。 IE。 (概念上)将 spring 上下文文件更改为:

top-context.xml:

<bean id="childLoader" class="com.mark.test.ChildLoader" />
<bean id="theExpensiveserviceReference" class="com.mark.test.ReallyExpensiveService" />

消息1/2.xml

    <bean id="classThatDoesStuff" class="com.mark.test.ClassThatDoesStuff"
  autoWired="byType">   
        <property name="messageStart" value = "Hello! " />  
    </bean>

我意识到解决这个问题的方法是让 ClassThatDoeStuff 有一个服务 setter ,并设置子容器中的值,子容器本身通过主上下文注入(inject)。但是想象一下,有任意服务,每个 ClassThatDoesStuff 实现者都使用不同的服务。有什么方法可以让它在 Spring 中工作吗?

最佳答案

似乎您所能期望的最好结果就是将每个 ReallyExpensiveService 实例化一次。 (你在那里提到你不确定哪个 ClassThatDoesStuff 可能使用不同的。)我可能会尝试在顶级上下文中定义我所有的 ReallyExpensiveService bean,然后将它们分发给在适当的地方使用它们的类,或者通过您正在使用的 XML 配置文件,或者通过您注入(inject) ClassThatDoesStuff bean 的某种工厂。

您还可以尝试寻找一种方法来推迟启动 ReallyExpensiveService 的昂贵操作,直到您确定它们将被使用。当然这要看“贵”是什么意思。是服务使用了太多内存,如果它们不在使用中您不希望它们存在,还是它们实例化的时间太长?

无论如何,这里的关键是让昂贵的东西尽可能少地 float ,因此您需要在顶层配置它们,以便可以在任何地方传递对单个实例的引用。

关于java - 从子上下文引用在父上下文中创建的 Spring Singletons,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6388746/

相关文章:

java - 从 Object 转换为 ArrayList

java - JVM退出代码10的含义

c# - 使用实现 2 个接口(interface)的 EF DbContext 进行依赖注入(inject)

dependency-injection - 你可以在持久实体中使用依赖注入(inject)吗?

angular - 注入(inject)器与 ViewContainerRef.injector 与 ViewContainerRef.parentInjector

java - 如何从 Mono<Boolean> 类型字段中提取值?

java - 读取请求使服务器停止

java - Mongo 可审核的 ZonedDateTime 字段在 Spring Boot 2 中不起作用

java - 限制需要反序列化的json字段为java对象的字段

java - 设置对象时保留对象的值