2

In a Spring 3 webapp, I have a DAO that looks something like this:

public class BaseDAOImpl<T extends AbstractEntity> implements BaseDAO<T> {
   ...

    public void doSomething(Class<T> clazz) {
        log.debug("class name: " + clazz.getName());
        ...
    }

   ...
}

That log prints what I'm looking for, let's say com.xyz.Customer.

But that logging line above is just for illustration. In the app, I'm using an aspect to handle logging. And in that aspect, I'm recording arguments. So in my @Before advice, I have some code like this:

...
Object[] args = joinPoint.getArgs();
for (Object o : args) {
    ...
    log.debug("class name: " + o.getClass().getName());
    ...

And when that runs against clazz in BaseDAOImlp's doSomething(), it logs as java.lang.Class.

So, while understanding that generics are implemented via type erasure, I don't understand why I see com.xyz.Customer with the getName() call in doSomething(), but java.lang.Class in the aspect.

4

2 回答 2

1

在第二个示例中,实例已向上转换为Object,而在您的第一个示例中,Class提供了实际实例。在那次上调期间,o其他类型的事实丢失了。

调用时不考虑泛型参数,clazz.getName()因为代码会打印类的实际类型。

List<String> listList无论参数化类型包含什么泛型类型参数,它仍然是一个。我们无法确定List是否提供了类型的泛型参数这一事实String证明了类型擦除的概念。无论提供何种泛型参数,无论类型擦除调用list.getClass().getName()返回原始类型。java.util.List

于 2013-05-24T18:41:52.220 回答
0

为了记录我想要的信息,我使用了两个不同的切入点。其中一个切入点识别何时java.lang.Class是我们 DAO 中方法的第一个参数,并将该参数传递给通知。

(幸运的是,按照我们代码库中的约定,当 DAO 接受类参数时,它总是先出现。这不是一个非常通用的解决方案。)

以下是切入点的样子:

@Pointcut("execution(* com.xyz.dao..*.*(..)) && args(clazz,..)")
public void classyDAOMethods(Class<?> clazz) { ... }

@Pointcut("execution(* com.xyz.dao..*.*(..)) && !args(java.lang.Class,..)")
public void unclassyDAOMethods() { ... }

这个建议对每个切口的处理方式略有不同:

@Before("classyDAOMethods(clazz)")
public void classyAdvice(JoinPoint joinPoint, Class<?> clazz) {
    logMethodEntry(joinPoint, clazz);
}

@Before("unclassyDAOMethods()")
public void logMethodEntry(JoinPoint joinPoint) {
    logMethodEntry(joinPoint, null);
}

clazz一个传递的@Before具有我需要的日志类名。

于 2013-06-21T21:42:07.223 回答