SpringAOP:为什么在Java、AspectJ中@After注释在@AfterThrowing之后执行?

SpringAOP:为什么在Java、AspectJ中@After注释在@AfterThrowing之后执行?,java,aspectj,spring-aop,Java,Aspectj,Spring Aop,我正在学习AspectJ注释,我认为@After注释在@After注释之前执行。但是,它会在它之后执行。为什么? import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterThrowing; import org.aspe

我正在学习AspectJ注释,我认为@After注释在@After注释之前执行。但是,它会在它之后执行。为什么?

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Aspect
@Component
@Order(2)
public class MyDemoLoggingAspect {

    @After("execution(* com.luv2code.aopdemo.dao.AccountDAO.findAccounts(..))")
    public void afterFinallyFindAccountsAdvice(JoinPoint theJoinPoint) {
        
        // print out which method we are advising on
        String method = theJoinPoint.getSignature().toShortString();
        System.out.println("\n=====>>> Executing @After (finally) on method: " 
                            + method);
    
    }
    
    @AfterThrowing(
            pointcut="execution(* com.luv2code.aopdemo.dao.AccountDAO.findAccounts(..))",
            throwing="theExc")
    public void afterThrowingFindAccountsAdvice(
                    JoinPoint theJoinPoint, Throwable theExc) {
        
        // print out which method we are advising on
        String method = theJoinPoint.getSignature().toShortString();
        System.out.println("\n=====>>> Executing @AfterThrowing on method: " + method);
        
        // log the exception
        System.out.println("\n=====>>> The exception is: " + theExc);
    
    }
    
    @AfterReturning(
            pointcut="execution(* com.luv2code.aopdemo.dao.AccountDAO.findAccounts(..))",
            returning="result")
    public void afterReturningFindAccountsAdvice(
                    JoinPoint theJoinPoint, List<Account> result) {
        
        // print out which method we are advising on 
        String method = theJoinPoint.getSignature().toShortString();
        System.out.println("\n=====>>> Executing @AfterReturning on method: " + method);
                
        // print out the results of the method call
        System.out.println("\n=====>>> result is: " + result);
        
        // let's post-process the data ... let's modify it :-)
        
        // convert the account names to uppercase
        convertAccountNamesToUpperCase(result);

        System.out.println("\n=====>>> result is: " + result);
        
    }

    private void convertAccountNamesToUpperCase(List<Account> result) {

        // loop through accounts

        for (Account tempAccount : result) {
            
            // get uppercase version of name
            String theUpperName = tempAccount.getName().toUpperCase();
            
            // update the name on the account
            tempAccount.setName(theUpperName);
        }

    }

