AOP之ASpectj最詳細使用

AOP面向切面編程,通過預編譯方式和運行期動態代理實現程序的統一維護的一種技術。

Aspectj框架就是通過預編譯方式實現程序的統一維護,今天介紹如何使用:

//配置版本信息分兩步,使用分三步

最新版本的aspectj是1.9.4但是需要SDK最低版本24,這裏我就是使用1.8.9版本

//配置信息

1:在工程的build.gradle添加下面依賴

buildscript {
    
    repositories {
        google()
         //鏡像倉,解決需要翻牆下載的
        maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.2.0'
        //aspectj框架
        classpath 'org.aspectj:aspectjtools:1.8.9'
        classpath 'org.aspectj:aspectjweaver:1.8.9'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        google()
        //鏡像倉,解決需要翻牆下載的
        maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
        jcenter()
    }
}

2:在module的build.gradle添加下面依賴

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'

    //使用aspectj框架
    implementation 'org.aspectj:aspectjrt:1.8.9'

}

//aspectj配置打印log

import org.aspectj.bridge.IMessage
import org.aspectj.bridge.MessageHandler
import org.aspectj.tools.ajc.Main
final def log = project.logger
final def variants = project.android.applicationVariants

variants.all { variant ->
    if (!variant.buildType.isDebuggable()) {
        log.debug("Skipping non-debuggable build type '${variant.buildType.name}'.")
        return
    }
     //如果JavaCompile報紅能編譯過不影響使用
    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
            }
        }
    }
}

//使用三部曲

1>自定義註解:根據你的需要設置註解的目標,和作用域

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LoginTrace {
    String value() default "";

}

2>創建個切面處理類,處理所有使用註解的邏輯,統一在這個類處理

//切面
@Aspect
public class LoginAapect {

    //切入點 ("execution(@註解全類名 * *(..)")
    @Pointcut("execution(@com.example.administrator.aop_aspectj.annotation.LoginTrace *  *(..))")
    public void methodAnnotationWithLoginTrace() {
    }


    //切入點邏輯處理(可以對 切入點 前處理 後處理  前後處理 )
    //參數--->切入點方法名()--->methodAnnotationWithLoginTrace()
//    @After("methodAnnotationWithLoginTrace()")//切入點後運行 --》使用註解LoginTrace的方法運行完後執行這個方法代碼
//    @Before("methodAnnotationWithLoginTrace()")//切入點前運行
    @Around("methodAnnotationWithLoginTrace()")//切入點前 後 都運行(後運行是在ProceedingJoinPoint對象非空時運行)
    public Object weaveJoinPoint(ProceedingJoinPoint joinPoint) throws Throwable {
        Log.e("zdh", "-------------前");

        Object proceed=null;
        if (joinPoint != null) {
             //如果使用Around註解需要返回proceed對象,要不然註解方法裏面代碼不執行
             proceed = joinPoint.proceed();
            Log.e("zdh", "-------------後");
        }

        return proceed;
    }


}

//在需要統一處理的方法添加註解

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

  
     //如果你想區分不同方法可以使用標記區分--》@LoginTrace("send")
    @LoginTrace
    public void send(View view) {
        Log.e("zdh","------------測試");
    }
}

//運行代碼就可以看到打印日誌如下

 

 是不是很簡單。

總結:1:在依賴時需要注意1.9前和1.9的SDK最低版本問題,

           2:在依賴導報可以添加鏡像倉看看。

           3:如果使用Around註解需要返回proceed對象,要不然註解方法裏面代碼不執行

           4:使用註解的方法一般是不會影響方法裏面代碼執行的,所以要考慮方法裏面代碼執行後的效果,

 

//下面以實際項目需要寫個demo,一般在開發中我們有些頁面是需要用戶登錄後才能進入的,這裏面就以登錄爲實例寫個demo

源碼地址https://github.com/zhudaihao/AOP_aspectj

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章