要网站开发费用短信,秦皇岛网站建设服务,如何做能切换语言的网站,吉安哪家做网站的公司好您在使用AspectJ Transactionals和Spring吗#xff1f; 您是否有多个SessionFactory#xff0c;也许一个用于嵌入式数据库进行单元测试#xff0c;一个用于实际数据库进行集成测试#xff1f; 您是否遇到这些例外之一#xff1f; org.springframework.transaction.Cannot… 您在使用AspectJ Transactionals和Spring吗 您是否有多个SessionFactory也许一个用于嵌入式数据库进行单元测试一个用于实际数据库进行集成测试 您是否遇到这些例外之一 org.springframework.transaction.CannotCreateTransactionException无法打开Hibernate Session进行事务处理。 嵌套的异常是org.hibernate.service.UnknownServiceException请求了未知的服务 要么 net.sf.ehcache.Cache.isKeyInCacheCache.java:3068的org.hibernate.cache.ehcache.internal.regions.EhcacheDataRegion.containsEhcacheDataRegion.java:223上的java.lang.NullPointerException 然后您遇到了一个问题其中多个缓存的应用程序上下文相互踩在一起。 这篇博客文章将描述一些解决我们遇到的问题的策略。 背景 Spring的Text Context框架默认尝试通过缓存容器来最小化spring容器必须启动的次数。 如果您正在运行全部使用相同配置的多个测试则只需为所有测试创建一次容器而无需在每次测试之前创建容器。 如果您要进行1000次测试并且容器需要10到15秒的启动时间那么构建/测试时间就会大为不同。 仅当每个人您和您使用的所有库都避免使用静态字段全局状态时这才有效不幸的是在某些情况下这是很难/不可能避免的即使spring违反了此规定 导致我们出现问题的几个地方 Spring AspectJ 事务支持 EhCache缓存管理器 方面是设计上的单例。 Spring使用它来放置对BeanFactory和PlatformTransactionManager的引用。 如果您有多个带有各自“自己的” AnnotationTransactionAspect的容器则它们实际上共享AnnotationTransactionAspect而最后启动的容器是“赢家”从而导致各种意外的难以调试的问题。 Ehcache在这里也很痛苦。 ehcache库维护它在VM中创建的所有缓存管理器的静态列表。 因此如果要使用多个容器它们将共享对同一缓存的引用。 Spring Test提供了一种机制来指示该测试已“污染”了容器并需要创建它。 这意味着在完成测试类后会破坏容器。 很好但是如果您的容器具有其他容器共享的对象则销毁该共享对象会破坏其他容器。 解决方案 最简单的解决方案是基本上完全禁用应用程序上下文缓存。 只需在每个测试上放置DirtiesContext即可完成此操作或者最好您可能应该使用超级类“抽象测试夹具”来组织您的测试在这种情况下只需在基类上添加DirtiesContext。 不幸的是您还失去了所有缓存优势并且构建时间将增加。 弹簧容器没有“清理自身”的通用机制因为跨容器共享状态肯定是一种反模式。 他们自己这样做AnnotationTransactionAspectEhCacheManagerFactoryBean.setSharedtrue等这表明他们可能应该添加一些支持。 如果要继续缓存则第1步是确保您的代码中不使用任何“静态字段”单例。 还要确保将要写入的所有外部资源分开以便多个容器可以共存于同一JVM中。 为了解决AspectJ问题我发现的最佳解决方案是创建一个TestExecutionListener以在测试执行之前“重置” AnnotationTransactionAspect以指向正确的bean工厂和PTM。 这种侦听器的代码在本要点中 。 然后要使用侦听器请将TestListeners放在基类测试夹具上以便所有测试都使用新的侦听器运行。 请注意使用TestListeners批注时必须指定所有执行侦听器包括现有的Spring侦听器。 要点有一个例子。 Ehcache的解决方法是不允许在容器之间共享CacheManager实例。 为此您必须确保所有缓存管理器都有唯一的名称。 实际上这很容易配置。 org.springframework.context.annotation.Configuration
public class CacheBeans {private static final AtomicInteger cacheCounter new AtomicInteger(0);Beanpublic EhCacheManagerFactoryBean ecmfb() {EhCacheManagerFactoryBean ecmfb new EhCacheManagerFactoryBean();// cannot share the cache managersecmfb.setShared(false);// if you are using ehcache.xml on the classpath then theres nothing more to do than just make it // a unique name. If you are using a different config file then use ecmfb.setConfigLocation()ecmfb.setCacheManagerName(ehCache- cacheCounter.incrementAndGet());return ecmfb;}// more Bean defs
}相关问题 以下是一些涉及此问题的Spring jira问题的链接 https://jira.spring.io/browse/SPR-6121 https://jira.spring.io/browse/SPR-6353 翻译自: https://www.javacodegeeks.com/2014/04/spring-test-context-caching-aspectj-transactional-ehcache-pain.html