gpt4 book ai didi

java - Spring boot 2.0.2,使用Aop拦截Cloud Stream注释不再起作用

转载 作者:行者123 更新时间:2023-11-30 06:08:47 28 4
gpt4 key购买 nike

我试图使标题尽可能明确和简单。

基本上,我需要拦截Cloud Stream的@Input和@Output注释的使用。这是为了自动向每个 MessageChannel 添加特定的 ChannelInterceptor 所必需的。 (无论消息是被生成还是被消费,preSend 方法中的行为都会略有不同)。

例如,如果我声明此建议

@Around("@annotation(org.springframework.cloud.stream.annotation.Input)")
public Object interceptInput(ProceedingJoinPoint joinPoint) throws Throwable {
LOG.debug("Intercepted @Input from method : {}", joinPoint.getSignature());

Object returnValue = null;

try {
returnValue = joinPoint.proceed();
ChannelInterceptorManager.addInputInterceptor((AbstractMessageChannel)returnValue);
} catch (Exception e) {
LOG.warn("@Input error", e);
}

return returnValue;
}

我声明这个示例类

@EnableBinding(Sink.class)
@Component
public class MyClass {

@StreamListener(Sink.INPUT)
public void handle(Object message) {
// preSend has been called before this method
}
}

这在 Spring Boot 2.0.1 上工作得很好,但在 Spring Boot 2.0.2 上却不行,我很难理解为什么。

我还没有尝试过其他云流的注释,但基本的Aop工作正常。

请记住,这意味着在 JAR 中使用,因此我事先不知道将使用的类或 channel 名称,我需要它对开发人员来说是自动且透明的。

谢谢!

编辑:如果阅读本文的人不熟悉云流,Sink 接口(interface)声明了一个用 @Input 注释的方法,因此启用它的绑定(bind)就可以了。

最佳答案

所以,BPP 并没有完全解决这个问题,因为我需要区分使用 @Input 创建的 MessageChannel 和使用 @Output 创建的 MessageChannel。 MessageChannel bean 不携带此信息。这就是为什么我首先使用 Aop 来分别拦截这两个注释。

为了洞察:我还考虑过将 @GlobalChannelInterceptor 与包含“输入”或“输出”的模式一起使用,但这意味着向最终用户强制执行此类模式。我保留这个解决方案作为最后的手段,但我希望这个过程在使用 jar 时完全不可见并且影响较小。这就是 AOP 派上用场的地方,但 2.0.2 中的这种新行为对我来说肯定是有问题的。

编辑:对于任何在 Spring boot 2.0.2 中遇到类似问题的人来说,版本更改的问题是 bean 初始化顺序。如果您可以控制所需的每个 bean,我建议您看看@DependsOn。

最终,按照 @Oleg Zhurakousky 的建议,我通过使用 BeanPostProcessor 而不是 AOP 将输入与输出分开来解决了我的具体问题。下面是一个工作方法:

@Autowired
private AbstractBeanFactory beanFactory;

@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof AbstractMessageChannel) {
try {
RootBeanDefinition beanDefinition = (RootBeanDefinition) beanFactory.getMergedBeanDefinition(beanName);
Method method = beanDefinition.getResolvedFactoryMethod();

if (method != null) {
if (AnnotationUtils.findAnnotation(method, Input.class) != null) {
((AbstractMessageChannel)bean).addInterceptor(/*Your input ChannelInterceptor*/);
} else if (AnnotationUtils.findAnnotation(method, Output.class) != null) {
((AbstractMessageChannel)bean).addInterceptor(/*Your output ChannelInterceptor*/);
}
}
} catch (Exception e) {
// exception can be thrown by the bean factory
}
}

return bean;
}

关于java - Spring boot 2.0.2,使用Aop拦截Cloud Stream注释不再起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50682722/

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