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



在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的doSomething()中的clazz时,它记录为java.lang.Class

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

在第二个示例中,实例已被升级为Object,而在第一个示例中,提供了实际的Class。在这个上升过程中,o是其他类型的事实丢失了。

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

无论参数化类型包含什么泛型参数,

List<String> list仍然是List。我们不能确定List是否有提供的类型为String的泛型参数,这一事实证明了类型消除的概念。不管类型擦除,调用list.getClass().getName()返回原始类型java.util.List,而不管提供的泛型参数。

为了记录我想要的信息,我使用了两个不同的切入点。其中一个切入点识别出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);
}

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

相关内容

  • 没有找到相关文章

最新更新