JAVA: アスペクト指向プログラミング AOP

1. 定義

        あるオブジェクトからいくつかの機能を抽出して分離し、抽出後、ある兄弟の一方的な機能を修正および拡張することができます

        それは、すべての公開コードをさまざまな方法で抽出し、特定の場所に置いて集中管理することです。

        ビジネスロジックの各部分が分離されることで、ビジネスロジックの各部分間の結合が軽減され、プログラムの再利用性が向上し、開発効率が向上します。

2. 対面での思考表現

  1. たとえば、動的プロキシ (AOP) は、MVP のモデルが空かどうかを判断するために動的プロキシを使用します。
  2. アプリケーションでのアクティビティ登録ライフサイクルの監視
  3. サードパーティのコンパイル ツールに基づく: APT、AspectJ、Javassist など。

3. OOP(オブジェクト指向プログラミング)との違い

        OOP は問題を個々のモジュールに分割することです

        AOP は、多くのモジュールが関与する特定の種類の問題を統合して管理するものです。

4. AOP の使用シナリオ

  • パラメータのチェックサムが空です
  • 権限検出、ネットワーク検出など 
  • 埋葬された
  • 安全に制御する
  • ロギング
  • パフォーマンス統計

  • 防御的な try-Catch の代わりに例外処理を行う

  • キャッシュ
    メソッドの戻り値をキャッシュし、次回メソッドを実行するときにキャッシュから直接取得します。

  • ホットフィックス

5. AspectJの使い方

@Aspect: アスペクトを宣言、クラスをマーク
@Pointcut (ポイントカット式): ポイントカットを定義、メソッドをマーク
@Before (ポイントカット式): 事前通知、ポイントカット前に実行
@Around (ポイントカット式) : 囲み通知、ポイントカット前後に実行
@After (ポイントカット式): ポスト通知、ポイントカット後に実行 @AfterReturning
(ポイントカット式): リターン通知、ポイントカット後に
@AfterThrowing (ポイントカット式)を実行メソッドは結果を返します: 例外通知。カットポイントが例外をスローしたときに実行されます
 
。 注: @Aspect が追加されていない場合、次のアノテーションは機能しません。

1. プロジェクトの下に gradle への依存関係を追加します

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'org.aspectj:aspectjtools:1.8.9'
        classpath 'org.aspectj:aspectjweaver:1.8.9'
    }
}

plugins {
    ……
}

2.使用するモジュールgradleを追加します

import org.aspectj.bridge.IMessage
import org.aspectj.bridge.MessageHandler
import org.aspectj.tools.ajc.Main

android {
    ……
}
 
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 = 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;
            }
        }
    }
}

dependencies {
    ……
    implementation 'org.aspectj:aspectjrt:1.8.9'
}

3. 注釈を作成し、カットポイントをマークする

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)ButterKnife   SOURCE 代表资源
public @interface CheckNet {

}

4. ハンドルカットポイント

@Aspect //声明切面
public class SectionAspect {

    /**
     * 找到处理的切点
     * * *(..)  可以处理所有的方法
     */
    @Pointcut("execution(@com.darren.architect_day02.CheckNet * *(..))")
    public void checkNetBehavior() {

    }

    /**
     * 处理切面
     */
    @Around("checkNetBehavior()")
    public Object checkNet(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        CheckNet checkNet = signature.getMethod().getAnnotation(CheckNet.class);
        if (checkNet != null) {
            Object object = joinPoint.getThis();
            Context context = getContext(object);
            if (context != null) {
                if (!isNetworkAvailable(context)) {
                    //处理公共事件
                    Toast.makeText(context,"请检查您的网络",Toast.LENGTH_LONG).show();
                    return null;
                }
            }
        }
        return joinPoint.proceed();
    }
}

6、AspectJ 原則

        実行時には、aspectJ サードパーティ コンパイラが使用され、aspectJ はパフォーマンスに影響を与えることなくクラス ファイルを変更します。

おすすめ

転載: blog.csdn.net/weixin_42277946/article/details/131034556