    @Before("com.luv2code.aopdemo.aspect.LuvAopExpressions.forDaoPackageNoGetterSetter()")
    public void beforeAddAccountAdvice(JoinPoint theJoinPoint) {
        
        System.out.println("\n=====>>> Executing @Before advice on method");    
        
        // display the method signature
        MethodSignature methodSig = (MethodSignature) theJoinPoint.getSignature();
        
        System.out.println("Method: " + methodSig);
        
        // display method arguments
        
        // get args
        Object[] args = theJoinPoint.getArgs();
        
        // loop thru args
        for (Object tempArg : args) {
            System.out.println(tempArg);
            
            if (tempArg instanceof Account) {
                
                // downcast and print Account specific stuff
                Account theAccount = (Account) tempArg;
                
                System.out.println("account name: " + theAccount.getName());
                System.out.println("account level: " + theAccount.getLevel());                              

            }
        }
        
    }
    
}
import org.aspectj.lang.JoinPoint;
导入org.aspectj.lang.annotation.After;
导入org.aspectj.lang.annotation.AfterReturning;
导入org.aspectj.lang.annotation.afterhrowing;
导入org.aspectj.lang.annotation.Aspect;
导入org.aspectj.lang.annotation.Before;
导入org.aspectj.lang.reflect.MethodSignature;
导入org.springframework.core.annotation.Order;
导入org.springframework.stereotype.Component;
@面貌
@组成部分
@订单(2)
公共类MyDemoLoggingAspect{
@之后(“执行(*com.luv2code.aopdemo.dao.AccountDAO.findAccounts(..)”)
最终发现AccountsDevice后的公共无效(连接点连接点){
//打印出我们建议的方法
String方法=theJoinPoint.getSignature().ToSortString();
System.out.println(“\n====>>>在方法上执行@After(finally):”
+方法);
}
@后冲(
pointcut=“execution(*com.luv2code.aopdemo.dao.AccountDAO.findAccounts(..)”,
投掷(“theExc”)
发布FindAccountsDevice后的公共无效(
接合点接合点,可丢弃(Xc){
//打印出我们建议的方法
String方法=theJoinPoint.getSignature().ToSortString();
System.out.println(“\n====>>>在方法“+方法”上执行@afterthrough);
//记录异常
System.out.println(“\n====>>>异常为:“+theExc”);
}
@返回后(
pointcut=“execution(*com.luv2code.aopdemo.dao.AccountDAO.findAccounts(..)”,
返回=“结果”)
返回FindAccountsDevice后公共无效(
连接点(连接点,列出结果){
//打印出我们建议的方法
String方法=theJoinPoint.getSignature().ToSortString();
System.out.println(“\n====>>>在返回方法“+方法”后执行@);
//打印出方法调用的结果
System.out.println(“\n====>>>结果为:“+result”);
//让我们对数据进行后处理…让我们修改它:-)
//将帐户名转换为大写
ConvertAccountNamesToUpper案例(结果);
System.out.println(“\n====>>>结果为:“+result”);
}
私有void convertAccountNamesToUpperCase(列表结果){
//循环查询帐户
for(帐户临时帐户:结果){
//获取名称的大写版本
字符串theUpperName=tempAccount.getName().toUpperCase();
//更新帐户上的名称
tempAccount.setName(大写);
}
}
@在(“com.luv2code.aopdemo.aspect.LuvAopExpressions.forDaoPackageNoGetterSetter()”之前)
添加AccountAdvice之前的公共无效(连接点连接点){
System.out.println(“\n====>>>在方法通知之前执行@”);
//显示方法签名
MethodSignature methodSig=(MethodSignature)theJoinPoint.getSignature();
System.out.println(“方法:+methodSig”);
//显示方法参数
//获取args
Object[]args=theJoinPoint.getArgs();
//循环通过参数
用于(对象临时参数:参数){
System.out.println(tempArg);
if(帐户的临时参数实例){
//向下播放并打印特定于帐户的内容
账户账户=(账户)临时参数;
System.out.println(“帐户名:+theAccount.getName());
System.out.println(“帐户级别:+theAccount.getLevel());
}
}
}
}
输出示例:

====>>>以异步方式登录到云

=======>>>在方法的建议之前执行@Before 方法:列出com.luv2code.aopdemo.dao.AccountDAO.findAccounts(布尔值) 真的

=======>>>执行API分析

====>>>在方法AccountDAO.findAccounts(..)上执行@AfterThrowing

====>>>例外是:java.lang.RuntimeException:没有汤给你

====>>>在方法AccountDAO.findAccounts(..)上执行@After(finally)

主程序。。。捕获异常:java.lang.RuntimeException:没有汤给你

主程序:AfterhrowingDemoApp

问题的答案在日志语句中。After通知相当于finally块

====>>>在方法AccountDAO.findAccounts(..)上执行@After(finally)

Before、afterhrowing和After类似于下面的java代码

public void advice() {
    before();
    try {
        joinPoint();
    } catch (Exception e) {
        afterThrowing();
    } finally {
        after();
    }
}

private void before() {
    System.out.println("Before");
}

private void after() {
    System.out.println("After");
    
}

private void afterThrowing() {
    System.out.println("After throwing");
    
}

public void joinPoint() {
    System.out.println("Performing API analytics");
    throw new RuntimeException();
}
希望这有帮助

参考资料


问题的答案在日志语句中。After通知相当于finally块

====>>>在方法AccountDAO.findAccounts(..)上执行@After(finally)

Before、afterhrowing和After类似于下面的java代码

public void advice() {
    before();
    try {
        joinPoint();
    } catch (Exception e) {
        afterThrowing();
    } finally {
        after();
    }
}

private void before() {
    System.out.println("Before");
}

private void after() {
    System.out.println("After");
    
}

private void afterThrowing() {
    System.out.println("After throwing");
    
}

public void joinPoint() {
    System.out.println("Performing API analytics");
    throw new RuntimeException();
}
希望这有帮助

参考资料


非常感谢您的解释,也请参阅一些文档链接。非常感谢您的解释,也请参阅一些文档链接。我也在从同一个UDE学习我的教程,我认为图坦卡蒙的示例的行为方式与我们现在使用的库的当前版本不同。同样的问题也出现在成功案例中,@AfterReturning在@AfterOh之前运行,这解释了很多。但这门课之后该怎么办呢?我甚至不知道我能为自己做什么项目。我决定学点别的东西。不管怎样,我想我输了