SpringAOPの実装

1. AOPとは何ですか?

AOP(Aspect Orient Programming)は、一般に、オブジェクト指向の補足としてアスペクト指向(アスペクト)プログラミングと呼ばれ、トランザクション管理、ロギング、キャッシングなど、システム内のさまざまなモジュールに分散された分野横断的な懸念に対処するために使用されます。 。AOP実装の鍵は、AOPフレームワークによって自動的に作成されるAOPプロキシです。AOPプロキシは主に静的プロキシと動的プロキシに分けられます。静的プロキシの代表はAspectJであり、動的プロキシの代表はSpringAOPです。この記事では、AspectJとSpringAOPの実装をそれぞれ分析して紹介します。

2. springaopはどのようにそれを達成しますか?

Spring AOPの動的プロキシには、主にJDK動的プロキシとCGLIB動的プロキシの2つの方法があります。JDK動的プロキシは、リフレクションを介してプロキシクラスを受け取り、インターフェイスを実装するためにプロキシクラスを必要とします。JDK動的プロキシのコアはInvocationHandlerインターフェイスとProxyクラスです。

ターゲットクラスがインターフェイスを実装していない場合、SpringAOPはCGLIBを使用してターゲットクラスを動的にプロキシすることを選択します。CGLIB(Code Generation Library)は、実行時に特定のクラスのサブクラスを動的に生成できるコード生成クラスライブラリです。CGLIBは継承による動的プロキシであるため、クラスが次のようにマークされている場合は注意してください。final、その後、動的プロキシとしてCGLIBを使用できません。

2.1、JDK動的プロキシ

インターフェイスクラスを定義する

package org.java.base.springaop;
public interface Service {
 /**
 * add方法
 */
 public void add();

 /**
 * update方法
 */
 public void update();
}复制代码

インターフェイスクラスを実装する

package org.java.base.springaop;
public class ServiceImpl implements Service {
 
 public void add() {
 System.out.println("AService add>>>>>>>>>>>>>>>>>>");
 }


 public void update() {
 System.out.println("AService update>>>>>>>>>>>>>>>");
 }
}复制代码

動的プロキシクラスMyInvocationHandlerを実装し、InvocationHandlerインターフェイスを実装し、インターフェイスにinvokeメソッドを実装します。このメソッドにアスペクトロジックを追加するinvokeメソッドを詳しく見てみましょう。ターゲットクラスメソッドの実行は、ステートメントmehod.invoke(target、args)によって完了します。

package org.java.base.springaop;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class MyInvocationHandler implements InvocationHandler {
 private Object target;
 /**
 * 构造函数
 * @param target
 */
 MyInvocationHandler(Object target) {
 super();
 this.target = target;
 }
 public Object invoke(Object proxy, Method method, Object[] args)
 throws Throwable {
 // 程序执行前加入逻辑,MethodBeforeAdviceInterceptor
 System.out.println("before-----------------------------");
 // 程序执行
 Object result = method.invoke(target, args);
 // 程序执行后加入逻辑,MethodAfterAdviceInterceptor
 System.out.println("after------------------------------");
 return result;
 }

}复制代码

拡張ターゲットオブジェクトがProxy.newProxyInstance(aService.getClass()。getClassLoader()、aService.getClass()。getInterfaces()、handler);によって生成されるテストクラス。

package org.java.base.springaop;

import java.lang.reflect.Proxy;
public class Test {
 public static void main(String[] args) {
 Service aService = new ServiceImpl();
 MyInvocationHandler handler = new MyInvocationHandler(aService);
 // Proxy为InvocationHandler实现类动态创建一个符合某一接口的代理实例
 Service aServiceProxy = (Service) Proxy.newProxyInstance(aService
 .getClass().getClassLoader(), aService.getClass()
 .getInterfaces(), handler);
 // 由动态生成的代理对象来aServiceProxy 代理执行程序,其中aServiceProxy 符合Service接口
 aServiceProxy.add();
 System.out.println();
 aServiceProxy.update();
 
 }
}复制代码

