我正在使用 @Before
和 @AfterThrowing
Spring AOP 建议。在之前的建议中,我正在验证数据并在验证失败时抛出用户定义的异常。由于我已经定义了 @AfterThrowing
,我希望这会捕获错误以打印我需要的其他信息。但出乎意料的是,我无法点击 @AfterThrowing
建议。我不确定我是否做得正确或者 Spring AOP 不支持。
Spring配置类
package configurations;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScans;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@ComponentScans({
@ComponentScan(value = "beans"),
@ComponentScan(value = "aspects")
})
@ComponentScan(basePackages = {"exceptions"})
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class SpringConfiguration {}
员工类别
package beans;
import java.io.Serializable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Component;
@Component("employee")
//@DependsOn("fullName")
public class Employee implements Comparable<Employee>, Serializable, Cloneable {
private int id;
private String userId;
private String email;
@Autowired(required = false)
private FullName fullName;
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public String getUserId() { return userId; }
public void setUserId(String userId) { this.userId = userId; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
public FullName getFullname() { return fullName; }
public void setFullname(FullName fullname) { this.fullName = fullname; }
@Override
public String toString() {
return "Employee [id=" + id + ", userId=" + userId + ", email=" + email + ", fullname=" + fullName + "]";
}
public int compareTo(Employee secondEmployee) {
return Integer.compare(this.id, secondEmployee.id);
}
}
员工方面
package aspects;
import java.util.Arrays;
import java.util.List;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import exceptions.DataOverflowException;
import exceptions.NumberUnderflowException;
@Component
@Aspect
public class EmployeeAspect {
@Before(value="execution(* beans.Employee.set*(..))")
public void before(JoinPoint joinPoint) throws Exception{
List<Object> inputArguments = Arrays.asList(joinPoint.getArgs());
for(Object argument : inputArguments) {
switch(argument.getClass().getName()) {
case "java.lang.String" : {
String inputString = (String) argument;
if(inputString.length() > 20)
throw new DataOverflowException(joinPoint.getSignature().toString() +" is having excess input information to store.");
else
break;
}
case "java.lang.int" : {
int inputNumber = (int) argument;
if(inputNumber < 1)
throw new NumberUnderflowException(joinPoint.getSignature().toString() +" is not meeting minimun input information to store.");
else
break;
}
}
}
}
@Around("execution(* beans.Employee.*(..))")
public void invoke(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("Method with Signature :: "+ joinPoint.getSignature() + " having data "+ joinPoint.getTarget() + " invoked");
joinPoint.proceed(joinPoint.getArgs());
System.out.println("Method with Signature :: "+ joinPoint.getSignature() + " having data "+ joinPoint.getTarget() + " completed Successfully");
}
@AfterThrowing(pointcut = "execution(* *(..))", throwing= "error")
public void afterThrowing(JoinPoint joinPoint, Exception error) {
System.out.println("===============ExceptionAspect============");
}
}
测试类
package clients;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import beans.Employee;
import configurations.SpringConfiguration;
public class TestClientA {
public static void main(String[] args) {
ConfigurableApplicationContext springContext = new AnnotationConfigApplicationContext(SpringConfiguration.class);
Employee empl = springContext.getBean(Employee.class);
empl.setEmail("<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="32445b5c57575e1c42575e5e575e5e53725b5c545d401c515d5f" rel="noreferrer noopener nofollow">[email protected]</a>");
springContext.close();
}
}
最佳答案
来自引用文档@AfterThrowing人们可以阅读:
Note that @AfterThrowing does not indicate a general exception handling callback. Specifically, an @AfterThrowing advice method is only supposed to receive exceptions from the join point (user-declared target method) itself but not from an accompanying @After/@AfterReturning method.
在您的代码中,@Before
建议在实际用户声明的目标方法之前执行,并引发异常。控制权从此时返回,因此不会到达 @AfterThrowing
建议
另请浏览 advice ordering
As of Spring Framework 5.2.7, advice methods defined in the same @Aspect class that need to run at the same join point are assigned precedence based on their advice type in the following order, from highest to lowest precedence: @Around, @Before, @After, @AfterReturning, @AfterThrowing.
您可以通过this answer (基于spring-aop-5.3.3
)和@Around
,以便可以尝试实现您的用例。
关于spring - 无法捕获 @AfterThrowing 建议中的 @Before 建议中引发的异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66224340/