将元数据添加到java可丢弃对象中



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

@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

我为我的春季启动应用程序启动了一个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保存在数据库中,但我需要在这个可丢弃对象上有一个额外的布尔属性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中,方法执行(joinpoint(可以在方法开始之前、方法完成之后(有或没有异常(或前后(方法开始之前和方法完成之后(进行建议。这也意味着该方法中的逻辑在运行时不能更改,只能操作方法执行的输入或结果。

根据共享的代码逻辑,异常是基于方法内的验证抛出的,并且在抛出excpetion之前,Spring AOP不提供建议的句柄。

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

  1. Bypassable异常是根据条件引发的,并且字段bypassable可以在异常实例创建期间设置。这将是最简单的方法

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

  1. @AfterThrowing可按如下方式用于设置旁路。

  2. 可以模拟CCD_ 11。

注意:使用SpringAOP不能截获内部调用。参考文件中的相关信息可在第节中找到。

由于Spring的AOP框架的基于代理的特性根据定义,目标对象不被拦截。

出于这个原因,出于演示目的,示例代码autowires有自己的参考。抛出异常的方法可能会被移动到另一个bean,并类似地被拦截。

对该示例进行了以下更改。

可绕过的异常具有公共基类

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 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);
}
}

希望这能帮助

最新更新