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

时间:2014-02-27 12:20:43

标签: java aspectj

我在我的方面遇到了几个切入点签名的问题。

1 ..消息通过2个公开的接口(IIncoming,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);这样的消息时,消息被记录两次,一次作为传入消息,一次作为传出消息。

我预计只会调用 processIncomingCalled 方法。

但我的两个切入点都被召唤了!

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

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


在我的案例中,更改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; } }

1 个答案:

答案 0 :(得分:1)

我假设传入的消息实现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的编译器,所以我还没有能够自己测试它。)< / p>