AOP埋点从入门到放弃(三)

2,023 阅读5分钟

前两篇文章已经很好的说明了AOP的使用方式,但是话说回来了,在项目中有什么卵用?能帮到我平时开发吗?

其实我就喜欢这么直接的朋友,其实一开始的时候我也是这么觉得的!我花了这么长时间学习这个东西到底有什么卵用?但是后来我渐渐的发现这个东西还是挺有用的,平时能帮助到我们节省很多代码的!好了,废话不多说直接说说这个东西在项目中到底有什么卵用!!!

一张复仇者联盟镇楼(感兴趣的我可以发你)!皮一下就是这么开森。。。

AspectJ在项目中的卵用

  • 解决一些判断条件登录的问题;
  • 解决一些埋点的问题;
  • 还有些就有待于发现了...

1. 解决一些判断条件登录的问题

不知道大家在项目中有没有这样的需求?APP有些内容是需要登录才能继续向下走的,这个时候你需要先判断用户是否登录,然后再能往下走,这个需求很常见。但是如果有了AOP这个框架的话,再也不用if/else了,也不用在每一地方都if/else了。

好了,实现的效果说完了,那么我们开始装逼吧!!!

对于这个需求,如果之前你看了上两篇文章的话,那么这个需求就可以说是so easy了,我们看看怎么实现的吧!

1.1 首先你需要一个注解,是长这样的!

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

这就是一个注释在方法上的注解!!!仅此而已。。。

1.2 写相应的切面方法。

先来看下代码,然后我们在讲解

@Aspect
public class LoginAspect {
    private static final String TAG = LoginAspect.class.getSimpleName();

    @Around("execution(@com.jinlong.aspectjdemo.CheckLogin * *(..))")
    public Object beforeDebugTraceMethod(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();

        Method method = signature.getMethod();
        Log.e(TAG, "beforeDebugTraceMethod: " + method.toString());

        //获取上下文的方法
        Context context = (Context) joinPoint.getThis();

        if (APP.isIsLogin()) {
            return joinPoint.proceed();
        } else {
            Intent intent = new Intent(context, MainActivity.class);
            context.startActivity(intent);
            return null;
        }
    }
}

说明几点问题:

  • 通配符:这个我不讲了,上一篇博客已经讲解了,如果有什么不理解的,可以看看AOP埋点从入门到放弃(二) 这篇文章!
  • 其实我主要想说的就是里面的这些判断的代码**Context context = (Context) joinPoint.getThis();**其实这里返回的是当前执行的对象,有可能是空的,因为我是在Activity中执行的点击时间,所以这里强转成上下文是没问题的,但是如果你要是写在Fragment的话,就要在获取一下了!
  • 这里其实是可以传递相应的数据的,但是只能是相应的基本的数据方式String、int 等;怎么传递呢?这个就涉及到注解的问题了,所以这里只贴出相应的代码了,不再本文的讲解中!!!

首先注解编程这个样子了:就是添加了一个相应传递的值。

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface CheckLoginDefault {
    String param1() default "";
}

然后看怎么获取?

    @Around("execution(@com.jinlong.aspectjdemo.CheckLoginDefault * *(..))")
    public void beforeDebugCheckLogin(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();

        Method method = signature.getMethod();
        CheckLoginDefault annotation = method.getAnnotation(CheckLoginDefault.class);

        Log.e(TAG, "注解传递的值为:" + annotation.param1());

        Context context = (Context) joinPoint.getThis();

        Toast.makeText(context, "注解传递的值为\n" + annotation.param1(), Toast.LENGTH_SHORT).show();
    }

里面注解传递的值为:Log打印出来的值。这里由于没有执行之前方法的内容,所以不会打印前面方法的Toast了!

最后看看怎么用?

    @CheckLoginDefault(param1 = "token")
    public void checkLoginDefault(View view) {
        Toast.makeText(this, "执行下一步操作", Toast.LENGTH_SHORT).show();
    }

通过param1添加相应的参数就可以了,这样你就可以在点击的时候进行相应的处理了!!!

2. 解决项目中的埋点问题

首先确定好一个问题,你们项目埋点要埋些什么东西?比如点击事件,或者方法的执行时间?这些都是比较简单的内容,但是如果你要在某个点击事件的时候,还想获取相应的内容,这个时候就比较复杂了,怎么说呢?因为注解只能传递相应的基本类型参数(也可能是我自己的只是层面有限),所以这里存在一定的问题?什么样的问题呢?埋点的时候,怎么区分这些类型,只有在你传的时候区分了,添加注解的时候去区分,就没有然后了。至于其他的一些内容,看你们产品需要什么,需要什么埋什么! 这里就直接上两个简单的例子吧!

2.1 相应方法的埋点

    @Before("execution(* android.app.Activity.on*(..))")
    public void onActivityMethodBefore(JoinPoint joinPoint) {
        String key = joinPoint.getSignature().toString();
        Log.e(TAG, "onActivityMethodBefore: 切面的点执行了!" + key);
    }

2.2 相应方法的执行时间

    @Around("call(* com.jinlong.aspectjdemo.MainActivity.callMethod(..))")
    public void aroundCallMethod(ProceedingJoinPoint joinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();
        joinPoint.proceed();
        long endTime = System.currentTimeMillis();
        Log.e(TAG, "方法执行的时间为" + (endTime - startTime));
    }

这里就不详细讲解了!细节前面都讲了。至于埋点东西多的话,可以参照上面那个传递参数的,总之怎么简单怎么来!!!


除了AOP实现6.0以上权限的内容,基本上项目中就这些使用的地方,因为最近公司开了一个新项目,所以比较忙,没有时间去看关于权限的问题!其实关于AOP实现6.0以上权限的内容,很多的内容都要讲,估计没有时间细看,所以等忙完这个项目后,我会仔细看一下给伙伴们讲,如果现在讲的话,怕有些地方讲错了,对不起广大小伙伴!!!