使用log4j在Logging,Spring AOP中的切入点表达式问题

时间:2014-10-30 05:29:44

标签: spring spring-aop

我必须为属于com.mycomp的包和子包的所有方法应用日志信息。**。我尝试过在春季参考手册中给出的许多切入点,但遗憾的是没有人为我工作。 我正在使用

@Pointcut("execution(* com.mycomp..(..))")
private void businessService() {}  // signature

我得到的是

Caused by: java.lang.IllegalArgumentException: Pointcut is not well-formed: expecting
'name pattern cannot finish with ..' at character position 27
 execution(* com.mycomp..(..))

在文档中给出了

 @Pointcut("execution( com.xyz.someapp..service..(..))")

我尝试过使用执行(com.mycomp ..(..))但得到了类似的异常。

按照James的建议使用切入点@Around(value =“execution(* xyz.package.foo.bar .. *(..))”)我在启动服务器时遇到了新的异常。

   Caused by: java.lang.IllegalStateException: Cannot convert value of type [$Proxy76 implementing org.springframework.context.ApplicationContextAware,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised] to required type [com.mycompname.BancsContextAware] for property 'bancsContextAware': no matching editors or conversion strategy found
at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:264)
at org.springframework.beans.BeanWrapperImpl.convertIfNecessary(BeanWrapperImpl.java:448)
... 57 more

后来在调试时发现我在其中一个类中使用了object.getClass()。getAnnotation(),而spring AOP创建的代理对象没有注释。因为只有我得到一个空指针异常。我使用AopProxyUtils.ultimateTargetClass(s​​omeObject)对其进行了排序 但现在的问题是我在com.mycom的子包中有一些最终的类和枚举..因为我得到了

nested exception is org.springframework.aop.framework.AopConfigException: 
Could not generate CGLIB subclass of class [class com.mycom.util.BancsServiceProvider]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Cannot subclass final class class com.mycom.util.BancsServiceProvider
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:529)

那么如何从Spring AOP切入点中排除最终类和枚举。

2 个答案:

答案 0 :(得分:2)

您正在寻找的切入点和方法是这样的:

@Around(value="execution(* xyz.package.foo.bar..*(..))")
public Object beforeAdvice(ProceedingJoinPoint jp) throws Throwable {
    //Get log4j logger for target class.
    Logger logger = LogManager.getLogger(jp.getTarget().getClass());

    logger.info(jp.getTarget().getClass().getName() + " " + jp.getSignature().getName() + " "
            + "Hit:");
    Object returnVal = jp.proceed(jp.getArgs());
    logger.info(jp.getTarget().getClass().getName() + " " + jp.getSignature().getName() + " "
            + "Finished:");
    return returnVal;
}

上面的代码将在进入方法之前记录类和方法名称以及“命中”,并在以下列方式完成后完成“完成”:

xyz.package.foo.bar.service.getPerson: Hit:
xyz.package.foo.bar.dao.getPerson: Hit:
xyz.package.foo.bar.dao.getPerson: Finished:
xyz.package.foo.bar.service.getPerson: Finished:
...

如果您想尝试遵循方法的多线程执行,只需使用以下内容:

@Around(value="execution(* xyz.package.foo.bar..*(..))")
public Object beforeAdvice(ProceedingJoinPoint jp) throws Throwable {
    Logger logger = LogManager.getLogger(jp.getTarget().getClass());

    String executionId = UUID.randomUUID().toString();

    logger.info(jp.getTarget().getClass().getName() + " " + jp.getSignature().getName() + " "
            + "Hit:" + executionId);
    Object returnVal = jp.proceed(jp.getArgs());
    logger.info(jp.getTarget().getClass().getName() + " " + jp.getSignature().getName() + " "
            + "Finished:" + executionId);
    return returnVal;
}

每个线程调用将获得一个UUID,这将允许您跟踪这些方法在所有线程中执行的速度。我在尝试获取性能测试的方法时间时使用此代码,并且它可以创建奇迹。

确保您将此类声明为一个方面。

答案 1 :(得分:0)

您是否尝试过以下操作?

@Pointcut( “内(com.mycomp .. *)”)