1525849940(1)

ターゲットクラスServiceImplのaddメソッドとupdateメソッドの前後にカスタムアスペクトロジックが追加され、AOPインターセプトメカニズムが有効になっていることがわかります。

2.2、CGLIB動的エージェント

ターゲットクラス、cglibターゲットクラスの統一されたインターフェイスを定義する必要はありません

package org.java.base.springaop;

public class Base {
 /**
 * 一个模拟的add方法
 */
 public void add() {
 System.out.println("add ------------");
 }
}复制代码

動的プロキシクラスCglibProxyを実装するには、MethodInterceptorインターフェイスを実装し、interceptメソッドを実装する必要があります。プロキシは、addメソッドの前後にカスタムアスペクトロジックを追加します。ターゲットクラスのaddメソッドの実行ステートメントはproxy.invokeSuper(object、args);です。

package org.java.base.springaop;
import java.lang.reflect.Method;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

public class CglibProxy implements MethodInterceptor {

 public Object intercept(Object object, Method method, Object[] args,
 MethodProxy proxy) throws Throwable {
 // 添加切面逻辑(advise),此处是在目标类代码执行之前,即为MethodBeforeAdviceInterceptor。
 System.out.println("before-------------");
 // 执行目标类add方法
 proxy.invokeSuper(object, args);
 // 添加切面逻辑(advise),此处是在目标类代码执行之后,即为MethodAfterAdviceInterceptor。
 System.out.println("after--------------");
 return null;
 }

}复制代码

拡張ターゲットクラスのファクトリファクトリを取得します。拡張メソッドクラスオブジェクトはEnhancerによって実装されます。コードは次のとおりです。

 package org.java.base.springaop;

import org.springframework.cglib.proxy.Enhancer;

public class Factory {
 /**
 * 获得增强之后的目标类,即添加了切入逻辑advice之后的目标类
 * 
 * @param proxy
 * @return
 */
 public static Base getInstance(CglibProxy proxy) {
 Enhancer enhancer = new Enhancer();
 enhancer.setSuperclass(Base.class);
 //回调方法的参数为代理类对象CglibProxy,最后增强目标类调用的是代理类对象CglibProxy中的intercept方法
 enhancer.setCallback(proxy);
 // 此刻,base不是单纯的目标类,而是增强过的目标类
 Base base = (Base) enhancer.create();
 return base;
 }
}复制代码

テストクラス

package org.java.base.springaop;

public class Testcglib {
 public static void main(String[] args) {
 CglibProxy proxy = new CglibProxy();
 // base为生成的增强过的目标类
 Base base = Factory.getInstance(proxy);
 base.add();
 }
}复制代码

それ以来、cglib動的プロキシによって実装されたAOPインターセプトメカニズムが基本的に実装されています。インターセプトの効果を見てみましょう。プログラムの実行結果は次のとおりです。

前 - - -

追加 - -

後————–

ご覧のとおり、ターゲットクラスBaseのaddメソッドの前後にカスタムアスペクトロジックが追加され、AOPインターセプトメカニズムが有効になっています。

3.動的プロキシとCGLIBの2つの方法の概要は次のとおりです。

  • JDK動的プロキシ(動的プロキシ)
    • 標準JDKに基づく動的プロキシ機能
    • インターフェイスを実装するビジネスオブジェクトのみ
  • CGLIB
    • ターゲットオブジェクトを動的にサブクラス化することにより、AOPプロキシを実現します。
    • @EnableAspectJAutoProxy(proxyTargetClass = true)強制的に使用するように指定する必要があります
    • ビジネスオブジェクトがインターフェイスを実装していない場合、デフォルトでCGLIBが選択されます

おすすめ

転載: blog.csdn.net/suifeng629/article/details/106867908