何时使用Spring Container的多个实例?

时间:2012-06-12 16:04:29

标签: java spring

我使用ApplicationContext作为Spring容器。

但是,由于我不想更改我的API,我觉得需要使用容器的多个实例,如下所示 -

public static void main(String[] args)
 { 
    ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");

    ...
    objA = context.getBean(...);
    objB = context.getBean(...);
 }

// code for Class A

 public void execute() // <-- cannot change this signature 
 {
     ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
     objC = context.getBean(...); // earlier, this was objC = new C();
     objC.method1("...");
 }

所以我最终使用了两个不同的ApplicationContext实例。什么时候适当,什么时候不适合有多个ApplicationContext实例?

6 个答案:

答案 0 :(得分:2)

对于大多数应用程序,不需要多个ApplicationContexts。主要限制是您不能跨容器共享bean实例。从技术上讲,没有理由你不能将它们分成两个容器,但我确信你会想要分享一些常见的bean,比如dataSources和公共业务层等。

查看您的示例我建议您允许A类接受SpringApplication上下文作为构造函数(或者您可以使用setter方法)

public class A {

    private ApplicationContext ctx;

    public A(ApplicationContext applicationContext) {   
        ctx = applicationContext;
    }

    public void execute() {
        // do stuff with beans retrieved from "ctx"
    }
}

你的主()会自助;上下文并将其传递给A

的实例
public class MyMain {

    public static void main(String[] args) {

        A a = new A(SpringContextFactory.getInstance());

        a.execute();        
    }
}

作为一个好的设计的额外部分,将您的上下文创建封装在Factory类

public class SpringContextFactory {

    public static ApplicationContext getInstance() {

        String[] contextXml = new String[]{ "resources/spring-context.xml",
                                            "resources/spring-db.xml" };

        return new ClassPathXmlApplicationContext(contextXml);
    }
}

我发现这个设置适用于我的单元测试

答案 1 :(得分:1)

对于我的测试,我创建了一个实用程序类,只使用了一个静态实例并创建了一个单例。

例如:

 public class Utilities {
private static ApplicationContext _applicationContext = null; 
private static void initApplicationContext() {
        if (_applicationContext == null) {
            _applicationContext = 
new ClassPathXmlApplicationContext("PersistenceHelper-context.xml");
        }
    }
}

然后,只要你需要它,就说:

Utilities.initApplicationContext();

答案 2 :(得分:1)

如果您可以控制类,请尝试实现ApplicationContextAware:  http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/context/ApplicationContextAware.html

这会将applicationContext注入到类中,让您自由地获得所需的任何类。

只要类A被spring初始化,这就行了。从给出的代码来看就是这种情况。

答案 3 :(得分:0)

在您当前的代码中,您没有正确使用Spring。我们的想法是在Spring中连接您的依赖项,然后使用一个ApplicationContext来加载您的起始bean(可能来自您的main()方法)。为了获得不同的bean,在多个地方多次加载相同的上下文并不理想。

据我所知,ClassA的代码应该尝试@Autowired ClassC(或ObjectC}的成员加入其成员。你想这样做是因为ClassA已经是一个Spring定义的bean了!根据为ClassC bean提供给Spring的范围,您应该直接注入bean(对于singleton范围):

@Autowired
private ClassC objC;

或者你应该注入一个工厂来创建bean的实例(对于prototype范围):

@Autowired
private ClassCFactory objCFactory;

如果您进行此更改,则无需多次加载ApplicationContext

答案 4 :(得分:0)

没有必要拥有多个应用程序上下文。在许多情况下,我们需要一个共享的应用程序上下文。

为避免在应用程序中创建多个应用程序上下文,请执行以下操作。

当创建applicationcontextprovider bean时,spring框架会将ApplicationContext注入setApplicationContext。

现在我们有一个静态实用程序方法getApplicationContext,它将在需要时返回应用程序上下文。

无论何时需要应用程序上下文,您只需说:ApplicationContextProvider.getApplicationContext(); ,它将返回共享的应用程序上下文。

/ * Application Context Provider类* /

public class ApplicationContextProvider implements ApplicationContextAware {

    private static Logger logger = Logger.getLogger(ApplicationContextProvider.class);

    private static ApplicationContext ctx;

    @Override
    public void setApplicationContext(ApplicationContext arg0)
            throws BeansException {
        if (arg0 != null) {
            ctx=arg0;
        }
    }

    public synchronized static ApplicationContext getApplicationContext(){
        if (ctx==null) {
            logger.info("Getting the context again as it is null");
            ctx = new ClassPathXmlApplicationContext("Spring-All-Module.xml");
        }
        return ctx;
    }


}

Spring Xml:

<bean id="applicationContextProvider" class="dell.harmony.service.ApplicationContextProvider"></bean> 

从您的主程序类:

try {
            logger.info("Spring Application Context !!");
            ApplicationContext context = new ClassPathXmlApplicationContext(
                    "/Spring-All-Module.xml");
            logger.info("Spring Application Context - End !!");
        } catch (Exception e) {
                    logger.error("Exception in getting the Spring Application Context !!");
                     /* log the exception */
        }

每当您需要上下文时,您只需说: //获取应用程序上下文

ApplicationContext context = ApplicationContextProvider.getApplicationContext();
dl =(SingleDataLoader)context.getBean(“singledataloaderdao”);

答案 5 :(得分:-1)

尝试在main方法中使用context和只放置application context到你的程序上下文中,在你必须得到的其他方法中,在你的情况下使用来自某个Context类的静态方法,它是不是很好,但你不能改变API