如何在使用加载时间编织(AspectJ)获取参数时配置aop.xml?

时间:2014-09-11 14:07:48

标签: aspectj load-time

我想从HBase那里得到一些东西。使用AspectJ的加载时间编织。我编写了AbstractAspect.aj和aop.xml.I也尝试使用“ajc -outxml AbstractAspect.aj”来生成aop.xml,它太简单了,无法得到方法的参数。我怀疑道路(LTW)是否可以得到上下文。

AbstractAspect.aj:

package com.test.apectj.aj;

import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.GetRequest;
import com.google.protobuf.RpcController;

public abstract aspect AbstractAspect {

    pointcut scan();

    pointcut multi();

    pointcut getdata(final RpcController controller, final GetRequest request): target(org.apache.hadoop.hbase.protobuf.generated.ClientProtos) && call (public * org.apache.hadoop.hbase.regionserver.HRegionServer.get(RpcController, GetRequest)) && args(controller, request);

    pointcut scope();

    before() : scan() {
      System.out.println("[aop]before methon scan()");
      System.out.println(thisEnclosingJoinPointStaticPart);
      System.out.println(thisJoinPoint.getSourceLocation());
    }

    before() : multi() {
      System.out.println("[aop]before methon multi()");
      System.out.println("[aop]Execute multiple actions on a table: get,                        
                          mutate,and/orexecCoprocessor");
    }

    after() : multi(){
      System.out.println("[aop]after methon multi()");
    }

    before(RpcController controller, GetRequest request) : getdata(controller, request)                   
    {

      System.out.println("[aop]before methon get()");
      System.out.println("[aop]Get data from a table");
      System.out.println(request.toString());
    }

}

aop.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
    <aspectj>
        <aspects>
            <concrete-aspect name="com.test.apectj.aj.ConcreteAspect"
                extends="com.test.apectj.aj.AbstractAspect">
                <pointcut name="scan"
                    expression="execution(public * org.apache.hadoop.hbase.regionserver.HRegionServer.scan(com.google.protobuf.RpcController, org.apache.hadoop.hbase.protobuf.generated.ClientProtos.ScanRequest)) AND target(org.apache.hadoop.hbase.regionserver.HRegionServer)" />
                <pointcut name="multi"
                    expression="execution(public * org.apache.hadoop.hbase.regionserver.HRegionServer.multi(..)) AND target(org.apache.hadoop.hbase.regionserver.HRegionServer)" />
                <pointcut name="getdata()"
                    expression="call(public * org.apache.hadoop.hbase.regionserver.HRegionServer.get(..))" />
            </concrete-aspect>
        </aspects>


        <weaver options="-verbose -Xset:weaveJavaxPackages=true">
        </weaver>

    </aspectj>
跑步时

  • 没有参数[pointcut:scan()multi()]:成功。可以打印信息
  • 有参数[pointcut:getdata()]:失败。像这样警告:......
[AppClassLoader@4d97507c] warning at com/test/apectj/aj/E:\EclipseWorkspace\hbase-regionserver-aop\src\com\test\apectj\aj\AbstractAspect.aj:25::0 does not match because declaring type is org.apache.hadoop.hbase.protobuf.generated.ClientProtos$ClientService$BlockingInterface, if match desired use target(org.apache.hadoop.hbase.regionserver.HRegionServer) 
[Xlint:unmatchedSuperTypeInCall]
see also: org/apache/hadoop/hbase/protobuf/generated/ClientProtos.java:28857::0

如果mothod不是抽象的,那么在使用这种机制时,只能实现一个简单的抽象切入点。

我的问题是这种方式是否可以获取参数?如果可能,如何配置。

1 个答案:

答案 0 :(得分:1)

您的aop.xml定义了一个具体方面,为两个抽象基本方面切入点scan()multi()提供切入点。到现在为止还挺好。但是你想用切入点getdata(final RpcController controller, final GetRequest request)做什么?它已在基本方面具体定义,具有两个参数以及参数绑定。看来你试图重新定义它(同名),没有任何参数和另一个目标。这没有意义,如果您不自己定义参数绑定并覆盖现有参数绑定,那么您如何期望参数绑定(如果可能的话,我从未尝试过)?

更新:我忘了提及警告信息的含义:

pointcut getdata(final RpcController controller, final GetRequest request):
    target(org.apache.hadoop.hbase.protobuf.generated.ClientProtos) &&
    call (public * org.apache.hadoop.hbase.regionserver.HRegionServer.get(RpcController, GetRequest)) &&
    args(controller, request);

如果将目标类型ClientProtos与截获的目标方法HRegionServer.get(..)进行比较,您会发现存在矛盾:目标对象不能具有类型ClientProtos,它必须是HRegionServer因为您正在拦截该类的方法。 AspectJ非常友好地告诉你。

逻辑上,this(Foo) && call(* Bar.blah(..))是可能的,因为调用者类型可能与被调用者类型不同,但target(Foo) && call(* Bar.blah(..))没有意义,因为生成的连接点集将始终为空,因为call(* Bar.blah(..))始终表示目标类型必须为Bar