AOP之AspectJ简单使用

参考文章:

  1. 使用AspectJ在Android中实现Aop
  2. 深入理解Android之AOP
  3. 自动打印日志

主要知识点:

  1. 主要是JPoint、pointcuts、advice以及他们之间的关系
  2. 可以通过aj文件、或@AspectJ注解的Java文件实现
  3. AspectJ和其他模块交互
  4. 重载方法会多次调用,需要用within限制是基类还是子类。

案例代码,实现自动化埋点:改自gradle-android-aspectj-plugin

activity_my.xml

<com.uphyca.gradle.android.aspectj.CLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/root"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    android:clickable="true"
    tools:context=".MyActivity">

    <TextView
        android:id="@+id/greeting"
        android:layout_width="wrap_content"
        android:layout_height="100dp"
        android:gravity="center"/>

    <TextView
        android:id="@+id/greeting1"
        android:layout_width="wrap_content"
        android:layout_height="100dp"
        android:layout_below="@id/greeting"
        android:text="click me"
        android:gravity="center"/>

    <TextView
        android:id="@+id/greeting2"
        android:layout_width="wrap_content"
        android:layout_height="100dp"
        android:layout_below="@id/greeting1"
        android:text="click me"
        android:gravity="center"/>

</com.uphyca.gradle.android.aspectj.CLinearLayout>

MyActivity.java

public class MyActivity extends AppCompatActivity implements View.OnClickListener{

    @Inject
    Greeter greeter;

    private View.OnClickListener clickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Log.i("aaaaaaaaaaaa", "AppCompatActivity.clickListener");
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ((MyApplication) getApplication()).getComponent().inject(this);
        setContentView(R.layout.activity_my);
        TextView.class.cast(findViewById(R.id.greeting)).setText(greeter.greet());
        TextView.class.cast(findViewById(R.id.greeting)).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                doActivityKisClick(v);
            }
        });

        TextView.class.cast(findViewById(R.id.greeting1)).setOnClickListener(this);
        TextView.class.cast(findViewById(R.id.greeting2)).setOnClickListener(clickListener);

        init();
    }

    private void init()
    {
        Log.i("aaaaaaaaaaaa", "init");
    }

    private void doActivityKisClick(View v)
    {
        Log.i("aaaaaaaaaaaa", "doActivityKisClick");
    }

    @Override
    public void onClick(View v) {
        Log.i("aaaaaaaaaaaa", "MyActivity.onClick");
    }
}

MyAspect.aj

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;


public aspect MyAspect {

    pointcut callGreet() : call(String com.uphyca.gradle.android.aspectj.Greeter+.greet());
    pointcut callInit() : call(private void com.uphyca.gradle.android.aspectj.MyActivity.init());
    /* 不管是匿名OnClickListener还是Activity implements方式,包括Activity、Fragment、自定义View中,都可以匹配*/
    pointcut callClick(android.view.View v) : execution(* android.view.View.OnClickListener.onClick(..)) && args(v);
    /* callClick也匹配了*/
    pointcut callDoClick(android.view.View v) : call(private void com.uphyca.gradle.android.aspectj.MyActivity.doActivityKisClick(android.view.View)) && target(com.uphyca.gradle.android.aspectj.MyActivity) && args(v);
    /* callClick也匹配了*/
    pointcut doCLayoutClick(android.view.View v) : call(private void com.uphyca.gradle.android.aspectj.CLinearLayout.doCKisClick(android.view.View)) && target(com.uphyca.gradle.android.aspectj.CLinearLayout) && args(v);
    /* 匹配所有KisClick结尾的事件, public/private/protect,以及static/final属于可选项。如果不设置它们,则默认都会选择,不需要用*代替 */
    pointcut doAllClick(android.view.View v) : call(* *.*KisClick(android.view.View)) && args(v);

    String around() : callGreet() {
        String result = proceed();
        return result.replace("world", "aspect");
    }

    before() : callInit() {
        android.util.Log.i("aaaaaaaaaaaa", "callInit");
    }

    before(android.view.View v) : callClick(v) {
        android.util.Log.i("aaaaaaaaaaaa", "callClick");
    }

    before(android.view.View v) : callDoClick(v) {
        android.util.Log.i("aaaaaaaaaaaa", "callDoClick");
    }

   before(android.view.View v) : doCLayoutClick(v) {
      android.util.Log.i("aaaaaaaaaaaa", "doCLayoutClick");
   }

    before(android.view.View v) : doAllClick(v) {
      org.aspectj.lang.Signature signature = thisJoinPoint.getSignature();
      String typeName = signature.getDeclaringTypeName();
      String methodName = signature.getName();
      android.util.Log.i("aaaaaaaaaaaa", "DeclaringTypeName: " + typeName + "." + methodName);
   }
}

CLinearlayout.java

public class CLinearLayout extends LinearLayout{

    public CLinearLayout(Context context) {
        this(context, null);
    }

    public CLinearLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        setOrientation(VERTICAL);

        setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                doCKisClick(v);
                doCSecondKisClick(v);
            }
        });
    }

    private void doCKisClick(View v)
    {
        Log.i("aaaaaaaaaaaa", "CLinearLayout.click");
    }

    private void doCSecondKisClick(View v)
    {
        Log.i("aaaaaaaaaaaa", "CLinearLayout.doCSecondKisClick");
    }

}

转载于:https://my.oschina.net/bruces/blog/759962

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值