使用@Aspect 更改方法签名
Change method signature with @Aspect
您可以使用方面更改 Spring 中方法的签名吗?
点赞有效转化如下:
@GetMapping("/thing")
@User // custom annotation that should authenticate the user
public ResponseEntity getThing() {
... // user is successfully authenticated, get the "thing" from the database
}
进入:
@GetMapping("/thing")
public ResponseEntity getThing(@CookieValue("Session-Token") String sessionToken) {
User user = authenticator.authenticateSessionTokenOrThrow(sessionToken);
... // user is successfully authenticated, get the "thing" from the database
}
随着 user
变量也可以在方法主体中使用。
如果不是,我如何在不到处重复代码(参数和验证器调用)的情况下获得相同的结果?
方面不是为了那个。
是的,他们可以有效地修改 .class
文件字节码,编译时或 运行 时间编织,但他们 不会 覆盖方法的签名。
此外,默认的 Spring AOP 方面是在纯 Java 中实现的,因此无法触及字节码层。为此,您需要 AspectJ。
在 run/compile 时自定义字节码的工具是 ASM, ByteBuddy、CGLIB 或 Javassist。
但是,您可能可以通过 Annotation Processor 来完成此操作,它允许您修改实际的 sources,而不是已经编译的字节码。
If not, how can I achieve the same result without repeating the code
(parameter and authenticator call) everywhere?
可能的解决方案是
- HandlerInterceptor,如果用户未通过身份验证
,它只会抛出一个 Exception
- 标准 Spring AOP 建议,如果用户未通过身份验证
,它只会抛出 Exception
- Spring 安全性
1 很简单。
2比较耗时
3 恕我直言,似乎最适合身份验证,但它是最复杂的,可能
The HandlerInterceptor can choose which methods it applies to?
不,不幸的是。几个月前,我有一个要求 "cover" 只有某些带有 Interceptor
的方法,我实现了一个自定义解决方案,它只查找方法本身指定的注释。
这是我的自定义 HandlerInterceptor
的摘录,它查找 CheckInit
注释,首先在类型上,然后在方法上,以进行更具体的自定义。
@Override
public boolean preHandle(
final HttpServletRequest request,
final HttpServletResponse response,
final Object handler
) throws Exception {
if (handler instanceof HandlerMethod) {
if (shouldCheckInit((HandlerMethod) handler)) {
checkInit();
}
}
return true;
}
private static boolean shouldCheckInit(final HandlerMethod handlerMethod) {
final var typeAnnotation = handlerMethod.getBeanType().getAnnotation(CheckInit.class);
final var shouldCheckInit = typeAnnotation != null && typeAnnotation.value();
final var methodAnnotation = handlerMethod.getMethodAnnotation(CheckInit.class);
return (methodAnnotation == null || methodAnnotation.value()) && shouldCheckInit;
}
private void checkInit() throws Exception {
if (!manager.isActive()) {
throw new NotInitializedException();
}
}
The "Standard Spring AOP advice" seems interesting, do you have a link
for that?
Spring AOP documentation - 寻找基于 Java 的配置(我讨厌 XML)
AspectJ really touches the bytecode and can modify signatures as well?
您可以让 AspectJ 修改签名。只需 fork 项目并修改其 Java 代理或编译器。
AFAIK Annotation Processors cannot modify classes, they can only
create new ones.
事实是,他们不修改 .class
文件,而是修改源文件,这意味着他们只是编辑它们。例如。 Lombok使用注解处理修改源文件
但是,是的,修改后的源被写入一个新文件。
您可以使用方面更改 Spring 中方法的签名吗?
点赞有效转化如下:
@GetMapping("/thing")
@User // custom annotation that should authenticate the user
public ResponseEntity getThing() {
... // user is successfully authenticated, get the "thing" from the database
}
进入:
@GetMapping("/thing")
public ResponseEntity getThing(@CookieValue("Session-Token") String sessionToken) {
User user = authenticator.authenticateSessionTokenOrThrow(sessionToken);
... // user is successfully authenticated, get the "thing" from the database
}
随着 user
变量也可以在方法主体中使用。
如果不是,我如何在不到处重复代码(参数和验证器调用)的情况下获得相同的结果?
方面不是为了那个。
是的,他们可以有效地修改 .class
文件字节码,编译时或 运行 时间编织,但他们 不会 覆盖方法的签名。
此外,默认的 Spring AOP 方面是在纯 Java 中实现的,因此无法触及字节码层。为此,您需要 AspectJ。
在 run/compile 时自定义字节码的工具是 ASM, ByteBuddy、CGLIB 或 Javassist。
但是,您可能可以通过 Annotation Processor 来完成此操作,它允许您修改实际的 sources,而不是已经编译的字节码。
If not, how can I achieve the same result without repeating the code (parameter and authenticator call) everywhere?
可能的解决方案是
- HandlerInterceptor,如果用户未通过身份验证 ,它只会抛出一个
- 标准 Spring AOP 建议,如果用户未通过身份验证 ,它只会抛出
- Spring 安全性
Exception
Exception
1 很简单。
2比较耗时
3 恕我直言,似乎最适合身份验证,但它是最复杂的,可能
The HandlerInterceptor can choose which methods it applies to?
不,不幸的是。几个月前,我有一个要求 "cover" 只有某些带有 Interceptor
的方法,我实现了一个自定义解决方案,它只查找方法本身指定的注释。
这是我的自定义 HandlerInterceptor
的摘录,它查找 CheckInit
注释,首先在类型上,然后在方法上,以进行更具体的自定义。
@Override
public boolean preHandle(
final HttpServletRequest request,
final HttpServletResponse response,
final Object handler
) throws Exception {
if (handler instanceof HandlerMethod) {
if (shouldCheckInit((HandlerMethod) handler)) {
checkInit();
}
}
return true;
}
private static boolean shouldCheckInit(final HandlerMethod handlerMethod) {
final var typeAnnotation = handlerMethod.getBeanType().getAnnotation(CheckInit.class);
final var shouldCheckInit = typeAnnotation != null && typeAnnotation.value();
final var methodAnnotation = handlerMethod.getMethodAnnotation(CheckInit.class);
return (methodAnnotation == null || methodAnnotation.value()) && shouldCheckInit;
}
private void checkInit() throws Exception {
if (!manager.isActive()) {
throw new NotInitializedException();
}
}
The "Standard Spring AOP advice" seems interesting, do you have a link for that?
Spring AOP documentation - 寻找基于 Java 的配置(我讨厌 XML)
AspectJ really touches the bytecode and can modify signatures as well?
您可以让 AspectJ 修改签名。只需 fork 项目并修改其 Java 代理或编译器。
AFAIK Annotation Processors cannot modify classes, they can only create new ones.
事实是,他们不修改 .class
文件,而是修改源文件,这意味着他们只是编辑它们。例如。 Lombok使用注解处理修改源文件
但是,是的,修改后的源被写入一个新文件。