成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Android高手進階:性能調優hugo中全面分析AOP切面編程使用詳解

移動開發 Android
AOP 能夠實現將日志紀錄,性能統計,埋點統計,安全控制,異常處理等代碼從具體的業務邏輯代碼中抽取出來,放到統一的地方進行處理。

[[411233]]

前言

Android 性能調優中,通常存在需要對方法的執行時間進行統計的需求,這樣就可以看出哪些方法耗時多,是系統的瓶頸。最容易想到的方案是在每個方法的開頭處獲取系統時間,在方法的結尾處再次獲取系統時間,前后兩個時間戳的差值就是這個方法執行所消耗的總時間;

Hugo項目是一個調試函數調用耗時的工具,通過對方法或者類添加@DebugLog注解,在運行時會將函數的耗時打印在控制臺中,通常用于排查函數耗時,或者用于卡頓檢測;

hugo 這個框架麻雀雖小但五臟俱全,它使用了很多 Android 開發中流行的技術,例如注解,AOP,AspectJ,Gradle 插件;

一、hugo插件詳解

1、hugo使用

hugo 以 gradle 插件的形式供開發者集成和使用,分為兩步:

  • 在項目全局添加對 hugo 插件的依賴
  • 在需要使用 hugo 的 module 中應用 hugo 插件
  1. buildscript { 
  2.   repositories { 
  3.     mavenCentral() 
  4.   } 
  5.   dependencies { 
  6.     classpath 'com.jakewharton.hugo:hugo-plugin:1.2.1' // 添加 Hugo 的 Gradle 插件依賴 
  7.   } 
  1. apply plugin: 'com.jakewharton.hugo' // 應用 Hugo 插件 

2、hugo源碼分析

①aspectjrt.jar:aspectJ 運行時的依賴庫,想要使用 aspectJ 的功能都需要引入這個庫;

hugo-annotations:hugo 的注解庫,定義了 DebugLog 這個注解;

  1. @Target({TYPE, METHOD, CONSTRUCTOR}) @Retention(CLASS) 
  2. public @interface DebugLog { 

②hugo-runtime:hugo 的運行時庫,是實現 hugo 日志功能的核心庫;

③hugo-plugin:hugo 的插件庫,主要實現了aop的插件;

  1. class HugoPlugin implements Plugin<Project> { 
  2.   @Override void apply(Project project) { 
  3.     def hasApp = project.plugins.withType(AppPlugin) 
  4.     def hasLib = project.plugins.withType(LibraryPlugin) 
  5.     if (!hasApp && !hasLib) { 
  6.       throw new IllegalStateException("'android' or 'android-library' plugin required."
  7.     } 
  8.     final def log = project.logger 
  9.     final def variants 
  10.     if (hasApp) { 
  11.       variants = project.android.applicationVariants 
  12.     } else { 
  13.       variants = project.android.libraryVariants 
  14.     } 
  15.     project.dependencies { 
  16.       debugCompile 'com.jakewharton.hugo:hugo-runtime:1.2.2-SNAPSHOT' 
  17.       // TODO this should come transitively 
  18.       debugCompile 'org.aspectj:aspectjrt:1.8.6' 
  19.       compile 'com.jakewharton.hugo:hugo-annotations:1.2.2-SNAPSHOT' 
  20.     } 
  21.     project.extensions.create('hugo', HugoExtension) 
  22.     variants.all { variant -> 
  23.       if (!variant.buildType.isDebuggable()) { 
  24.         log.debug("Skipping non-debuggable build type '${variant.buildType.name}'."
  25.         return
  26.       } else if (!project.hugo.enabled) { 
  27.         log.debug("Hugo is not disabled."
  28.         return
  29.       } 
  30.       JavaCompile javaCompile = variant.javaCompile 
  31.       javaCompile.doLast { 
  32.         String[] args = [ 
  33.             "-showWeaveInfo"
  34.             "-1.5"
  35.             "-inpath", javaCompile.destinationDir.toString(), 
  36.             "-aspectpath", javaCompile.classpath.asPath, 
  37.             "-d", javaCompile.destinationDir.toString(), 
  38.             "-classpath", javaCompile.classpath.asPath, 
  39.             "-bootclasspath", project.android.bootClasspath.join(File.pathSeparator) 
  40.         ] 
  41.         log.debug "ajc args: " + Arrays.toString(args) 
  42.         MessageHandler handler = new MessageHandler(true); 
  43.         new Main().run(args, handler); 
  44.         for (IMessage message : handler.getMessages(nulltrue)) { 
  45.           switch (message.getKind()) { 
  46.             case IMessage.ABORT: 
  47.             case IMessage.ERROR: 
  48.             case IMessage.FAIL: 
  49.               log.error message.message, message.thrown 
  50.               break; 
  51.             case IMessage.WARNING: 
  52.               log.warn message.message, message.thrown 
  53.               break; 
  54.             case IMessage.INFO: 
  55.               log.info message.message, message.thrown 
  56.               break; 
  57.             case IMessage.DEBUG: 
  58.               log.debug message.message, message.thrown 
  59.               break; 
  60.           } 
  61.         } 
  62.       } 
  63.     } 
  64.   } 

3、代碼實操

需要進行日志記錄的類名或者方法名處使用 @DebugLog 注解標記即可;

  1. @Override 
  2. protected void onCreate(Bundle savedInstanceState) { 
  3.     super.onCreate(savedInstanceState); 
  4.     setContentView(R.layout.activity_main); 
  5. @DebugLog 
  6. private void test(String... tests) { 
  7.     for (String arg : tests) { 
  8.         Log.i("Args", arg); 
  9.     } 

二、AOP詳解

 1、什么是aop

AOP,全稱為 Aspect Oriented Programming,即面向切面編程;AOP 是軟件開發中的一個編程范式,通過預編譯方式或者運行期動態代理等實現程序功能的統一維護的一種技術,它是 OOP(面向對象編程)的延續,利用 AOP 開發者可以實現對業務邏輯中的不同部分進行隔離,從而進一步降低耦合,提高程序的可復用性,進而提高開發的效率;

aop涉及到的關鍵知識點:

  • 橫切關注點(Cross-cutting concerns):在面向對象編程中,經常需要在不同的模塊代碼中添加一些類似的代碼,例如在函數入口處打印日志,在 View 的點擊處添加點擊事件的埋點統計,在 AOP 中把軟件系統分成兩個部分:核心關注點和橫切關注點,核心關注點就是業務邏輯處理的主要流程,而橫切關注點就是上面所說的經常發生在核心關注點的多個地方,且基本相似的日志紀錄,埋點統計等等;
  • 連接點(Joint point):在核心關注點中可能會存在橫切關注點的地方,例如方法調用的入口,View 的點擊處理等地方,在 AOP 中習慣稱為連接點;
  • 增強(Advice):特定連接點處所執行的動作,也就是 AOP 織入的代碼,目的是對原有代碼進行功能的增強;
  • before:在目標方法執行之前的動作;
  • around:在目標方法之前前后的動作;
  • after:在目標方法執行之后的動作;
  • 切入點(Pointcut):連接點的集合,這些連接點可以確定什么時機會觸發一個通知;
  • 切面(Aspect):切入點和通知可以組合成一個切面;
  • 織入(Weaving):將通知注入到連接點的過程;

AOP 中代碼的織入根據類型的不同,主要可以分為三類:

  • 編譯時織入:在 Java 類文件編譯的時候進行織入,這需要通過特定的編譯器來實現,例如使用 AspectJ 的織入編譯器;
  • 類加載時織入:通過自定義類加載器 ClassLoader 的方式在目標類被加載到虛擬機之前進行類的字節代碼的增強;
  • 運行時織入:切面在運行的某個時刻被動態織入,基本原理是使用 Java 的動態代理技術;

2、Android中aop實現:用aspectj實現aop

2.1、什么是AspectJ

①AspectJ實際上是對AOP編程思想的一個實踐,AOP雖然是一種思想,但就好像OOP中的Java一樣,一些先行者也開發了一套語言來支持AOP;

基礎知識點:

  • Aspect 切面:切面是切入點和通知的集合;
  • PointCut 切入點:切入點是指那些通過使用一些特定的表達式過濾出來的想要切入Advice的連接點;
  • Advice 通知:通知是向切點中注入的代碼實現方法;
  • Joint Point 連接點:所有的目標方法都是連接點;
  • Weaving 編織:主要是在編譯期使用AJC將切面的代碼注入到目標中, 并生成出代碼混合過的.class的過程;

涉及到的注解:

  • @Aspect:聲明切面,標記類
  • @Pointcut(切點表達式):定義切點,標記方法
  • @Before(切點表達式):前置通知,切點之前執行
  • @Around(切點表達式):環繞通知,切點前后執行
  • @After(切點表達式):后置通知,切點之后執行
  • @AfterReturning(切點表達式):返回通知,切點方法返回結果之后執行
  • @AfterThrowing(切點表達式):異常通知,切點拋出異常時執行

2.2、實現一個網絡狀態檢測的AOP

①aspectj配置

項目的gradle中配置build.gradle(project)

  1. buildscript { 
  2.   repositories { 
  3.     google() 
  4.     mavenCentral() 
  5.     jcenter() 
  6.   } 
  7.   dependencies { 
  8.     classpath 'com.android.tools.build:gradle:4.1.1' 
  9.     classpath 'org.aspectj:aspectjtools:1.8.6' 
  10.   } 
  11. ...... 
  12. ...... 

主app中build.gradle(app)

  1. dependencies { 
  2.   compile 'org.aspectj:aspectjrt:1.8.6' 
  3. android.libraryVariants.all { variant -> 
  4.   JavaCompile javaCompile = variant.javaCompile 
  5.   javaCompile.doLast { 
  6.     String[] args = [ 
  7.         "-showWeaveInfo"
  8.         "-1.5"
  9.         "-inpath", javaCompile.destinationDir.toString(), 
  10.         "-aspectpath", javaCompile.classpath.asPath, 
  11.         "-d", javaCompile.destinationDir.toString(), 
  12.         "-classpath", javaCompile.classpath.asPath, 
  13.         "-bootclasspath", android.bootClasspath.join(File.pathSeparator) 
  14.     ] 
  15.     MessageHandler handler = new MessageHandler(true); 
  16.     new Main().run(args, handler) 
  17.     def log = project.logger 
  18.     for (IMessage message : handler.getMessages(nulltrue)) { 
  19.       switch (message.getKind()) { 
  20.         case IMessage.ABORT: 
  21.         case IMessage.ERROR: 
  22.         case IMessage.FAIL: 
  23.           log.error message.message, message.thrown 
  24.           break; 
  25.         case IMessage.WARNING: 
  26.         case IMessage.INFO: 
  27.           log.info message.message, message.thrown 
  28.           break; 
  29.         case IMessage.DEBUG: 
  30.           log.debug message.message, message.thrown 
  31.           break; 
  32.       } 
  33.     } 
  34.   } 

②aop實現

定義annotation:

  1. @Target(ElementType.METHOD) 
  2. @Retention(RetentionPolicy.RUNTIME) 
  3. public @interface CheckNetwork { 

代碼注解:

  1. @CheckNetwork() 
  2.     private void checkNetwork() { 
  3.         LogUtil.i("AnnotationFragment""檢測完畢"); 
  4.     } 

關鍵處理切入點:

  1. @Aspect 
  2. public class CheckNetworkAspect { 
  3.     private static final String TAG = CheckNetworkAspect.class.getSimpleName(); 
  4.     /** 
  5.      * 找到處理的切點 
  6.      *   * *(..)  “**”表示是任意包名   “..”表示任意類型任意多個參數 
  7.      */ 
  8.     @Pointcut("execution(@la.xiong.androidquick.demo.features.function.annotation.aspect.CheckNetwork  * *(..))"
  9.     public void executionCheckNetwork() { 
  10.     } 
  11.     /** 
  12.      * 處理切面 
  13.      * 
  14.      * @param joinPoint 
  15.      * @return 
  16.      */ 
  17.     @Around("executionCheckNetwork()"
  18.     public Object checkPermission(ProceedingJoinPoint joinPoint) throws Throwable { 
  19.         MethodSignature signature = (MethodSignature) joinPoint.getSignature(); 
  20.         CheckNetwork annotation = signature.getMethod().getAnnotation(CheckNetwork.class); 
  21.         if (annotation != null) { 
  22.             Context context = AspectUtils.getContext(joinPoint.getThis()); 
  23.             if (NetworkUtils.isConnected()) { 
  24.                 Toast.makeText(context, "當前網絡正常", Toast.LENGTH_SHORT).show(); 
  25.             } else { 
  26.                 Toast.makeText(context, "此時沒有網絡連接", Toast.LENGTH_SHORT).show(); 
  27.             } 
  28.             return joinPoint.proceed(); 
  29.         } 
  30.         return null
  31.     } 

總結:

AOP 能夠實現將日志紀錄,性能統計,埋點統計,安全控制,異常處理等代碼從具體的業務邏輯代碼中抽取出來,放到統一的地方進行處理;

利用 AOP 開發者可以實現對業務邏輯中的不同部分進行隔離,從而進一步降低耦合,提高程序的可復用性,進而提高開發的效率;

可以自定義屬于你的功能比如:日志記錄,性能統計,安全控制,事務處理,異常處理等等。

本文轉載自微信公眾號「Android開發編程」,可以通過以下二維碼關注。轉載本文請聯系Android開發編程公眾號。

 

責任編輯:姜華 來源: Android開發編程
相關推薦

2024-05-21 09:55:43

AspectOrientedAOP

2019-11-01 08:49:07

JVM監控性能

2012-02-10 10:32:33

JavaSpring

2023-11-07 16:00:25

面向切面編程開發

2015-07-28 17:11:00

編程技術提升

2009-08-24 09:46:40

面向切面編程AOP

2011-04-26 09:33:04

SpringAOP

2013-03-20 17:18:07

Linux系統性能調優

2009-04-01 11:17:52

內存分配調優Oracle

2017-07-21 08:55:13

TomcatJVM容器

2013-09-17 10:37:03

AOPAOP教程理解AOP

2012-06-20 11:05:47

性能調優攻略

2021-03-04 08:39:21

SparkRDD調優

2018-11-12 14:53:09

Redis性能調優數據庫

2023-11-30 18:03:55

IDEA工具

2013-03-21 11:20:00

性能測試性能調優測試

2011-03-10 14:40:54

LAMPMysql

2011-11-14 10:28:23

2020-11-30 11:40:35

NginxLinux性能調優

2011-05-20 15:02:01

Oracle性能調優
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产一级一级国产 | 91一区二区| 久久久久久久99 | 户外露出一区二区三区 | www.中文字幕av | 国产成人精品高清久久 | 成人免费视频一区 | 日日操操 | 精品一区二区久久久久久久网站 | 国产电影一区二区三区爱妃记 | 亚洲福利网| 久久高清亚洲 | 自拍偷拍第一页 | 视频一区在线播放 | 亚洲国产精品久久久久 | 国产中文视频 | 午夜精品视频在线观看 | 欧美性精品 | 精品熟人一区二区三区四区 | 天堂资源| 亚洲成人精品一区 | 日韩在线看片 | 日韩中文字幕2019 | 激情婷婷成人 | 97色在线观看免费视频 | 精品国产乱码久久久久久影片 | 亚洲成人精选 | 日韩国产在线 | 日韩在线观看网站 | 欧美一级在线免费 | 中国黄色在线视频 | 毛片网站在线观看 | 精品久久亚洲 | 91在线精品秘密一区二区 | 国产美女在线看 | 天天看天天干 | 亚洲国产aⅴ精品一区二区 免费观看av | 三极网站 | 亚洲欧美一区二区三区国产精品 | 国产精品久久久久久52avav | 高清国产午夜精品久久久久久 |