AOPの実現原理——スタティックエージェントとダイナミックエージェント(Spring AOP)
記事の目次、AOPは何ですか? 、スタティックエージェント、AsppectJ 2.1、例示 、動的エージェント 3.1、JDKダイナミックエージェント 3.1.1、コアクラス: 3.1.2、例1−JDK動的エージェント 3.2、CGLOIB動的エージェント 3.2.1コアクラス: 3.2.2、例 、小結 一、AOPは何ですか?
ここのAOPはSpring AOPではなく、面に向かってプログラミングする思想を指します.
AOP(Aspect Orient Prograamming)は、一般的には、指向プログラミングと呼ばれ、対象に向けた補足として、処理システムにおいて各モジュールに分布する横断的な注目点、例えば、事務管理、ログ、キャッシュなどに用いられます.
AOP実装は主に静的エージェントと動的エージェントに分けられる.静的エージェントは、主に である.動的エージェントは主に である.
本論文はAspectJとSpring AOPの実現をそれぞれ分析して紹介します.
二、スタティックエージェント——AsppectJ
AsppectJの基礎技術は静的エージェントであり、AsppectJがサポートする特定の言語で切断面を作成し、コマンドをコンパイルして、新しいエージェントクラスを生成します.このエージェントはビジネスクラスを強化しています.
2.1、例を挙げて説明する
まず普通のハロークラスがあります.
ハロークラス:
TxAspectクラス:
コンパイル後のHello.class
Asppectコンパイル後のクラスファイル
三、ダイナミックエージェント
Spring AOPで使用する動的エージェントとは、AOPフレームがバイトコードを修正することなくメモリに一時的にAOPオブジェクトを生成するということであり、このAOPオブジェクトはターゲットオブジェクトのすべての方法を含み、特定の接点で強化処理を行い、元のオブジェクトを調整する方法である.
Spring AOPにおける動的エージェントは主に2つの方法があります.JDKダイナミックエージェントとCGLOIBダイナミックエージェントです.
3.1、JDKダイナミックエージェント
JDK動的エージェントは、反射によってプロキシされたクラスを受信し、プロキシが要求されるクラスは、インターフェースを実装しなければならない.
3.1.1、コアクラス: InvocationHandlerインターフェース Proxy.newProxyInstance() 3.1.2、例1–JDKダイナミックエージェント
Personインターフェースを定義します.
Asppectを定義する
3.2、CGLOIBダイナミックエージェント
ターゲットクラスがインターフェースを実現していない場合、Spring AOPはCGLOIBを使用してターゲットクラスを動的に代理することを選択します. CGLOIB(Code Generation Library)は、コード生成のクラスであり、実行時にあるクラスのサブクラスを動的に生成することができる. CGLOIBは 3.2.1コアクラス: MethodInterceptorインターフェース Enhancer類 3.2.2、例
四、結び
AspectJはコンパイル時にターゲットオブジェクトを強化し、Spring AOPの動的エージェントは運行毎に動的に強化され、AOPエージェントオブジェクトを生成する.
AOPプロキシを生成するタイミングが違っていて、AsppectJのスタティックエージェント方式はより良い性能を持っていますが、AspectJは特定のコンパイラを必要とします.Spring AOPは特定のコンパイラ処理を必要としません.
ここのAOPはSpring AOPではなく、面に向かってプログラミングする思想を指します.
AOP(Aspect Orient Prograamming)は、一般的には、指向プログラミングと呼ばれ、対象に向けた補足として、処理システムにおいて各モジュールに分布する横断的な注目点、例えば、事務管理、ログ、キャッシュなどに用いられます.
AOP実装は主に静的エージェントと動的エージェントに分けられる.
AspectJ
Spring AOP
本論文はAspectJとSpring AOPの実現をそれぞれ分析して紹介します.
二、スタティックエージェント——AsppectJ
AsppectJの基礎技術は静的エージェントであり、AsppectJがサポートする特定の言語で切断面を作成し、コマンドをコンパイルして、新しいエージェントクラスを生成します.このエージェントはビジネスクラスを強化しています.
2.1、例を挙げて説明する
まず普通のハロークラスがあります.
ハロークラス:
public class Hello {
public void sayHello() {
System.out.println("hello");
}
public static void main(String[] args) {
Hello h = new Hello();
h.sayHello();
}
}
AsppectJを使ってAsppectを作成します.TxAspectクラス:
public aspect TxAspect {
void around():call(void Hello.sayHello()){
System.out.println(" ...");
proceed();
System.out.println(" ...");
}
}
ここではSpringのような事務の場面をシミュレーションした.AsppectJのコンパイラを使ってコンパイルします.ajc -d . Hello.java TxAspect.aj
コンパイルが完了したら、このハロークラスを実行します.以下の出力が見られます. ...
hello
...
明らかに、AOPはすでに発効しました.一体、AsppectJはHello類を修正しないで、ハロー類のために新しい機能を追加したのですか?コンパイル後のHello.class
public class Hello {
public Hello() {
}
public void sayHello() {
System.out.println("hello");
}
public static void main(String[] args) {
Hello h = new Hello();
sayHello_aroundBody1$advice(h, TxAspect.aspectOf(), (AroundClosure)null);
}
}
これはAsppectJのスタティックエージェントであり、コンパイル段階でAsppectをJavaバイトコードに編入し、実行する時は強化された後のAOPオブジェクトである.Asppectコンパイル後のクラスファイル
public void ajc$around$com_listenzhangbin_aop_TxAspect$1$f54fe983(AroundClosure ajc$aroundClosure) {
System.out.println(" ...");
ajc$around$com_listenzhangbin_aop_TxAspect$1$f54fe983proceed(ajc$aroundClosure);
System.out.println(" ...");
}
Asppectがコンパイルした後のclassファイルから、実行の論理がより明確に見られます.プロシージャ方法は、被プロキシクラスをリピートして実行する方法です.三、ダイナミックエージェント
Spring AOPで使用する動的エージェントとは、AOPフレームがバイトコードを修正することなくメモリに一時的にAOPオブジェクトを生成するということであり、このAOPオブジェクトはターゲットオブジェクトのすべての方法を含み、特定の接点で強化処理を行い、元のオブジェクトを調整する方法である.
Spring AOPにおける動的エージェントは主に2つの方法があります.JDKダイナミックエージェントとCGLOIBダイナミックエージェントです.
3.1、JDKダイナミックエージェント
JDK動的エージェントは、反射によってプロキシされたクラスを受信し、プロキシが要求されるクラスは、インターフェースを実装しなければならない.
3.1.1、コアクラス:
Personインターフェースを定義します.
public interface Person {
String sayHello(String name);
}
実現クラス–中国人:@Component
public class Chinese implements Person {
@Timer
@Override
public String sayHello(String name) {
System.out.println("-- sayHello() --");
return name + " hello, AOP";
}
public void eat(String food) {
System.out.println(" :" + food);
}
}
ここの@Timer注解は自分で定義した普通の注釈で、Pointcutをマークします.Asppectを定義する
@Aspect
@Component
public class AdviceTest {
@Pointcut("@annotation(com.listenzhangbin.aop.Timer)")
public void pointcut() {
}
@Before("pointcut()")
public void before() {
System.out.println("before");
}
}
テスト:@SpringBootApplication
@RestController
public class SpringBootDemoApplication {
// Person
@Autowired
private Person chinese;
@RequestMapping("/test")
public void test() {
chinese.sayHello("listen");
System.out.println(chinese.getClass());
}
public static void main(String[] args) {
SpringApplication.run(SpringBootDemoApplication.class, args);
}
}
出力:before
-- sayHello() --
class com.sun.proxy.$Proxy53
このタイプはcomp.sun.proxy 53であり、前述のProxy類であるため、Spring AOPはJDK
を使用しています.3.2、CGLOIBダイナミックエージェント
ターゲットクラスがインターフェースを実現していない場合、Spring AOPはCGLOIBを使用してターゲットクラスを動的に代理することを選択します.
によって動的エージェントを行うので、あるクラスがfinalとしてマークされている場合、CGLOIBを動的エージェントとして使用することはできない.@Component
public class Chinese {
public String sayHello(String name) {
System.out.println("-- sayHello() --");
return name + " hello, AOP";
}
public void eat(String food) {
System.out.println(" :" + food);
}
}
テスト:@SpringBootApplication
@RestController
public class SpringBootDemoApplication {
// Chinese
@Autowired
private Chinese chinese;
@RequestMapping("/test")
public void test() {
chinese.sayHello("listen");
System.out.println(chinese.getClass());
}
public static void main(String[] args) {
SpringApplication.run(SpringBootDemoApplication.class, args);
}
}
出力:before
-- sayHello() --
class com.listenzhangbin.aop.Chinese$$EnhancerBySpringCGLIB$$56b89168
CGLOIBによってクラスが強化された、すなわちCGLOIB動的エージェントが見られます.ここのCGLOIBエージェントはSpring AOPの代理であり、このクラスはいわゆるAOPエージェントであり、AOPエージェント類は接点で動的に補強処理に織り込まれている.四、結び
AspectJはコンパイル時にターゲットオブジェクトを強化し、Spring AOPの動的エージェントは運行毎に動的に強化され、AOPエージェントオブジェクトを生成する.
AOPプロキシを生成するタイミングが違っていて、AsppectJのスタティックエージェント方式はより良い性能を持っていますが、AspectJは特定のコンパイラを必要とします.Spring AOPは特定のコンパイラ処理を必要としません.