我在spring kafka的GenericMessageListener上添加了切入点, 我正在使用@KafkaListener,并且该方面不起作用。如果我将切入点更改为 KafkaListener 的注释,它就可以工作。
我有两个问题:
在 Spring Kafka 项目中重现此操作的最少代码
@Pointcut("execution(* org.springframework.kafka.listener.GenericMessageListener.*(..))")
fun consumerOnMessagePC() {}
@Around("consumerOnMessagePC()")
fun consumerRedirectionAdvice(pjp: ProceedingJoinPoint):Any? {
println("consumerOnMessagePointCut works ~~~~")
return null
}
@SpringBootApplication
@Import(RedirectionConfig::class)
class DemoApplication {
private val logger = LoggerFactory.getLogger(javaClass)
// redirection topic: "topic-poc-v1-redirection"
@KafkaListener(id = "consumer-poc", topics = ["topic-poc-v1"])
fun listen(value: String?) {
logger.info("Listen with Simple Value, message {}", value)
}
}
- 有人说这不起作用,因为 Spring 方面在代理(动态代理或 cglib 代理)上工作,但我不太明白为什么它会影响父类/接口上的点;
答案#1。当针对
@KafkaListener
的父类或接口时,方面不起作用的原因是 Spring AOP 的工作方式。 Spring AOP 使用 JDK 动态代理或 CGLIB 为给定的目标对象创建代理。如果目标对象至少实现一个接口,则使用 JDK 动态代理。如果目标对象未实现任何接口,则会创建 CGLIB 代理。这意味着代理只能建议属于目标对象或其类实现的接口一部分的方法。如果您尝试建议的方法不属于这些接口,则建议将不会被应用。
- 如何直接更改接口,以便所有直接或间接实现它的类都可以更改?
答案#2。创建一个扩展现有接口的新接口,并将您的方法添加到这个新接口。然后,让您的类实现这个新接口而不是原来的接口。
这只是一个示例执行:
public interface NewInterface extends OriginalInterface {
void newMethod();
}
public class MyClass implements NewInterface {
@Override
public void newMethod() {
// Your implementation here.
}
}
在上面的代码中,
NewInterface
扩展了OriginalInterface
并添加了一个新方法newMethod()
。 MyClass
然后实现 NewInterface
并提供 newMethod()
的实现。这样,所有实现 NewInterface
的类都必须提供 newMethod()
的实现。