参考文章:
主要知识点:
- 主要是JPoint、pointcuts、advice以及他们之间的关系
- 可以通过aj文件、或@AspectJ注解的Java文件实现
- AspectJ和其他模块交互
- 重载方法会多次调用,需要用within限制是基类还是子类。
案例代码,实现自动化埋点:改自:
activity_my.xml
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"); }}