如何使用Spring 4

时间:2018-02-02 08:17:34

标签: java spring spring-aop interceptor

我正在使用Spring 4并且我不想为每个DAO方法编写记录器,而是我想编写一个方面或拦截器,它可以拦截每个dao方法并将日志放在方法体和内部catch块中。这样做的正确方法是什么?我怎样才能做到这一点?

我尝试编写Spring-Advice,但我无法将logger放在catch块内或方法内。

我的问题是如何编写代码,以便记录器可以放在每个Dao方法体内,也可以在同一方法的catch块中,如果有任何错误 < / p>

这是我的Dao类方法,我不写任何日志

      public Person xyz(SomeObject model) {
                Myresponse response=new Myresponse();
                try {
                    DemoClass blocking=new DemoClass(jdtmp);
                    blocking.setlmfuncparam1(model.getCode());
                    blocking.setlmfuncparam2(model.getIdentification());
                    blocking.startaction();
                    return response;
                }catch(BusinessValidationException e)
                {
                    response.setErrorCode(e.getErrorCode());
                    response.setErrorDescription(e.getErrorMessage());
                    response.setSuccess(false);
                }
                catch (Exception e) {
                            throw new InternalServiceException(APIConstants.INTERNAL_SERVER_ERROR_CODE,
                            APIConstants.INTERNAL_SERVER_ERROR_REQUEST_UNABLE_TO_PROCESS);
                }
                return response;
            }

我想编写AOP或Interceptor,通过这种方法,上面写的每个方法都会有像下面这样的Logger

   <code>
        public Person xyz(SomeObject model) {
            **FILE_LOGGER.debug("In MyDaoImpl Class - xyz method");**
                Myresponse response=new Myresponse();
                try {
                    DemoClass blocking=new DemoClass(jdtmp);
                    blocking.setlmfuncparam1(model.getCode());
                    blocking.setlmfuncparam2(model.getIdentification());
                    blocking.startaction();
                    return response;
                }catch(BusinessValidationException e)
                {
                    response.setErrorCode(e.getErrorCode());
                    response.setErrorDescription(e.getErrorMessage());
                    response.setSuccess(false);
                }
                catch (Exception e) {
                    **FILE_LOGGER.error(Util.getStackTraceAsString(e));**
                    throw new InternalServiceException(APIConstants.INTERNAL_SERVER_ERROR_CODE,
                            APIConstants.INTERNAL_SERVER_ERROR_REQUEST_UNABLE_TO_PROCESS);
                }
                return response;
            }

2 个答案:

答案 0 :(得分:0)

我没有看到任何问题,我建议捕捉的小改变如下:

@Aspect
@Slf4j
@Component
public class LoggerAspect {

    @Around("execution(* com.foo.bar.api.ws.dao..*.*(..))")
    public Object printServiceLogger(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start(proceedingJoinPoint.toShortString());
        String throwableName = null;
        try {
            // execute the profiled method
            return proceedingJoinPoint.proceed();
        } catch (Throwable throwable) {
            throwableName = throwable.getClass().getName();
            throw throwable;
        } finally {
            stopWatch.stop();
            if (throwableName != null) {
                log.error("ERROR while processing request " + proceedingJoinPoint.getSignature().toString() + " " + +stopWatch.getTotalTimeMillis()
                        + " milliseconds with exception [" + throwableName + "]");
            } else {
                log.debug("Total taken for processing request " + proceedingJoinPoint.getSignature().toString() + " " + +stopWatch.getTotalTimeMillis()
                        + " milliseconds");
            }
        }
    }

}

你也可以使用 Afterthrowing

答案 1 :(得分:0)

示例代码中的第一个logger语句可以替换为Spring AOP中的简单@Before("execution(* *(..))")建议。当然,你应该将切入点从拦截所有方法缩小到只有你感兴趣的方法,类似于 Yogi 的例子。但是,由于您既没有解释DAO类的共同点(包名,类名模式,实现的接口或基类),也没有在代码中显示任何包或类名,所以现在我不能给你一个更具体的例子。 (如果你在SO上提出不清楚的问题,你只能得到一些不明确的答案,对不起。)

问题是catch块内的第二个日志语句。在AspectJ中,你可以使用handler()切入点,但是Spring AOP does not support it。所以如果你真的想要这个,你需要在Spring中activate full AspectJ via LTW (load-time weaving)

解决方法不是拦截catch块本身,而是通过InternalServiceException建议拦截抛出的@AfterThrowing。这个解决方案的缺点是你的非正统的异常处理方式:你实例化新的异常,但不要在构造函数中给它原始的异常作为原因。您只是吞下原始异常,使调试变得不必要。这是异常处理的一种不好的方式。因此,根据@AfterThrowing建议,在这种情况下,您无法再记录原始异常。

底线:重构或切换到AspectJ。

P.S。:随意为您的问题添加更多细节,然后我可以提供具体的方面代码示例。