离开方法时使用拦截器
Using interceptor when leaving a method
在我的 Java EE 程序中,我想使用 Interceptor 进行日志记录。当我进入一个方法时它很容易使用:
注释:
@Inherited
@InterceptorBinding
@Retention(RUNTIME)
@Target({ METHOD, TYPE })
public @interface Logged {
}
拦截器:
@Logged
@Interceptor
public class LoggedInterceptor implements Serializable {
private static final long serialVersionUID = 1L;
@Inject
private Logger logger;
@AroundInvoke
public Object logMethodEntry(InvocationContext invocationContext) throws Exception {
logger.info("Entering method: "
+ invocationContext.getMethod().getName() + " in class "
+ invocationContext.getMethod().getDeclaringClass().getName());
return invocationContext.proceed();
}
}
我的class使用拦截器:
public class MyClass {
@Logged
public void MyMethod() {
// do something
}
}
但现在我想在离开 MyMethod 时做同样的事情。这可能吗?
AroundInvoke 并不意味着具体进入 - 它意味着您将其挂起 "around the invocation";它的名字被恰当地选择了。那里的 proceed() 调用是您用拦截器包装的实际方法调用。因此,您当前在 proceed() 调用之前记录 - 如果您在 proceed() 调用之后添加日志,那就是离开方法调用的点。
@Logged
@Interceptor
public class LoggedInterceptor implements Serializable {
private static final long serialVersionUID = 1L;
@Inject
private Logger logger;
@AroundInvoke
public Object logMethodCall(InvocationContext invocationContext) throws Exception {
logger.info("Entering method: "
+ invocationContext.getMethod().getName() + " in class "
+ invocationContext.getMethod().getDeclaringClass().getName());
Object ret = invocationContext.proceed();
logger.info("Left method: "
+ invocationContext.getMethod().getName() + " in class "
+ invocationContext.getMethod().getDeclaringClass().getName());
return ret;
}
}
@Gimby 的回答几乎是正确的。他的解决方案缺少的是异常处理。在异常的情况下,"Left method" 永远不会被记录。
建议解决方案:
@Logged
@Interceptor
public class LoggedInterceptor implements Serializable {
private static final long serialVersionUID = 1L;
@Inject
private Logger logger;
@AroundInvoke
public Object logMethodCall(InvocationContext invocationContext) throws Exception {
Object ret = null;
logger.info("Entering method: "
+ invocationContext.getMethod().getName() + " in class "
+ invocationContext.getMethod().getDeclaringClass().getName());
try {
ret = invocationContext.proceed();
} catch(Exception e) {
throw e;
} finally {
logger.info("Left method: "
+ invocationContext.getMethod().getName() + " in class "
+ invocationContext.getMethod().getDeclaringClass().getName());
}
return ret;
}
}
在我的 Java EE 程序中,我想使用 Interceptor 进行日志记录。当我进入一个方法时它很容易使用:
注释:
@Inherited
@InterceptorBinding
@Retention(RUNTIME)
@Target({ METHOD, TYPE })
public @interface Logged {
}
拦截器:
@Logged
@Interceptor
public class LoggedInterceptor implements Serializable {
private static final long serialVersionUID = 1L;
@Inject
private Logger logger;
@AroundInvoke
public Object logMethodEntry(InvocationContext invocationContext) throws Exception {
logger.info("Entering method: "
+ invocationContext.getMethod().getName() + " in class "
+ invocationContext.getMethod().getDeclaringClass().getName());
return invocationContext.proceed();
}
}
我的class使用拦截器:
public class MyClass {
@Logged
public void MyMethod() {
// do something
}
}
但现在我想在离开 MyMethod 时做同样的事情。这可能吗?
AroundInvoke 并不意味着具体进入 - 它意味着您将其挂起 "around the invocation";它的名字被恰当地选择了。那里的 proceed() 调用是您用拦截器包装的实际方法调用。因此,您当前在 proceed() 调用之前记录 - 如果您在 proceed() 调用之后添加日志,那就是离开方法调用的点。
@Logged
@Interceptor
public class LoggedInterceptor implements Serializable {
private static final long serialVersionUID = 1L;
@Inject
private Logger logger;
@AroundInvoke
public Object logMethodCall(InvocationContext invocationContext) throws Exception {
logger.info("Entering method: "
+ invocationContext.getMethod().getName() + " in class "
+ invocationContext.getMethod().getDeclaringClass().getName());
Object ret = invocationContext.proceed();
logger.info("Left method: "
+ invocationContext.getMethod().getName() + " in class "
+ invocationContext.getMethod().getDeclaringClass().getName());
return ret;
}
}
@Gimby 的回答几乎是正确的。他的解决方案缺少的是异常处理。在异常的情况下,"Left method" 永远不会被记录。
建议解决方案:
@Logged
@Interceptor
public class LoggedInterceptor implements Serializable {
private static final long serialVersionUID = 1L;
@Inject
private Logger logger;
@AroundInvoke
public Object logMethodCall(InvocationContext invocationContext) throws Exception {
Object ret = null;
logger.info("Entering method: "
+ invocationContext.getMethod().getName() + " in class "
+ invocationContext.getMethod().getDeclaringClass().getName());
try {
ret = invocationContext.proceed();
} catch(Exception e) {
throw e;
} finally {
logger.info("Left method: "
+ invocationContext.getMethod().getName() + " in class "
+ invocationContext.getMethod().getDeclaringClass().getName());
}
return ret;
}
}