AOP面向切面编程

﹏ヽ暗。殇╰゛Y 2022-06-09 11:12 429阅读 0赞

AOP 面向切面编程

1.使用场景还原

当我们打开京东 app 进入首页,如果当前是没有网络的状态,里面的按钮点击是没有反应的。只有当我们打开网络的情况下,点击按钮才能跳转页面.按照我们一般人写代码的逻辑应该是这个样子:

  1. /** * 跳转到待收货页面 */
  2. public void jumpWaitReceiving() {
  3. // 判断当前有没有网络
  4. if(CheckNetUtil.isNetworkAvailable(this)) {
  5. // 当前有网络我才跳转,进入待收货页面
  6. Intent intent = new Intent(this, WaitReceivingActivity.class);
  7. startActivity(intent);
  8. }
  9. }
  10. /** * 跳转到我的钱包页面 */
  11. public void jumpMineWallet() {
  12. if(CheckNetUtil.isNetworkAvailable(this)) {
  13. Intent intent = new Intent(this, MineWalletActivity.class);
  14. startActivity(intent);
  15. }
  16. }

分析:当然,上面只有2个按钮,也就只检测了2次,写了2次网络监测,但是如果项目中的其他很多地方(几十处几百处)需要用到网络监测的话,就非常麻烦了,需要重复写很多次上面的if条件.而且这仅仅是网络监测,万一要需要在这里加入网络埋点、友盟统计、日志打印、日志上传、登录判断,权限判断等等。那就更加麻烦了,需要重复写的地方更多。

2.在Android Studio中引入AspectJ

在项目的根目录的build.gradle文件中添加依赖,修改后文件如下

  1. repositories {
  2. jcenter()
  3. }
  4. dependencies {
  5. classpath 'com.android.tools.build:gradle:2.3.0'
  6. classpath 'com.hujiang.aspectjx:gradle-android-plugin-aspectjx:1.0.8'
  7. // NOTE: Do not place your application dependencies here; they belong
  8. // in the individual module build.gradle files
  9. }

然后在项目或者库的build.gradle文件中添加AspectJ的依赖

  1. compile 'org.aspectj:aspectjrt:1.8.9'

同时在该文件中加入AspectJX模块

  1. apply plugin: 'android-aspectjx'

3.AOP 偷懒式网络访问

  1. /** * 跳转到待收货页面 */
  2. @CheckNet
  3. public void jumpWaitReceiving() {
  4. Intent intent = new Intent(this, WaitReceivingActivity.class);
  5. startActivity(intent);
  6. }
  7. /** * 跳转到我的钱包页面 */
  8. @CheckNet
  9. public void jumpMineWallet() {
  10. Intent intent = new Intent(this, MineWalletActivity.class);
  11. startActivity(intent);
  12. }

上面我只是加了1个注解,就实现了执行方法前的网络监测(其实还需要写下面的SectionNetAspect)。
这个注解是我自己写的,如下:

  1. @Retention(RetentionPolicy.RUNTIME)
  2. public @interface CheckNet {
  3. }

这里,解释一下,上面的Retention,首先要明确生命周期长度 SOURCE < CLASS < RUNTIME ,所以前者能作用的地方后者一定也能作用。一般如果需要在运行时去动态获取注解信息,那只能用 RUNTIME 注解;如果要在编译时进行一些预处理操作,比如生成一些辅助代码(如 ButterKnife),就用 CLASS注解;如果只是做一些检查性的操作,比如 @Override 和 @SuppressWarnings,则可选用 SOURCE 注解。

