org.test4j.module.spring.utility.SpringModuleHelper Maven / Gradle / Ivy
package org.test4j.module.spring.utility;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import org.springframework.aop.framework.MockCglib2AopProxy;
import org.springframework.beans.factory.BeanFactory;
import org.test4j.module.Test4JException;
import org.test4j.module.core.TestContext;
import org.test4j.module.core.utility.MessageHelper;
import org.test4j.module.core.utility.ModulesManager;
import org.test4j.module.spring.SpringModule;
import org.test4j.module.spring.SpringTestedContext;
import org.test4j.module.spring.annotations.SpringContext;
import org.test4j.module.spring.strategy.ApplicationContextFactory;
import org.test4j.module.spring.strategy.Test4JBeanFactory;
import org.test4j.module.spring.strategy.Test4JSpringContext;
import org.test4j.module.spring.strategy.injector.SpringBeanInjector;
import org.test4j.tools.commons.AnnotationHelper;
import org.test4j.tools.commons.ClazzHelper;
import org.test4j.tools.commons.ConfigHelper;
@SuppressWarnings("rawtypes")
public class SpringModuleHelper {
/**
* 获得当前测试类spring容器中名称为beanname的spring bean
*
* @param beanName
* @return
*/
public static Object getBeanByName(String beanname) {
BeanFactory factory = SpringTestedContext.getSpringBeanFactory();
if (factory == null) {
throw new RuntimeException("can't find SpringApplicationContext for tested class:"
+ TestContext.currTestedClazzName());
} else {
Object bean = factory.getBean(beanname);
return bean;
}
}
/**
* 往测试对象中注入spring bean
* 支持注解
* o @SpringBeanByName
* o @SpringBeanByType
* o @Autowired
* o @Resource
*
* @param injected
*/
public static void setSpringBean(Object injected) {
Test4JBeanFactory beanFactory = SpringTestedContext.getSpringBeanFactory();
if (beanFactory != null) {
SpringBeanInjector.injectSpringBeans(beanFactory, injected);
}
}
/**
* 强制重新加载spring 容器
* Forces the reloading of the application context the next time that it is
* requested. If classes are given only contexts that are linked to those
* classes will be reset. If no classes are given, all cached contexts will
* be reset.
*
* @param classes The classes for which to reset the contexts
*/
public static void invalidateApplicationContext() {
boolean springModuleEnabled = ModulesManager.isModuleEnabled(SpringModule.class);
if (springModuleEnabled) {
SpringModule module = ModulesManager.getModuleInstance(SpringModule.class);
module.invalidateApplicationContext();
}
}
private static final Map SHARED_SPRING_CONTEXT = new HashMap();
/**
* 初始化当前测试类用到的spring application context对象
*
* @param testedObject
* @param contextFactory
* @return does initial spring context successfully
*/
public static Test4JSpringContext initSpringContext(Class testClazz, ApplicationContextFactory contextFactory) {
Test4JSpringContext springContext = SpringTestedContext.getSpringContext();
if (springContext != null) {
return springContext;
}
SpringContext annotation = AnnotationHelper.getClassLevelAnnotation(SpringContext.class, testClazz);
Class declaredAnnotationClazz = AnnotationHelper.getClassWithAnnotation(SpringContext.class, testClazz);
if (annotation == null) {
return null;
}
boolean share = annotation.share();
Test4JSpringContext context = null;
if (share) {
context = SHARED_SPRING_CONTEXT.get(declaredAnnotationClazz);
}
if (context == null) {
context = newSpringContext(testClazz, contextFactory, annotation);
}
if (share) {
SHARED_SPRING_CONTEXT.put(declaredAnnotationClazz, context);
}
SpringTestedContext.setSpringContext(springContext);
return context;
}
/**
* 创建新的spring容器
*
* @param testClazz
* @param contextFactory
* @param locations
* @param ignoreNoSuchBean
* @return
*/
private static Test4JSpringContext newSpringContext(Class testClazz, ApplicationContextFactory contextFactory,
SpringContext annotation) {
long startTime = System.currentTimeMillis();
String[] locations = annotation.value();
boolean allowLazy = annotation.allowLazy();
Test4JSpringContext springContext = contextFactory.createApplicationContext(Arrays.asList(locations), false,
allowLazy);
springContext.setShared(annotation.share());
springContext.refresh();
long duration = System.currentTimeMillis() - startTime;
MessageHelper.warn(String.format("take %d ms to init spring context for test obejct[%s]", duration,
testClazz.getName()));
return springContext;
}
/**
* 释放测试类的spring容器
*
* @param springContext
* AbstractApplicationContext实例,这里定义为Object是方便其它模块脱离spring依赖
*/
public static void closeSpringContext(Object springContext) {
if (springContext == null) {
return;
}
if (!(springContext instanceof Test4JSpringContext)) {
String error = String.format("there must be something error, the type[%s] object isn't a spring context.",
springContext.getClass().getName());
throw new RuntimeException(error);
}
Test4JSpringContext context = (Test4JSpringContext) springContext;
if (context.isShared() == false) {
context.destroy();
MessageHelper.warn("close spring context for class:" + TestContext.currTestedClazzName());
}
}
/**
* 返回spring代理的目标对象
*
* @param target
* @return
*/
public static Object getAdvisedObject(Object target) {
if (target instanceof org.springframework.aop.framework.Advised) {
try {
return ((org.springframework.aop.framework.Advised) target).getTargetSource().getTarget();
} catch (Exception e) {
throw new Test4JException(e);
}
} else {
return target;
}
}
/**
* 清空spring AOP容器的Dump容器,防止多次启动spring容器导致的Cglib AOP内存泄漏
*/
public static void resetDumpReference() {
boolean isAvailable = ClazzHelper.isClassAvailable("org.aspectj.weaver.Dump");
if (isAvailable == false) {
return;
}
org.aspectj.weaver.Dump.reset();
}
static boolean USE_ENHANCER_CACHED = ConfigHelper.getBoolean("spring.enhancer.cache.used", true);
/**
* 全局性替换Cglib2AopProxy类的createEnhancer方法
* 将net.sf.cglib.proxy.Enhancer的useCache置为false
* 防止多次启动spring容器导致的Cglib AOP内存泄漏
*/
public static void mockCglibAopProxy() {
if (USE_ENHANCER_CACHED) {
return;
}
boolean isAvailable = ClazzHelper.isClassAvailable("org.springframework.aop.framework.Cglib2AopProxy");
if (!isAvailable) {
return;
}
new MockCglib2AopProxy();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy