本文介绍了虫孔图案w. AspectJ:如何获取调用方方法名称?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

限时删除!!

在AspectJ中使用虫洞模式,是否有办法可以在虫洞建议中看到执行方法的名称?

Using the wormhole pattern with AspectJ, is there a way that the executing method name can be seen in the wormhole advice?

我有一个示例,其中服务类(ClientService)在域类(Client)上调用getter.我想要的是在建议中知道要知道称为getter的服务方法的名称.看到服务对象本身没有问题,但是我需要服务方法的名称.

I have an example where a service class (ClientService) calls getters on a domain class (Client). What I want, is to know in the advice to know the name of service method that called the getter.I have no problem seeing the service object itself, but I need the name of the service method.

这是我的方面:

public aspect MyAspect {

    pointcut serviceExecution(ClientService srv) : execution(* ClientService.*(..)) && this(srv);

    pointcut modelGetter(Client client) : execution(public * Client.get*()) && this(client);

    pointcut wormhole(ClientService srv, Client client) : cflow(serviceExecution(srv)) && modelGetter(client);

    Object around(ClientService srv, Client client) : wormhole(srv, client) {

        // what is the name of the service-method calling?

        Object ret = proceed(srv, client);
        return ret;
    }
}

这可能吗?

谢谢

-J

推荐答案

客户端:

package de.scrum_master.app;

public class Client {
    private String name;

    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
}

包括客户服务主要方法示例:

package de.scrum_master.app;

public class ClientService {
    private Client client;

    public ClientService(Client client) { this.client = client; }
    public String getSomething() { return client.getName(); }
    public void setSomething(String something) { client.setName(something); }

    public static void main(String[] args) {
        ClientService clientService = new ClientService(new Client());
        clientService.setSomething("new value");
        clientService.getSomething();
    }
}

方面:

在这里,您需要更改切入点modelGetter以使用call()代替execution(),并使用target()代替this().

Here you need to change pointcut modelGetter to use call() instead of execution() and target() instead of this().

package de.scrum_master.aspect;

import de.scrum_master.app.Client;
import de.scrum_master.app.ClientService;

public aspect MyAspect {
    pointcut serviceExecution(ClientService srv) :
        execution(* ClientService.*(..)) && this(srv);

    pointcut modelGetter(Client client) :
        call(public * Client.get*()) && target(client);

    pointcut wormhole(ClientService srv, Client client) :
        cflow(serviceExecution(srv)) && modelGetter(client);

    Object around(ClientService srv, Client client) : wormhole(srv, client) {
        System.out.println("Caller: " + thisEnclosingJoinPointStaticPart.getSignature().toShortString() + " -> " + srv);
        System.out.println("Callee: " + thisJoinPointStaticPart.getSignature().toShortString() + " -> " + client);

        return proceed(srv, client);
    }
}

控制台输出:

Caller: ClientService.getSomething() -> de.scrum_master.app.ClientService@72bcecc0
Callee: Client.getName() -> de.scrum_master.app.Client@515b6c19


更新:好吧,实际上,如果客户端服务直接调用客户端,则不需要使用虫洞模式.仅当调用链较长(介于两者之间的其他类或方法调用)时,才应使用后者.在那种情况下,我的示例代码将失败,因为thisEnclosingJoinPointStaticPart始终会捕获客户端方法调用之外的调用链中的最后一个调用方,而不一定是您感兴趣的控制流开始处的客户端服务入口点.已更新示例代码以显示更通用的解决方案:


Update: Well, actually if the client service directly calls the client you do not need to use a wormhole pattern. The latter should only be used if the call chain is longer (other classes or method calls in between). In that case my sample code would fail because thisEnclosingJoinPointStaticPart would always capture the last caller in the call chain outside the client method call, not necessarily the client service entry point at the beginning of the control flow you are interested in. Thus, I have updated the sample code to show a more generic solution:

客户:与上述相同

新的客户端委托(以引入一些间接性):

package de.scrum_master.app;

public class ClientDelegate {
    private Client client;

    public ClientDelegate(Client client) { this.client = client; }
    public String getName() { return client.getName(); }
    public void setName(String name) { client.setName(name); }
}

使用委托更新了客户端服务:

package de.scrum_master.app;

public class ClientService {
    private ClientDelegate clientDelegate;

    public ClientService(ClientDelegate clientDelegate) { this.clientDelegate = clientDelegate; }
    public String getSomething() { return clientDelegate.getName(); }
    public void setSomething(String something) { clientDelegate.setName(something); }

    public static void main(String[] args) {
        ClientService clientService = new ClientService(new ClientDelegate(new Client()));
        clientService.setSomething("new value");
        clientService.getSomething();
    }
}

更新的方面:

该方面现在不再是sigleton,而是使用percflow()实例化.它还为客户端服务控制流提供了额外的before()建议,将其连接点上下文保存在私有成员serviceContext中.以后需要将其打印到控制台上的信息.

The aspect now is not a sigleton anymore, but uses percflow() instantiation. It also comes with an extra before() advice for the client service control flow, saving its join point context in private member serviceContext. This is needed later in order to print the information to the console.

around()建议中,我还从call()切换到execution(),从target()切换到this(),因为现在我们不再使用thisEnclosingJoinPointStaticPart.

In the around() advice I also switched back from call() to execution() and from target() to this() because now we do not use thisEnclosingJoinPointStaticPart anymore.

package de.scrum_master.aspect;

import org.aspectj.lang.JoinPoint.StaticPart;
import de.scrum_master.app.Client;
import de.scrum_master.app.ClientService;

public aspect MyAspect percflow(serviceExecution(ClientService)) {
    private StaticPart serviceContext;

    pointcut serviceExecution(ClientService srv) :
        execution(* ClientService.*(..)) && this(srv);

    pointcut modelGetter(Client client) :
        execution(public * Client.get*()) && this(client);

    pointcut wormhole(ClientService srv, Client client) :
        cflow(serviceExecution(srv)) && modelGetter(client);

    before(ClientService srv) : serviceExecution(srv) {
        serviceContext = thisJoinPointStaticPart;
    }

    Object around(ClientService srv, Client client) : wormhole(srv, client) {
        System.out.println("Service: " + serviceContext.getSignature().toShortString() + " -> " + srv);
        System.out.println("Client: " + thisJoinPointStaticPart.getSignature().toShortString() + " -> " + client);
        return proceed(srv, client);
    }
}

新控制台输出:

Service: ClientService.getSomething() -> de.scrum_master.app.ClientService@4cc4dfc5
Client: Client.getName() -> de.scrum_master.app.Client@113f25e3

这篇关于虫孔图案w. AspectJ:如何获取调用方方法名称?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

1403页,肝出来的..

09-07 02:47