为何想到AOP
AOP
项目完整代码
如何接入
AspectJ
具体实现
自定义切点
切面
使用如何
获取切点中的自定义的值
如何获取方法中的参数
反编译结果
为何想到AOP
在移动端开发中,我们总能遇到这样的需求:跳转到下一个界面前判断一下用户的登陆状态,若登陆了,则跳转到下一界面,否则,跳转到登陆界面。Activity跳转代码我们肯定是烂熟于心的。
if(isLogin){ Intent intent = new Intent(context,NextActivity); startActivity(intent); }else{ Intent intent = new Intent(context,LoginActivity); startActivity(intent); }
搞定。若是项目只有几个Activity的话,这样写完全没什么问题,但是,一旦我们的项目有几十个Activity的话。。。再加上后续如果需要网络判断啊,Log啊之类的需求
FKarLCRo.jpg
要是有什么黑科技像把刀一样每次跳转前切开代码把这些前置逻辑判断自动添加进去就好了。
嘿嘿嘿,这还真的有,面向切面编程AOP!
AOP
AOP是通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。
AOP可以对所谓的业务逻辑进行隔离,让你更加心无旁骛的专注于你该专注的模块。
关于AOP的相关概念这里不做多的讲解,Google上都有,我们直接以一个Demo来实现我们上述的需求。
项目完整代码
https://github.com/KKaKa/AopDemo 欢迎Star
如何接入AspectJ
build.gradle
dependencies { .... classpath 'org.aspectj:aspectjtools:1.8.9' classpath 'org.aspectj:aspectjweaver:1.8.9' }
build.gradle(app)
implementation 'org.aspectj:aspectjrt:1.8.9'
添加gradle脚本( 在build.gradle(app)中 )
final def log = project.logger final def variants = project.android.applicationVariants variants.all { variant -> if (!variant.buildType.isDebuggable()) { log.debug("Skipping non-debuggable build type '${variant.buildType.name}'.") return; } JavaCompile javaCompile = variant.javaCompile javaCompile.doLast { String[] args = ["-showWeaveInfo", "-1.8", "-inpath", javaCompile.destinationDir.toString(), "-aspectpath", javaCompile.classpath.asPath, "-d", javaCompile.destinationDir.toString(), "-classpath", javaCompile.classpath.asPath, "-bootclasspath", project.android.bootClasspath.join(File.pathSeparator)] log.debug "ajc args: " + Arrays.toString(args) MessageHandler handler = new MessageHandler(true); new Main().run(args, handler); for (IMessage message : handler.getMessages(null, true)) { switch (message.getKind()) { case IMessage.ABORT: case IMessage.ERROR: case IMessage.FAIL: log.error message.message, message.thrown break; case IMessage.WARNING: log.warn message.message, message.thrown break; case IMessage.INFO: log.info message.message, message.thrown break; case IMessage.DEBUG: log.debug message.message, message.thrown break; } } } }
具体实现
大致分为三个步骤:
自定义切点
完成切面
对需要的方法添加注解
自定义切点
@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface CheckLogin { }
这里我们切点应用于方法,所以Target使用ElementType.METHOD。
切点中可以添加参数
@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface CheckLogin { String param(); }
切面
@Aspectpublic class CheckLoginAspectJ { private static final String TAG = "CheckLoginAspectJ"; @Pointcut("execution(@com.laizexin.sdj.aopdemo.aspectj.CheckLogin * *(..))") public void pointCut(){ } @Before("pointCut()") public void before(JoinPoint point){ Log.i(TAG,"CheckLoginAspectJ.before"); } @Around("pointCut()") public Object checkLogin(ProceedingJoinPoint joinPoint) throws Throwable{ ...判断是否登录 return joinPoint.proceed(); } @After("pointCut()") public void after(JoinPoint point){ Log.i(TAG,"CheckLoginAspectJ.after"); } @AfterThrowing(value = "pointcut()", throwing = "ex") public void afterThrowing(Throwable ex) { Log.i(TAG,"CheckLoginAspectJ.afterThrowing.ex = " + ex.getMessage()); } }
@Pointcut("execution(@com.laizexin.sdj.aopdemo.aspectj.CheckLogin * *(..))")
这里的路径要指向自己项目中的切点。
使用
@CheckLogin(param = "content")private void toNextActivity(Context context,boolean isLogin) { Log.i("CheckLoginAspectJ","toNextActivity"); }
如何获取切点中的自定义的值
MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); CheckLogin checkLogin = method.getAnnotation(CheckLogin.class);String content = checkLogin.param();
如何获取方法中的参数
for(Object obj : joinPoint.getArgs()){ //遍历获取值 .... }
反编译结果
@CheckLogin(param="content")private void toNextActivity(Context paramContext, boolean paramBoolean){ JoinPoint localJoinPoint = Factory.makeJP(ajc$tjp_0, this, this, paramContext, Conversions.booleanObject(paramBoolean)); try { CheckLoginAspectJ.aspectOf().before(localJoinPoint); toNextActivity_aroundBody1$advice(this,paramContext, paramBoolean,localJoinPoint,CheckLoginAspectJ.aspectOf(), (ProceedingJoinPoint)localJoinPoint); CheckLoginAspectJ.aspectOf().after(localJoinPoint); return; } catch (java.lang.Throwable paramContext) { CheckLoginAspectJ.aspectOf().after(localJoinPoint); } throw paramContext; }
作者:益力多不多
链接:https://www.jianshu.com/p/3d11ff8e298c
共同学习,写下你的评论
评论加载中...
作者其他优质文章