AspectJ:方法的多态记录.切入点签名问题



我遇到了一些切入点签名的问题。

1.. 消息通过 2 个公开的接口(即将到来,IOutgoing)进入我们的系统,然后由PartsManager组件处理,例如:

PartsManager pmanager = new PartManagerImpl(); pmanager.process(message);

public class PartManagerImpl implements PartsManager{ public boolean process(Message message){ //do some messsage processing.. return true; } }

2.. 然后通过以下方面记录所有已处理的消息。 @Aspect public class OldMessageLogging { private static final Logger LOGGER = Logger.getLogger(OldMessageLogging.class); @Before("execution(* org.company.PartManagerImpl.process(..))") public void processMessageCalled(final JoinPoint joinPoint) throws Throwable { LOGGER.info("Message processed."); return; } }

3..但是,现在我想记录已处理的消息,但要附加一条信息。
而不是处理消息。我希望日志条目变为"已处理传入消息"。 或"已处理传出邮件"。

4.. 因此,我定义了两个附加接口并更改了 PartManagerImpl.java如下所示:

public class PartManagerImpl implements PartsManager, IncommingMessageProcessor, OutgoingMessageProcessor { public boolean process(Message message){ //do some messsage processing.. return true; } } public interface IncommingMessageProcessor { boolean process(Message message); } public interface OutgoingMessageProcessor { boolean process(Message message); }

5.. 现在,消息处理是这样执行的:

IncommingMessageProcessor inProcessor = new PartManagerImpl(); inProcessor.process(message);

OutgoingMessageProcessor outProcessor = new PartManagerImpl(); outProcessor.process(message);

6.. 创建了一个新方面来反映我的新日志记录需求。

@Aspect public class NewMessageLogging { private static final Logger LOGGER = Logger.getLogger(NewMessageLogging.class); @Before("execution(* org.company.IncommingMessageProcessor.process(..))") public void processIncomingCalled(final JoinPoint joinPoint) throws Throwable { LOGGER.info("Incoming message processed."); return; } @Before("execution(* org.company.OutgoingMessageProcessor.process(..))") public void processOutgoingCalled(final JoinPoint joinPoint) throws Throwable { LOGGER.info("Outgoing message processed."); return; } }

THE CATCH:
每当我处理像IncommingMessageProcessor inProcessor = new PartManagerImpl(); inProcessor.process(message);这样的消息时,该消息都会被记录两次,一次作为传入消息,一次作为传出消息。

我只期望对进程传入调用方法的调用。

但是我的两个切入点都被叫了!

我的切入点签名显然是错误的:/

我尝试了各种方法,但无济于事。
有什么建议吗?

解决方案在我的情况下,更改Message类不是一种选择,但这是一个可行的解决方案

我采用了不同的方法来使代码更改最小化。

  1. 两个接口中public boolean process(Message message)的方法都重命名为processIncoming(Message message)processOutgoing(Message message)

    public interface IncommingMessageProcessor { boolean processIncoming(Message message); } public interface OutgoingMessageProcessor { boolean processOutgoing(Message message); }

  2. PartsManager 接口现在扩展了这两个接口class PartsManager extends IncommingMessageProcessor, OutgoingMessageProcessor {...}
    进程(消息消息)方法现在是私有的,但通过调用继承的方法 processIncoming(...) 和 processOutgoing(...) 调用 所以我的切入点现在针对的是对该方法的调用。

  3. 更改的方面(更改的方法名称) @Aspect public class NewMessageLogging { private static final Logger LOGGER = Logger.getLogger(NewMessageLogging.class); @Before("execution(* org.company.PartsManager.processIncoming(..))") public void processIncomingCalled(final JoinPoint joinPoint) throws Throwable { LOGGER.info("Incoming message processed."); return; } @Before("execution(* org.company.PartsManager.processOutgoing(..))") public void processOutgoingCalled(final JoinPoint joinPoint) throws Throwable { LOGGER.info("Outgoing message processed."); return; } }

我假设传入消息实现IIncoming,传出消息实现IOutgoing。然后你可以试试:

@Before("execution(* org.company.PartManagerImpl.process(..)) && args(message)")
public void processIncomingCalled(final JoinPoint joinPoint, IIncoming message)

@Before("execution(* org.company.PartManagerImpl.process(..)) && args(message)")
public void processOutgoingCalled(final JoinPoint joinPoint, IOutgoing message)

一个实现两个接口的类,这两个接口都定义了相同的方法签名,这对我来说似乎很麻烦,你可能不应该这样做。如果传入和传出消息都由同一消息处理程序(甚至相同的方法)处理,则处理程序应该只有一个接口。区分因素应该是消息及其层次结构/接口。这就是我建议的切入点的args部分应该检查的内容(我目前无法访问带有 AspectJ 的编译器,所以我还没有能够自己测试它)。

最新更新