在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 。
答案 0 :(得分:1)
在第二个示例中,实例已上传到Object
,而在第一个示例中,实际提供了Class
。在那个向上的过程中,o
是其他类型的事实已经丢失。
调用clazz.getName()
时不考虑泛型参数,因为代码打印了类的实际类型。
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
具有我需要的日志类名。