gpt4 book ai didi

java - 将元数据添加到 java throwable 对象

转载 作者:行者123 更新时间:2023-12-01 17:03:28 24 4
gpt4 key购买 nike

在我的应用程序中,我执行一些业务逻辑,例如我有业务逻辑方法:

@Override
@ByPassable(exceptions = {"InvalidIdentityException"})
public void validate(Model model) {
if (nonNull(model)) {
final boolean test = isOk(model.getIdentity());
if (test) {
throw new InvalidIdentityException("Invalid bla bla");
}
}
}

和自定义异常类:

public class InvalidIdentityException extends SomeException {

public InvalidIdentityException (final String message) {
super(message);
}
}
方法上的

@ByPassable 获取可以绕过的异常列表,因此在本例中,InvalidIdentityException 会被抛出,并且在不久的将来它会变为bypassable当重新执行该方法时。

我为我的 Spring Boot 应用程序启动了一个 bean,该应用程序具有一组可绕过的异常:

public class Config {

@Bean("bypassable-exceptions")
public Set<String> getBypassableExceptions() {
final Set<String> exceptions = new HashSet<>();
new Reflections(new MethodAnnotationsScanner())
.getMethodsAnnotatedWith(ByPassable.class).stream()
.filter(method -> method.getAnnotation(ByPassable.class).enabled())
.forEach(method -> {
final String[] exceptions = method.getAnnotation(ByPassable.class).exceptions();
exceptions.addAll(Arrays.asList(exceptions));
});
return exceptions;
}
}

每当在方法中引发 Bypassable 异常时,我的应用程序都会将 Throwable 对象作为 Json 保留在数据库中,但是我需要一个额外的 boolean 属性bypassable 在此可抛出对象上,应更新 @BeforeThrowing 异常作为拦截。这可能吗?

public class ExceptionAspect {

@Pointcut("@annotation(com.services.aop.ByPassable)")
public void byPassableExceptionMethods() {
}

@BeforeThrowing(pointcut = "byPassableExceptionMethods()", throwing = "exception")
public void beforeThrowingAdviceForByPassableExceptionMethods(final JoinPoint jp,
final Throwable exception) {

// check against the set of bypassable exceptions and update a custom property on the exception
class so when Throwable is persisted it is persisted with this customer property e.g. bypassable
= true

}

最佳答案

来自 Spring 引用文档:AOP Concepts没有建议类型@BeforeThrowing .

在 Spring AOP 中,可以建议方法执行(连接点) - 在方法开始之前、方法结束之后(有或没有异常)或前后(在方法开始之前和方法结束之后)。这也意味着该方法内的逻辑在运行时无法更改,只能操作方法执行的输入或结果。

根据共享的代码逻辑,异常是根据方法内的验证引发的,并且 Spring AOP 在引发异常之前不提供通知句柄。

话虽如此,以下是我能想到的实现相同目标的方法。

  1. 根据条件和字段 bypassable 引发可绕过异常可以在异常实例创建时本身进行设置。这是最简单的方法。

以下是我为实现相同目的而提出的 Spring AOP 方法。

  • @AfterThrowing可以按如下方式设置可绕过。

  • @BeforeThrowing可以模拟。

  • 注意:使用 Spring AOP 无法拦截内部调用。引用文档中的相关信息可以在section下找到。 。

    Due to the proxy-based nature of Spring’s AOP framework, calls within the target object are, by definition, not intercepted.

    因此,出于演示目的,示例代码 Autowiring 了自己的引用。抛出异常的方法可以移至另一个bean并进行类似的拦截。

    对示例进行了以下更改。

    可绕过异常以拥有公共(public)基类

    public class BaseBypassableException extends RuntimeException {

    private boolean bypassable;

    public BaseBypassableException(String message) {
    super(message);
    }

    public boolean isBypassable() {
    return bypassable;
    }

    public void setBypassable(boolean bypassable) {
    this.bypassable = bypassable;
    }
    }

    可绕过的异常从公共(public)基类扩展

    public class InvalidIdentityException extends BaseBypassableException {

    public InvalidIdentityException(String message) {
    super(message);
    }
    }

    建议方法修改如下。 (示例有 String 而不是 Model )

    @Component
    public class BypassableServiceImpl implements BypassableService {

    @Autowired
    BypassableService service;

    @Override
    @ByPassable(exceptions = {"InvalidIdentityException"})
    public void validate(String model) {
    if (null != model) {
    final boolean test = !("Ok".equals(model));
    if (test) {
    service.throwException(new InvalidIdentityException("Invalid bla bla"));
    }
    }
    System.out.println("Validate called : "+model);

    }

    @Override
    public void throwException(BaseBypassableException exception) {
    throw exception;
    }

    }

    建议这两种方法的方面。 throwing基于异常类型的过滤器,因此对于示例,我没有包含检查 bypassableExceptionNames 的逻辑并且逻辑安全地假设异常的类型为 BaseBypassableException 。如果需要,可以修改逻辑以包括检查。

    @Component
    @Aspect
    public class ExceptionAspect {

    @Autowired
    @Qualifier("bypassable-exceptions")
    Set<String> bypassableExceptionNames;

    @Pointcut("@annotation(com.services.aop.ByPassable)")
    public void byPassableExceptionMethods() {
    }

    @AfterThrowing(pointcut = "byPassableExceptionMethods()", throwing = "exception")
    public void afterThrowingAdviceForByPassableExceptionMethods(final JoinPoint jp,
    final BaseBypassableException exception) {
    System.out.println(jp.getSignature());
    System.out.println("Before " + exception.isBypassable());
    exception.setBypassable(true);
    System.out.println("After " + exception.isBypassable());
    System.out.println(exception);
    }

    @Before("execution(* com.services..*.*(..)) && args(exception)")
    public void beforeThrowingAdviceForByPassableExceptionMethods(final JoinPoint jp,
    final BaseBypassableException exception) {
    System.out.println(jp.getSignature());
    System.out.println("Before " + exception.isBypassable());
    exception.setBypassable(true);
    System.out.println("After " + exception.isBypassable());
    System.out.println(exception);
    }
    }

    希望这有帮助

    关于java - 将元数据添加到 java throwable 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61483347/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com