美文网首页
AOP面向切面编程-AspectJ-让相同逻辑代码更易维护管理的

AOP面向切面编程-AspectJ-让相同逻辑代码更易维护管理的

作者: _风听雨声 | 来源:发表于2020-04-04 20:23 被阅读0次

    现象:

    打开京东/淘宝APP,断开网络连接,发现点击没有任何反应。我们简单猜想一下,他们是怎么做的呢?


    一般实现方式:
        @Override
        public void onClick(View view) {
            switch (view.getId()) {
                case R.id.checkNet_tv:
                    if (!NewWorkUtils.isNetworkConnected(this)) {
                        return;
                    }
                    Intent intent = new Intent(MainActivity.this, OtherActivity.class);
                    startActivity(intent);
                    break;
            }
        }
    

    稍微看下上面的这一段代码,主要逻辑是通过判断网络是否可用,不可用就return,可用才继续往下走。这样显然是可以实现无网络状态时点击无反应这个需求的。但是在项目中,需要判断有网络状态才可以进入下一步的按钮,可能是几十个或者更多呢?每一个都需要写一段相同的逻辑判断一遍吗?如果有几十个都需要相同判断逻辑的按钮,项目中的相同代码会非常多,又或者这里的需求变更,需要改逻辑的位置会非常多,增加代码维护的成本。


    那有没有更好的实现方式呢?
    答案是有的
    接下来插入剧情…
        @CheckNet
        @Override
        public void onClick(View view) {
            switch (view.getId()) {
                case R.id.checkNet_tv:
                    Intent intent = new Intent(MainActivity.this, MainActivity.class);
                    startActivity(intent);
                    break;
            }
        }
    

    相比原来的代码,多了一个注解

    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface CheckNet {
    }
    

    注解简单理解就是给程序看的一个标签,使用@interface来定义一个注解,注解里面也可以声明变量。声明注解必须声明这个注解的作用域和作用阶段,也就是Target和Retention。常用的Target有ElementType.TYPE,ElementType.FLELD,ElementType.METHOD,分别代表作用在类、成员变量、方法上。常用的Retention有RetentionPolicy.CLASS,Retention.RUNTIME,Retention.SOURCE,分别代表编译阶段,运行阶段,编码阶段。RetentionPolicy.CLASS,Retention.RUNTIME使用的频率会更高一点,Retention.SOURCE常见的注解有@Override。

    @Aspect
    public class CheckNetAspect {
        @Pointcut("execution(@com.demo.checknetdemo.CheckNet * * (..))")
        public void onCheckNet() {
        }
    
        @Around("onCheckNet()")
        public void handleCheckNet(ProceedingJoinPoint joinPoint) throws Throwable {
            Object object = joinPoint.getThis();
            Context context = getContext(object);
            if (context != null) {
                if (!isNetworkConnected(context)) {
                    return;
                }
            }
            joinPoint.proceed();
        }
    
        private Context getContext(Object object) {
            if (object instanceof Activity) {
                return (Activity) object;
            } else if (object instanceof Fragment) {
                return ((Fragment) object).getContext();
            } else if (object instanceof View) {
                return ((View) object).getContext();
            }
            return null;
        }
    
        private boolean isNetworkConnected(Context context) {
            if (context != null) {
                ConnectivityManager mConnectivityManager = (ConnectivityManager) context
                        .getSystemService(Context.CONNECTIVITY_SERVICE);
                NetworkInfo mNetworkInfo = mConnectivityManager.getActiveNetworkInfo();
                if (mNetworkInfo != null) {
                    return mNetworkInfo.isAvailable();
                }
            }
            return false;
        }
    }
    

    @Aspect代表这是一个切面的处理类

        @Pointcut("execution(@com.demo.checknetdemo.CheckNet * * (..))")
        public void onCheckNet() {
        }
    

    @Pointcut代表一个切点,("execution(@com.demo.checknetdemo.CheckNet * * (..))")代表的是切点的完整的路径,后面的* *(..)是一种固定格式,相当于导包时路径后面跟的 *一样。

        @Around("onCheckNet()")
        public void handleCheckNet(ProceedingJoinPoint joinPoint) throws Throwable {
            Object object = joinPoint.getThis();
            Context context = getContext(object);
            if (context != null) {
                if (!isNetworkConnected(context)) {
                    return;
                }
            }
            joinPoint.proceed();
        }
    

    @Around("onCheckNet()")表示这里是针对切面的处理函数,使用@Around注解可以决定函数是否可以往下执行。joinPoint.proceed()表示让函数继续往下执行。这里常用的注解还有@Before,@After,分别代表要把这段代码插入到原方法的前面还是后面。


    总结:

    AOP面向切面编程是一种编程思想,这种编程方式的存在能使我们的代码更易维护管理。可以使用的场景有很多,如防多次点击、上传埋点、网络判断、权限申请..等等。AspectJ是AOP的一种实现方式。还有APT,Javassist..等等。

    相关文章

      网友评论

          本文标题:AOP面向切面编程-AspectJ-让相同逻辑代码更易维护管理的

          本文链接:https://www.haomeiwen.com/subject/dzwjphtx.html