Android AspectJ 重复织入的问题
程序员文章站
2022-03-26 10:30:11
AspectJ是Android AOP三剑客之一,对于一些面向切面的需求,能提供很好的解决方案。但最近,在使用过程中,发现一个问题,对于切点的织入,不仅仅是...
AspectJ是Android AOP三剑客之一,对于一些面向切面的需求,能提供很好的解决方案。
但最近,在使用过程中,发现一个问题,对于切点的织入,不仅仅是当前类,当前类的子类也会被织入,从而导致重复织入的问题。
比如我们有一个基类BaseActivity
public class BaseActivity extends AppCompatActivity {
@Override
public boolean onCreateOptionsMenu(Menu menu) {
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
return super.onOptionsItemSelected(item);
}
}
有一个主页Activity,继承自BaseActivity
public class MainActivity extends BaseActivity {
@Override
protected void onCreate(@androidx.annotation.Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_home, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.option_normal_1) {
Toast.makeText(MainActivity.this, "Normal1", Toast.LENGTH_SHORT).show();
return true;
}
return super.onOptionsItemSelected(item);
}
}
接着,我们新建一个BaseActivity的切面
@Aspect
public class CheckBackAspect {
@Pointcut("execution(boolean com.heiko.myaspecttest2.BaseActivity.onOptionsItemSelected(..))")
public void methodMyOnOptionsItemSelected() {
}
@Around("methodMyOnOptionsItemSelected()")
public boolean aroundMyOnOptionsItemSelected(ProceedingJoinPoint joinPoint) throws Throwable {
Log.i("CheckBackAspect", "----- methodMyOnOptionsItemSelected -----");
return (boolean) joinPoint.proceed();
}
}
运行程序,点击菜单的时候,会发现日志会被调用两遍。
----- methodMyOnOptionsItemSelected -----
----- methodMyOnOptionsItemSelected -----
这和我们想要的效果是有偏差的,为此,我们打印下joinPoint有哪些参数
@Aspect
public class CheckBackAspect {
@Pointcut("execution(boolean com.heiko.myaspecttest2.BaseActivity.onOptionsItemSelected(..))")
public void methodMyOnOptionsItemSelected() {
}
@Around("methodMyOnOptionsItemSelected()")
public boolean aroundMyOnOptionsItemSelected(ProceedingJoinPoint joinPoint) throws Throwable {
String kind = joinPoint.getKind();
String declaringTypeName = joinPoint.getSignature().getDeclaringTypeName();
String signatureName = joinPoint.getSignature().getName();
String srouceFileName = joinPoint.getSourceLocation().getFileName();
String sourceWithinType = joinPoint.getSourceLocation().getWithinType().getName();
Object target = joinPoint.getTarget();
Log.i("CheckBackAspect", "----- methodMyOnOptionsItemSelected -----");
Log.i("CheckBackAspect", "kind:" + kind);
Log.i("CheckBackAspect", "declaringTypeName:" + declaringTypeName);
Log.i("CheckBackAspect", "signatureName:" + signatureName);
Log.i("CheckBackAspect", "srouceFileName:" + srouceFileName);
Log.i("CheckBackAspect", "sourceWithinType:" + sourceWithinType);
Log.i("CheckBackAspect", "target:" + target);
return (boolean) joinPoint.proceed();
}
}
点击菜单的时候,可以看到
----- methodMyOnOptionsItemSelected -----
kind:method-execution
declaringTypeName:com.heiko.myaspecttest2.MainActivity
signatureName:onOptionsItemSelected
srouceFileName:MainActivity.java
sourceWithinType:com.heiko.myaspecttest2.MainActivity
target:com.heiko.myaspecttest2.MainActivity@8f6cec4
----- methodMyOnOptionsItemSelected -----
kind:method-execution
declaringTypeName:com.heiko.myaspecttest2.BaseActivity
signatureName:onOptionsItemSelected
srouceFileName:BaseActivity.java
sourceWithinType:com.heiko.myaspecttest2.BaseActivity
target:com.heiko.myaspecttest2.MainActivity@8f6cec4
可以看到,我们可以通过declaringTypeName
或sourceWithinType
来判断一下,拦截掉不需要的切面执行。
@Aspect
public class CheckBackAspect {
@Pointcut("execution(boolean com.heiko.myaspecttest2.BaseActivity.onOptionsItemSelected(..))")
public void methodMyOnOptionsItemSelected() {
}
@Around("methodMyOnOptionsItemSelected()")
public boolean aroundMyOnOptionsItemSelected(ProceedingJoinPoint joinPoint) throws Throwable {
String declaringTypeName = joinPoint.getSignature().getDeclaringTypeName();
if ("com.heiko.myaspecttest2.BaseActivity".equals(declaringTypeName)) {
Log.i("CheckBackAspect", "执行onOptionsItemSelected切面");
//执行了BaseActivity的onOptionsItemSelected切面
//这里可以进行相关业务逻辑...
return (boolean) joinPoint.proceed();
}else{
//对其他子类的切面,不进行操作
return (boolean) joinPoint.proceed();
}
}
}
我们再来运行下程序,点击菜单,可以看到,只打印了如下日志
执行onOptionsItemSelected切面
至此,我们就解决了切面重复织入的问题了。
本文地址:https://blog.csdn.net/EthanCo/article/details/109583110
上一篇: 青藏川藏行 险途万里
下一篇: “58速运”改名“快狗”引发争议
推荐阅读
-
Android开发中如何解决Fragment +Viewpager滑动页面重复加载的问题
-
Android中解决第三方库重复引用的问题
-
Android AspectJ 重复织入的问题
-
android跑马灯出现重复跳动以及不滚动问题的解决方法
-
Android解决---第三方库重复引用造成的 java.lang.NoSuchMethodError问题
-
Spring-AOP @AspectJ进阶之增强织入的顺序
-
Android开发中如何解决Fragment +Viewpager滑动页面重复加载的问题
-
Android AspectJ 重复织入的问题
-
android跑马灯出现重复跳动以及不滚动问题的解决方法
-
Android解决---第三方库重复引用造成的 java.lang.NoSuchMethodError问题