Spring ApplicationContextAware与MockBeans结合使用

时间:2018-11-07 08:58:45

标签: java spring spring-boot mockito applicationcontext

由于一些遗留代码,我需要访问无法自动装配bean的非spring类中的spring bean(spring boot 2,junit 5)。为此,大多数人建议像

那样实现ApplicationContextAware
@Component
public class BeanUtil implements ApplicationContextAware {

private static ApplicationContext context;

@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    context = applicationContext;
}

public static <T> T getBean(Class<T> beanClass) {
    return context.getBean(beanClass);
}

在生产代码中可以正常工作。但是我有一些使用@MockBean批注的测试,导致spring为此创建了一个新的应用程序上下文,这将触发setApplicationContext的{​​{1}}。如果此后的另一个测试没有任何模拟的Bean,则原始应用程序上下文将被重用,因为它已被spring缓存。问题在于,重用应用程序上下文不会触发ApplicationContextAware,因此我无法从setApplicationContext获取任何有效的bean,因为BeanUtil拥有过时的应用程序上下文,请参见Spring的{{1 }}

BeanUtil

更多正式流程:

  1. 不进行任何模拟的测试,创建ApplicationContext1,通知DefaultCacheAwareContextLoaderDelegate
  2. 进行模拟测试,创建ApplicationContext2,通知@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; } }
  3. 不进行任何模拟的测试,将重用spring缓存中的ApplicationContext1,不通知ApplicationContextAware

ApplicationContextAware中是否有任何方式可以通知您,再次使用了缓存的应用程序上下文?

0 个答案:

没有答案