我有一个复杂的企业环境,有多个项目相互依赖。配置由spring处理,包括疯狂的数字导入和不包括。
默认情况下,Spring可以多次构造一个具有相同名称的bean。特别是在多个Spring上下文的情况下。每个上下文都有自己的同一个单例bean的实例。 Singleton在Spring架构师中并不是真正的单身人士。头脑...
不幸的是,在我的情况下,一个bean永远不会被创建多次。
有没有办法强制Spring检查bean是否已经创建了它而不是尝试再次调用它的构造函数?
特别是,bean在内部创建了ehcache的CacheManager并失败,因为无法创建两次具有相同名称的CacheManager。
<bean id="cacheService" class="somepackage.CacheServiceImpl">
<constructor-arg index="0" value="/somepackage/ehcache.xml" />
</bean>
我无法控制CacheServiceImpl代码。我只能改变它周围的配置。
答案 0 :(得分:2)
不同的Spring应用程序上下文彼此不了解。就每个上下文而言,您的对象是单身。但是,听起来你不希望有多个上下文。
你是如何创造背景的?您的应用程序应创建ApplicationContext
的单个实例(可能在main
或附近的某个位置)。任何需要应用程序上下文的内容都应该注入或者ApplicationContextAware
。
您提到了“复杂的企业环境”。在我工作的地方最有效的方法是让一个项目管理Spring。假设您的所有项目都在同一个应用程序中运行(否则Spring无法真正帮助您),可能有一些项目会启动所有项目。对我们来说,这是一个内置于战争并部署到我们服务器的项目。
答案 1 :(得分:1)
我终于明白了。加载上下文两次的原因是在第一次上下文加载期间发生的隐藏错误。下面是一个冗长乏味的解释。
在第一次调用spring方法DefaultTestContext.getApplicationContext()时,应该加载Context。
有一个类DefaultCacheAwareContextLoaderDelegate,它负责实际加载上下文一次并将其缓存以备将来使用。方法代码如下:
@Override
public ApplicationContext loadContext(MergedContextConfiguration mergedContextConfiguration) {
synchronized (this.contextCache) {
ApplicationContext context = this.contextCache.get(mergedContextConfiguration);
if (context == null) {
try {
context = loadContextInternal(mergedContextConfiguration);
if (logger.isDebugEnabled()) {
logger.debug(String.format("Storing ApplicationContext in cache under key [%s]",
mergedContextConfiguration));
}
this.contextCache.put(mergedContextConfiguration, context);
}
catch (Exception ex) {
throw new IllegalStateException("Failed to load ApplicationContext", ex);
}
}
else {
if (logger.isDebugEnabled()) {
logger.debug(String.format("Retrieved ApplicationContext from cache with key [%s]",
mergedContextConfiguration));
}
}
this.contextCache.logStatistics();
return context;
}
}
显然,当在loadContextInternal()调用期间抛出除Exception之外的Throwable时,应用程序上下文不会被放入缓存中。
显然,即使运行单个JUnit测试,也会多次调用getApplicationContext()方法,期望第二次自已缓存后不再需要加载它。
如果在第一次加载期间抛出错误,它将被隐藏,JUnit / Spring继续测试,直到它第二次调用getApplicationContext()。这就是它捕获异常和崩溃的地方,因为ehcache不希望CacheManager多次初始化。