0

下面FailedMessageAspect.afterMethod()在下面被成功调用RabbitConsumerMain.main()。但是,当它在侦听 RabbitMQ 消息的上下文中使用时不会被调用 - 当MessageHandlerImpl.handleMesasge()从 RabbitMQ 队列接收消息时。知道为什么吗?

FailedMessageAspect.java

@Aspect
@Component
public class FailedMessageAspect {

    @AfterReturning("execution(* com..MessageHandlerImpl.testAspect(..))")
    private void afterMethod() {
        System.out.println("aspect foo");
    }
}

MessageHandlerImpl.java

@Component
public class MessageHandlerImpl implements MessageHandler {

    @Override
    public void testAspect() {
        System.out.println("handler foo");
    }

    @Override
    public void handleMessage(String message) {
        // handleMessage is called successfully when message is received
        testAspect();
        // FailedMessageAspect.afterMethod() does not get called
    }
}

RabbitConsumerMain.java

@Controller
@SpringBootApplication
public class RabbitConsumerMain implements CommandLineRunner {

    @Autowired
    private MessageHandler messageHandler;

    public static void main(String[] args) throws Exception {
        SpringApplication.run(RabbitConsumerMain.class, args);
    }

    @Override
    public void run(String... args) {
        messageHandler.testAspect();
        //FailedMessageSpect.afterMethod() gets called right here
    }
}

消费者配置.java

@Configuration
public class ConsumerConfiguration {
    @Autowired @Lazy
    private MessageHandler messageHandler;

    //other standard AMQP configs

    @Bean
    public MessageListenerContainer messageListenerContainer() {
        SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
        container.setConnectionFactory(connectionFactory());
        container.setQueues(workQueue());
        MessageListenerAdapter adapter = new MessageListenerAdapter(messageHandler, new Jackson2JsonMessageConverter());
        container.setMessageListener(adapter);
        return container;
    }
}
4

1 回答 1

3

您没有显示所有配置,但为了清楚起见,Spring AOP 不建议内部方法调用,例如在同一个类实例中handleMessage调用。testAspect()

为此,您需要使用 AspectJ;否则,您建议的所有方法都必须是通过 bean 定义调用的公共方法,因此 Spring 可以通过代理调用该方法。从不建议 bean 中的内部调用。

有关完整说明,请参阅参考手册

于 2015-06-06T03:50:39.170 回答