其他Android开发实战总结终端研发部

Android监测用户行为之中AOP编程之AspectJ实战

2017-07-10  本文已影响136人  goodgleCoder

文章背景

文章目标

看图简单解读Android的AOP实战

看到没有,在LinearLayoutTestActivity中除了加载布局的操作外,我并没有干其他的什么,但当我点击菜单跳转到该Activity时,onCreate的方法和参数被打印出来,甚至LinearLayoutTestActivity类信息也被打印出来了,干这个事情的是TraceAspect这个类。到这里上面所说的用户的行为跟踪就轻而易举得以实现,那么下面我们开始来了解一下这种技术。

什么是AOP

AspectJ是什么

为什么用 AspectJ?

如何Android项目中使用AspectJ

使用方法有两种:

Step

Paste_Image.png

然后运行我们的程序看日志打印效果

上面的代码片段中有两处地方值得注意,一个是把这个类注解为@Aspect,另一个是给方法的的注解并加上了类似正则表达式的过滤条件,我们先按照我的步骤走,后面会一一讲解。

根据图片我们会惊奇的发现LinearLayoutTestActivity中的onCreate(Bundle savedInstanceState)方法被TraceAspect类赤裸裸的监控了,不仅截取到了LinearLayoutTestActivity类信息和方法及方法参数。

那这到底是怎么回事呢?我们可以使用反编译我的apk看一下相关的代码
[图片上传中。。。(6)]

我们可以发现,在onCreate执行之前,插入了一些AspectJ的代码,并且调用了TraceAspect中的 onActivityMethodBefore(JoinPoint joinPoint)方法。这个就是AspectJ的主要功能,抛开AOP的思想来说,我们想做的,实际上就是『在不侵入原有代码的基础上,增加新的代码』。

监控Activity的下其它被调用的方法

看到没有我们仅仅在TraceAspect类中编写一个方法就可以监控RelativeLayoutTestActivity中被用户点击的方法,这样就可以轻轻松松采集用户行

我们还是照样看来看一下反编译的代码
这是在RelativeLayoutTestActivity类中调用testAOP()我们的源码:

public class RelativeLayoutTestActivity extends Activity {

  Button btn_test,btn_test2;
  //public static String A="88888";
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_relative_layout_test);
    btn_test=(Button)findViewById(R.id.btn_test);
    btn_test.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
        testAOP();
      }
    });
    btn_test2=(Button)findViewById(R.id.btn_test2);
    btn_test2.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
          mytestDebug();
      }
    });

  }

  private  void testAOP(){

    int cunt=0;
    for ( int i=0;i<1000;i++){
      cunt++;

    }
    //Log.d("ydc","cunt:"+cunt+"");
  }

  private void method4Call() {
    //System.out.println("in method method4Call");
  }

  @DebugTrace
  private void  mytestDebug(){

  }
}

下面是反编译的代码,读者只要关注testAOP()方法即可

public class RelativeLayoutTestActivity extends Activity
{
  private static final JoinPoint.StaticPart ajc$tjp_0;
  private static final JoinPoint.StaticPart ajc$tjp_1;
  private static final JoinPoint.StaticPart ajc$tjp_2;
  Button btn_test;
  Button btn_test2;

  static
  {
    ajc$preClinit();
  }

  private static void ajc$preClinit()
  {
    Factory localFactory = new Factory("RelativeLayoutTestActivity.java", RelativeLayoutTestActivity.class);
    ajc$tjp_0 = localFactory.makeSJP("method-execution", localFactory.makeMethodSig("4", "onCreate", "com.example.myaspectjapplication.activity.RelativeLayoutTestActivity", "android.os.Bundle", "savedInstanceState", "", "void"), 27);
    ajc$tjp_1 = localFactory.makeSJP("method-execution", localFactory.makeMethodSig("2", "testAOP", "com.example.myaspectjapplication.activity.RelativeLayoutTestActivity", "", "", "", "void"), 48);
    ajc$tjp_2 = localFactory.makeSJP("method-execution", localFactory.makeMethodSig("2", "mytestDebug", "com.example.myaspectjapplication.activity.RelativeLayoutTestActivity", "", "", "", "void"), 63);
  }

  private void method4Call()
  {
  }

  @DebugTrace
  private void mytestDebug()
  {
    JoinPoint localJoinPoint = Factory.makeJP(ajc$tjp_2, this, this);
    TraceAspect.aspectOf().weaveJoinPoint(new RelativeLayoutTestActivity.AjcClosure3(new Object[] { this, localJoinPoint }).linkClosureAndJoinPoint(69648));
  }

  static final void mytestDebug_aroundBody2(RelativeLayoutTestActivity paramRelativeLayoutTestActivity, JoinPoint paramJoinPoint)
  {
  }

  private void testAOP()
  {
    JoinPoint localJoinPoint = Factory.makeJP(ajc$tjp_1, this, this);
    TraceAspect.aspectOf().onActivityMethodAround(new RelativeLayoutTestActivity.AjcClosure1(new Object[] { this, localJoinPoint }).linkClosureAndJoinPoint(69648));
  }

  static final void testAOP_aroundBody0(RelativeLayoutTestActivity paramRelativeLayoutTestActivity, JoinPoint paramJoinPoint)
  {
    int i = 0;
    for (int j = 0; j < 1000; j++)
      i++;
  }

  protected void onCreate(Bundle paramBundle)
  {
    JoinPoint localJoinPoint = Factory.makeJP(ajc$tjp_0, this, this, paramBundle);
    TraceAspect.aspectOf().onActivityMethodBefore(localJoinPoint);
    super.onCreate(paramBundle);
    setContentView(2130903043);
    this.btn_test = ((Button)findViewById(2131230727));
    this.btn_test.setOnClickListener(new View.OnClickListener()
    {
      public void onClick(View paramAnonymousView)
      {
        RelativeLayoutTestActivity.this.testAOP();
      }
    });
    this.btn_test2 = ((Button)findViewById(2131230728));
    this.btn_test2.setOnClickListener(new View.OnClickListener()
    {
      public void onClick(View paramAnonymousView)
      {
        RelativeLayoutTestActivity.this.mytestDebug();
      }
    });
  }
}

我们不难发现我们的代码轻松被AspectJ重构了,而且这种重构是在不修改原有代码的情况下无缝的被插入。

Fragment的中的方法监控

上面我已经演示过Activity中的方法强势插入,在Fragment中依然可行

@Before("execution(* android.app.Fragment.on**(..))")
  public void onActivityMethodBefore(JoinPoint joinPoint) throws Throwable {
    String key = joinPoint.getSignature().toString();
    Log.d(TAG, "onActivityMethodBefore: " + key+"\n"+joinPoint.getThis());
  }
Paste_Image.png

AspectJ原理剖析

****注意这里****

AOP 应用场景非常多。
只要在我们想监控的方法上加上 @DebugTrace即可,我在这里给onMeasure方法上注解,当我进入LinearLayoutTestActivity 类时,运行如下:

项目结果显示

博客地址:

http://blog.csdn.net/xinanheishao/article/details/74082605

最后附上Dome下载地址:

http://download.csdn.net/download/xinanheishao/9886917

提供一个反编译工具:

apk反编译工具下载地址
[http://blog.csdn.net/xinanheishao/article/details/74278192]

相信自己,没有做不到的,只有想不到的

如果你觉得此文对您有所帮助,欢迎入群 QQ交流群 :232203809
微信公众号:终端研发部

技术+职场

(http://blog.csdn.net/xinanheishao/article/details/74278192)

上一篇下一篇

猜你喜欢

热点阅读