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