3

我使用 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 实例?

4

6 回答 6

2

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

查看您的示例,我建议您允许您的类 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"
    }
}

您的 main() 将引导;上下文并将其传递给A

public class MyMain {

    public static void main(String[] args) {

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

        a.execute();        
    }
}

作为一个额外的好设计,将您创建的上下文封装在工厂类中

public class SpringContextFactory {

    public static ApplicationContext getInstance() {

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

        return new ClassPathXmlApplicationContext(contextXml);
    }
}

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

于 2012-06-12T16:21:57.667 回答
1

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

例如:

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

然后,只要您需要它,只需说:

Utilities.initApplicationContext();
于 2012-06-12T18:13:33.527 回答
1

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

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

只要类A由spring初始化,这将起作用。从给出的代码来看,情况就是这样。

于 2012-06-12T18:33:19.887 回答
0

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

据我所知,您的代码ClassA应该尝试将(或)@Autowired的实例添加到其成员。您想要这样做是因为它已经是 Spring 定义的 bean!根据为您的bean 提供给 Spring 的范围,您应该直接注入 bean(对于范围):ClassCObjectCClassAClassCsingleton

@Autowired
private ClassC objC;

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

@Autowired
private ClassCFactory objCFactory;

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

于 2012-06-12T16:18:35.957 回答
0

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

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

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

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

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

/* 应用上下文提供者类 */

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


}

弹簧 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 上下文 = ApplicationContextProvider.getApplicationContext();
dl = (SingleDataLoader) context.getBean("singledataloaderdao");

于 2013-10-18T08:49:29.660 回答
-1

尝试使用contextapplication context在 main 方法中放入您的 PROGRAM CONTEXT,在其他方法中您必须获取,在您的情况下使用某个 Context 类中的静态方法,这不是一个好方法,但您不能更改 API

于 2012-06-12T16:11:14.867 回答