一、簡述
1、AOP的概念
如果你用java做過后臺(tái)開發(fā),那么你一定知道AOP這個(gè)概念。如果不知道也無妨,套用百度百科的介紹,也能讓你明白這玩意是干什么的:
AOP為Aspect Oriented Programming的縮寫,意為:面向切面編程,通過預(yù)編譯方式和運(yùn)行期動(dòng)態(tài)代理實(shí)現(xiàn)程序功能的統(tǒng)一維護(hù)的一種技術(shù)。AOP是OOP的延續(xù),是軟件開發(fā)中的一個(gè)熱點(diǎn),也是Spring框架中的一個(gè)重要內(nèi)容,是函數(shù)式編程的一種衍生范型。利用AOP可以對(duì)業(yè)務(wù)邏輯的各個(gè)部分進(jìn)行隔離,從而使得業(yè)務(wù)邏輯各部分之間的耦合度降低,提高程序的可重用性,同時(shí)提高了開發(fā)的效率。
2、項(xiàng)目場景
項(xiàng)目開發(fā)過程中,可能會(huì)有這樣的需求,需要我們在方法執(zhí)行完成后,記錄日志(后臺(tái)開發(fā)中比較常見~),或是計(jì)算這個(gè)方法的執(zhí)行時(shí)間,在不使用AOP的情況下,我們可以在方法最后調(diào)用另一個(gè)專門記錄日志的方法,或是在方法體的首尾分別獲取時(shí)間,然后通過計(jì)算時(shí)間差來計(jì)算整個(gè)方法執(zhí)行所消耗的時(shí)間,這樣也可以完成需求。那如果不只一個(gè)方法要這么玩怎么辦?每個(gè)方法都寫上一段相同的代碼嗎?后期處理邏輯變了要怎么辦?最后老板說這功能不要了我們還得一個(gè)個(gè)刪除?
很明顯,這是不可能的,我們不僅僅是代碼的搬運(yùn)工,我們還是有思考能力的軟件開發(fā)工程師。這么low的做法絕對(duì)不干,這種問題我們完全可以用AOP來解決,不就是在方法前和方法后插入一段代碼嗎?AOP分分鐘搞定。
3、AOP的實(shí)現(xiàn)方式
要注意了,AOP僅僅只是個(gè)概念,實(shí)現(xiàn)它的方式(工具和庫)有以下幾種:
本篇的主角就是AspectJ,下面就來看看AspectJ方式的AOP如何在Android開發(fā)中進(jìn)行使用吧。
二、AspectJ的引入
對(duì)于eclipse與Android Studio的引入是不一樣的,本篇只介紹Android Studio如何引入AspectJ,eclipse請(qǐng)自行百度。Android Studio需要在app模塊的build.gradle文件中引入,總共分為3個(gè)步驟:
1)添加核心依賴
dependencies { ... compile 'org.aspectj:aspectjrt:1.8.9'}2)編寫gradle編譯腳本
buildscript { repositories { mavenCentral() } dependencies { classpath 'org.aspectj:aspectjtools:1.8.9' classpath 'org.aspectj:aspectjweaver:1.8.9' }}AspectJ需要依賴maven倉庫。
3)添加gradle任務(wù)
dependencies { ...}// 貼上面那段沒用的代碼是為了說明:下面的任務(wù)代碼與dependencies同級(jí)import org.aspectj.bridge.IMessageimport org.aspectj.bridge.MessageHandlerimport org.aspectj.tools.ajc.Mainfinal def log = project.loggerfinal def variants = project.android.applicationVariantsvariants.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; } } }}直接粘貼到build.gradle文件的末尾即可,不要嵌套在別的指令中。
三、AOP的基本知識(shí)
在使用AspectJ之前,還是需要先介紹下AOP的基本知識(shí),熟悉的看官可以跳過這部分。
1、AOP術(shù)語