Spring AOP:为什么@After 注解在Java、AspectJ 中的@AfterThrowing 之后执行?
Spring AOP: Why @After annotation executes after @AfterThrowing in Java, AspectJ?
我正在学习 AspectJ 注释,我认为 @After 注释在 @AfterThrowing 注释之前执行。但相反,它在它之后执行。为什么?
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());
}
}
}
}
输出示例:
=====>>>> 以异步方式登录到云端
=====>>> 在方法上执行@Before 建议
方法:List com.luv2code.aopdemo.dao.AccountDAO.findAccounts(boolean)
真
=====>>> 执行 API 分析
=====>>> 在方法上执行@AfterThrowing:AccountDAO.findAccounts(..)
=====>>>>例外情况是:java.lang.RuntimeException:不给你喝汤!!!
=====>>> 在方法上执行@After(最后):AccountDAO.findAccounts(..)
主程序...捕获到异常:java.lang.RuntimeException:没有汤给你!!!
主程序:AfterThrowingDemoApp
无
您问题的答案在您的日志语句中。 After Advice 相当于一个 finally 块
=====>>> 在方法上执行@After(最后):AccountDAO.findAccounts(..)
Before、AfterThrowing 和 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();
}
希望对您有所帮助
参考资料
我正在学习 AspectJ 注释,我认为 @After 注释在 @AfterThrowing 注释之前执行。但相反,它在它之后执行。为什么?
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());
}
}
}
}
输出示例:
=====>>>> 以异步方式登录到云端
=====>>> 在方法上执行@Before 建议 方法:List com.luv2code.aopdemo.dao.AccountDAO.findAccounts(boolean) 真
=====>>> 执行 API 分析
=====>>> 在方法上执行@AfterThrowing:AccountDAO.findAccounts(..)
=====>>>>例外情况是:java.lang.RuntimeException:不给你喝汤!!!
=====>>> 在方法上执行@After(最后):AccountDAO.findAccounts(..)
主程序...捕获到异常:java.lang.RuntimeException:没有汤给你!!!
主程序:AfterThrowingDemoApp
无
您问题的答案在您的日志语句中。 After Advice 相当于一个 finally 块
=====>>> 在方法上执行@After(最后):AccountDAO.findAccounts(..)
Before、AfterThrowing 和 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();
}
希望对您有所帮助
参考资料