方面vs实例方法中的类getName()行为

时间:2013-05-24 18:28:04

标签: java spring reflection aop

在Spring 3 webapp中,我有一个看起来像这样的DAO:

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

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

   ...
}

该日志打印出我正在寻找的内容,让我们说 com.xyz.Customer

但上面的记录行只是为了说明。在应用程序中,我正在使用一个方面来处理日志记录。在那方面,我正在记录论点。所以在我的@Before建议中,我有一些像这样的代码:

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

当它在BaseDAOImlp的clazz中针对doSomething()运行时,它会记录为 java.lang.Class

因此,虽然理解通过类型擦除实现泛型,但我不明白为什么我在getName()中使用doSomething()调用看到 com.xyz.Customer ,但方面的 java.lang.Class

2 个答案:

答案 0 :(得分:1)

在第二个示例中,实例已上传到Object,而在第一个示例中,实际提供了Class。在那个向上的过程中,o是其他类型的事实已经丢失。

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

无论参数化类型包含哪种genric类型参数,

List<String> list仍然是List。我们无法确定List具有类型String的通用参数的事实演示了类型erause的概念。无论类型擦除如何,无论提供的通用参数如何,调用list.getClass().getName()都会返回原始类型java.util.List

答案 1 :(得分: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具有我需要的日志类名。