Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 从Spring上下文访问Spring测试类对象_Java_Spring_Reflection_Annotations - Fatal编程技术网

Java 从Spring上下文访问Spring测试类对象

Java 从Spring上下文访问Spring测试类对象,java,spring,reflection,annotations,Java,Spring,Reflection,Annotations,奇怪的主题继续问自己:)有没有办法从spring应用程序上下文访问spring测试类?问题详细信息作为注释块隐藏在“SimpleDaoHandler”类中:) 测试等级: @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("/applicationContext-core.xml") public class DbFuntionTests { @TestAnnotation private UserSes

奇怪的主题继续问自己:)有没有办法从spring应用程序上下文访问spring测试类?问题详细信息作为注释块隐藏在“SimpleDaoHandler”类中:)

测试等级:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/applicationContext-core.xml")
public class DbFuntionTests {

    @TestAnnotation
    private UserSessionDao userSessionDao; 

    @Test
    public void testOracleTimestamp() throws Exception {
        userSessionDao.findAll();
    }
}
spring上下文初始化后的处理程序类:

@Component
public class SimpleDaoHandler implements ApplicationContextAware, InitializingBean {
    private ApplicationContext applicationContext;
    private static Logger logger = Logger.getLogger(SimpleDaoHandler.class);

    @Override
    public void afterPropertiesSet() throws Exception {
        //I have the application context now, via method "setApplicationContext"
        // and need to get test class object to get the
        // annotated field "TestAnnotation" because I also need to set this
        // field with my business logic, using reflection.
        // Problem is; test class object is not included in the
        // "applicationContext" as a bean and I don't know how to access my 
        //test class which is already starting the spring context initialization. 
        //I need to get that test class object.
    }

    @Override
    public void setApplicationContext(final ApplicationContext applicationContext)
            throws BeansException {
        this.applicationContext = applicationContext;
    }

有什么线索吗?

也许用您的
@TestAnnotation
创建一些工作会更好?您可以查看Spring
AutowiredNotationBeanPostProcessor
,它扫描带有
@Autowire
注释的字段/方法的bean并对其进行处理。我认为这是您试图实现的目标,bean后处理器是解决此类问题的最干净的解决方案(由Spring本身使用)

请看下面的示例,
MyAnnotationPostProcessor
在应用程序上下文中的每个bean上扫描
MyAnnotation
,并记录适用的字段。(当然,您可以采取一些操作,而不是记录日志;))。请注意,您的批注必须声明
RetentionPolicy.RUNTIME
;否则,它在运行时将不可见

public final class MyAnnotationPostProcessor implements BeanPostProcessor {

    private static final Log LOG = LogFactory.getLog(MyAnnotationPostProcessor.class);

    public Object postProcessBeforeInitialization(Object bean, String beanName)
            throws BeansException {
        final Set<Field> annotatedFields = getAnnotatedFields(bean.getClass());
        for (Field annotatedField : annotatedFields) {
            LOG.info("Post process before initialization " + beanName + "," + annotatedField);
        }
        return bean;
    }

    public Object postProcessAfterInitialization(Object bean, String beanName)
            throws BeansException {
        final Set<Field> annotatedFields = getAnnotatedFields(bean.getClass());
        for (Field annotatedField : annotatedFields) {
            LOG.info("Post process after initialization " + beanName + "," + annotatedField);
        }
        return bean;
    }

    private Set<Field> getAnnotatedFields(final Class<?> clazz) {
        final Set<Field> annotatedFields = new HashSet<Field>();
        for (Field field : clazz.getDeclaredFields()) {
            if(hasMyAnnotation(field)) {
                annotatedFields.add(field);
            }
        }
        return annotatedFields;
    }

    private boolean hasMyAnnotation(final AccessibleObject ao) {
        return AnnotationUtils.getAnnotation(ao, MyAnnotation.class) != null;
    }
}

多亏了Piotrek De,我终于找到了答案。注释处理程序类还必须实现BeanPostProcessor类。通过这种方式,您还可以获得测试应用程序上下文使用的两种方法:

@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    try {
        injectGDao(bean);
    } catch (Exception e) {
        throw new BeanInstantiationException(bean.getClass(), e.getMessage(), e.getCause());
    }
    return bean;
}

@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    try {
        injectGDao(bean);
    } catch (Exception e) {
        throw new BeanInstantiationException(bean.getClass(), e.getMessage(), e.getCause());
    }
    return bean;
}

无论何时测试上下文侦听器到达此方法,您现在都可以到达测试类对象。更详细的答案可以在我前面提到的Piotrek De的答案中找到。

你是对的,有些@Autowired和AutowiredNotationBeanPostProcessor是如何做到这一点的,但我发现代码太复杂,无法满足我的需要(很明显,我很难理解该代码吗?:)。不管怎样,你的回答让我尝试不同类型的后处理器,如果我得到任何结果,我会通知你。感谢您的回复。是的,它看起来很复杂,但这只是因为它实现了一些自动连接逻辑,而不是因为@Autowired annotation lookup;)请查找并更新答案-我已经给出了简单的后处理器处理自定义注释的示例。您的答案更详细,因此我在我的答案之前选择了您的答案:)观众也可以在下面找到我的答案
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    try {
        injectGDao(bean);
    } catch (Exception e) {
        throw new BeanInstantiationException(bean.getClass(), e.getMessage(), e.getCause());
    }
    return bean;
}

@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    try {
        injectGDao(bean);
    } catch (Exception e) {
        throw new BeanInstantiationException(bean.getClass(), e.getMessage(), e.getCause());
    }
    return bean;
}