有了这个注解之后,就可以写到需要监测网络的地方,然后再写处理网络监测切面。其实就是在工程里面建一个类,随便放在哪里都行,随便什么名字都可以。

  1. /** * author feiyang * create at 2017/9/4 16:23 * description:处理网络监测切面 */
  2. @Aspect
  3. public class SectionNetAspect {
  4. private static final String TAG = "SectionNetAspect";
  5. /** * 找到处理的切点 * * *(..) 可以处理所有的方法 */
  6. @Pointcut("execution(@com.xfhy.aspectjdemo.CheckNet * *(..))")
  7. public void checkNetBehavior() {
  8. }
  9. /** * 处理切面 */
  10. @Around("checkNetBehavior()")
  11. public Object checkNet(ProceedingJoinPoint joinPoint) throws Throwable {
  12. Log.e(TAG, "checkNet");
  13. //做埋点 日志上传 权限监测
  14. //网络监测
  15. //1. 获取CheckNet注解 NDK 图片压缩 C++调用Java方法
  16. MethodSignature signature = (MethodSignature) joinPoint.getSignature();
  17. CheckNet checkNet = signature.getMethod().getAnnotation(CheckNet.class);
  18. if (checkNet != null) {
  19. //2. 判断有没有网络
  20. Log.e(TAG, "判断有没有网络");
  21. Object object = joinPoint.getThis();
  22. Context context = getContext(object);
  23. if (!isNetworkAvailable(context)) {
  24. // 3.没有网络不要往下执行
  25. Toast.makeText(context, "请检查您的网络", Toast.LENGTH_SHORT).show();
  26. return null;
  27. }
  28. }
  29. //继续下一个注解那里去执行
  30. return joinPoint.proceed();
  31. }
  32. private Context getContext(Object object) {
  33. if (object instanceof Activity) {
  34. return (Activity) object;
  35. } else if (object instanceof Fragment) {
  36. return ((Fragment) object).getActivity();
  37. } else if (object instanceof View) {
  38. return ((View) object).getContext();
  39. }
  40. return null;
  41. }
  42. /** * 检查当前网络是否可用 * * @return */
  43. private static boolean isNetworkAvailable(Context context) {
  44. // 获取手机所有连接管理对象(包括对wi-fi,net等连接的管理)
  45. ConnectivityManager connectivityManager = (ConnectivityManager)
  46. context.getSystemService(Context.CONNECTIVITY_SERVICE);
  47. if (connectivityManager != null) {
  48. // 获取NetworkInfo对象
  49. NetworkInfo[] networkInfo = connectivityManager.getAllNetworkInfo();
  50. if (networkInfo != null && networkInfo.length > 0) {
  51. for (int i = 0; i < networkInfo.length; i++) {
  52. // 判断当前网络状态是否为连接状态
  53. if (networkInfo[i].getState() == NetworkInfo.State.CONNECTED) {
  54. return true;
  55. }
  56. }
  57. }
  58. }
  59. return false;
  60. }
  61. }

现在好了,把上面这个类放到项目中,即可在需要的地方加入 @CheckNet,即可监测是否有网络。简单吧,very nice。

参考文章
http://blog.csdn.net/z240336124/article/details/77750874

发表评论

表情:
评论列表 (有 0 条评论,429人围观)

还没有评论,来说两句吧...

相关阅读

    相关 面向切面编程AOP

    1. 定义 AOP意为:[面向切面编程][Link 1],通过[预编译][Link 2]方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP可以对业务逻辑的各...

    相关 AOP面向切面编程

    [1.引言][1.]         原文地址:[点击打开链接][1.] 软件开发的目标是要对世界的部分元素或者信息流建立模型,实现软件系统的工程需要将系统分解成可以创

    相关 AOP面向切面编程

    AOP 面向切面编程 1.使用场景还原 当我们打开京东 app 进入首页,如果当前是没有网络的状态,里面的按钮点击是没有反应的。只有当我们打开网络的情况下,点击按钮

    相关 AOP面向切面编程简介

           AOP这个词相信大家都没有接触太多过,但是实际上你们已经有所接触了,就在设计模式中。AOP所用的思想其实和设计模式是一样的,即在不修改原代码的情况下统一增加或者修