java - 如何获取类型为 T 的字段的类?

标签 java spring generics spring-mvc

我为一些 Spring MVC Controller 编写 JUnit 测试。 JUnit 测试的初始化对于我所有的 Controller 测试都是通用的,因此我想创建一个抽象类来执行此初始化。

因此,我创建了以下代码:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath*:spring/applicationContext-test.xml", "classpath*:spring/spring-mvc-test.xml" })
@Transactional
public abstract class AbstractSpringMVCControllerTest<T> {

    @Autowired
    protected ApplicationContext applicationContext;

    protected MockHttpServletRequest request;

    protected MockHttpServletResponse response;

    protected HandlerAdapter handlerAdapter;

    protected T controller;

    @SuppressWarnings("unchecked")
    @Before
    public void initContext() throws SecurityException, NoSuchFieldException {
        request = new MockHttpServletRequest();
        response = new MockHttpServletResponse();
        handlerAdapter = applicationContext.getBean(AnnotationMethodHandlerAdapter.class);
        // Does not work, the problem is here...    
        controller = applicationContext.getBean(T);
    }

}

我的想法是为每个我想测试的 Controller 创建一个扩展我的 AbstractSpringMVCControllerTest 的 JUnit 测试类。 . extends 中给出的类型声明是 Controller 的类。

例如,如果我想测试我的 AccountController , 我将创建 AccountControllerTest像这样上课:

public class AccountControllerTest extends AbstractSpringMVCControllerTest<AccountController> {

    @Test
    public void list_accounts() throws Exception {
        request.setRequestURI("/account/list.html");
        ModelAndView mav = handlerAdapter.handle(request, response, controller);
        ...
    }

}

我的问题位于 initContext() 的最后一行抽象类的方法。这个抽象类声明了 controller对象作为 T对象,但如何才能让 Spring Application Context 返回类型为 T 的 bean? ?

我试过类似的东西:

    Class<?> controllerClass = this.getClass().getSuperclass().getDeclaredField("controller").getType();
    controller = (T) applicationContext.getBean(controllerClass);

但是controllerClass返回 java.lang.Object.class类,而不是 AccountController.class .

当然,我可以创建一个public abstract Class<?> getControllerClass();方法,它将被每个 JUnit Controller 测试类覆盖,但我更愿意避免这种解决方案。

那么,有什么想法吗?

最佳答案

如果 AbstractSpringMVCControllerTest 的子类在编译时绑定(bind) T,这是可能的。也就是说,你有类似的东西

public class DerpControllerTest extends AbstractSpringMVCControllerTest<DerpController> { }

而不是

public class AnyControllerTest<T> extends AbstractSpringMVCControllerTest<T> { }

我猜你可能有前者。在这种情况下,T 的类型在运行时从 AbstractSpringMVCControllerTestClass 对象中删除,但是 Class DerpControllerTest 的对象确实提供了一种了解T 是什么的方法,因为它在编译时绑定(bind)了T

下面的类演示了如何访问T的类型:

super .java

import java.lang.reflect.ParameterizedType;
public abstract class Super<T> {

    protected T object;

    @SuppressWarnings("unchecked")
    public Class<T> getObjectType() {
        // This only works if the subclass directly subclasses this class
        return (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
    }

}

子.java

public class Sub extends Super<Double> {
}

测试.java

public class Test {
    public static void main(String...args) {
        Sub s = new Sub();
        System.out.println(s.getObjectType()); // prints "Class java.lang.Double"
    }
}

关于java - 如何获取类型为 T 的字段的类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11158912/

相关文章:

java - 我如何在 java 中使用云 mysql 数据库?

java - Spring 的 MockHttpServlet(Request|Response) 替代品?

c# - 如何在 Java 中编写泛型方法

reactjs - React.memo 的 Typescript 通用类等价物

java - 尝试...最后...没有捕获生成异常

java - java如何填充多边形

java - 在 java Float.parseFloat 中舍入

java - 需要解决 Tomcat 在记录器被处理后尝试记录事件的 webapp 错误

java - 为什么 H2 数据库仅在某些测试中告诉我我的表不存在

java - 通用接口(interface)问题