所以我正在使用AspectJ重构我的程序以从主类中删除所有日志记录调用。相反,所有日志记录调用都将通过方面进行。到目前为止,这是我成功完成的事情:
捕获所有异常。因为我已经开始使用异常处理(异常传播调用堆栈直到它们到达我的控制器,然后被捕获),这并不太难。使用句柄(异常)我已经将每个catch块绑定到一个方面,该方面将在catch块执行之前记录异常。
调试信息记录。输入特定方法等基本内容。再次,使用before()相对简单,有时使用args()或thisJoinPoint.getArgs()来捕获参数。
但是,我需要做的最后一件事就是正确记录关键方法的成功完成情况。这是一个小例子,它是我程序中当前存在的一段代码,所以我可以在这里更好地解释我的意思:
private static void loadDefaultProperties(){
defaultProperties = new Properties();
try {
defaultProperties.load(
Main.class.getClassLoader().getResourceAsStream(
"default.properties"));
if(defaultProperties.size() == 0){
throw new IOException();
}
//THE CURRENT LOGGING LINE THAT NEEDS TO BE MOVED TO AN ASPECT
LOGGER.logp(Level.INFO, Main.class.getName(),
"loadDefaultProperties()",
"Default Properties file loaded successfully");
}
catch (IOException ex){
//THIS EXCEPTION IS LOGGED USING HANDLE(EXCEPTION) IN AN ASPECT
displayExceptionDialog(ex);
}
}
因此,此方法从类路径加载默认属性。如果失败,则抛出IOException。但是,如果没有抛出异常,并且它成功执行了它的任务,我也想记录它。
这个特殊的例子是一个相对较小的项目,不容错过,但这是目前在应用程序中使用的风格。
如何将AspectJ中的切入点/建议配置为仅在此方法完成后运行,并认识到它成功完成了?
PS。我考虑过在调用堆栈中进一步传播异常。这将允许我使用简单的after()返回(Object o)建议来完成此任务。如果抛出异常,则此建议将无法运行,因为该方法无法正常返回。
问题在于调用堆栈中没有比这更高的级别。我的示例中的这个特殊方法在程序初始化之后立即由我的main方法直接调用。在我的控制器类中,我的所有方法的调用堆栈中只有一个级别更高。
我想我可以做到这一点,但我想先看看是否还有其他选项,而不是将所有这些例外汇集在一起。
答案 0 :(得分:0)
你当然可以使用切入点来包装调用堆栈中的任何内容,包括main()
:
public aspect WrapMain
{
pointcut mainMethod() : execution(public static void main(String[]));
before() : mainMethod() {
System.out.println("Starting application...");
}
after() : mainMethod() {
System.out.println("Terminating application...");
}
}
如果您使用Java生成方面,则可以使用@AfterReturning
和@AfterThrowing
注释来管理成功或例外情况。
@Pointcut("execution(your-method-signature-here)
public void yourPointcut(){}
@AfterReturning(pointcut = "yourPointcut()", returning ="returnValue")
public void afterSuccessAdvice(JoinPoint jp, Object returnValue) {
// log here
}
@AfterThrowing(pointcut = "yourPointcut()", returning ="returnValue")
public void afterFailureAdvice(JoinPoint jp, Object returnValue) {
// log here
}
这是一篇Javaworld文章,其中包含解释日志记录方法进入和退出的示例。