AOPとは何ですか
AOP(アスペクト指向プログラミング)、即ち、 アスペクト指向プログラミング 、それはOOP(オブジェクト指向プログラミング、オブジェクト指向プログラミング)互いに補完、OOP異なる視点抽象ソフトウェア構成を備える。でOOP、我々のクラス(クラス)私たちの基本的な単位として、基本的な単位は、AOPのある アスペクト(セクション)
用語
アスペクト(セクション)
aspect
A point cut
と advice
組成の両方横定義されたロジックを含む、定義もある(点に参加する)接続点を含みます。
スプリングAOPは、フレーム部の実装を担当して、ロジック部を交差する接続点の指定区間に織り込ま定義されています。AOPにフォーカスする方法である(強化するadvice
)場合、ターゲット・オブジェクトターゲットの上部接続点に織り込まそれは2つのタスクで構成されます。
-
ポイントカットとアドバイスすることにより、特定のジョインポイントを見つける方法
-
内のコードセクションを作成する方法についてのアドバイス。
単に@Aspect注釈付きクラスの使用であることを、カット、出会いのポイントカットルールは、適切なアドバイスが運転されます追加ジョインポイント。
アドバイス(拡張)
コードの一部(すなわち、満たすルールがポイントポイントカットに参加する)点に参加する。春AOP含む多くのAOPフレームワークを、特定の態様に加え、助言は、インターセプタ(インターセプタ)としてモデル化され、参加ポイントの複数に維持されますアドバイス、インターセプトの層ごと。
接続ポイント(ジョインポイント)
プログラムの実行は、このような実行または例外処理方法の間の点。春AOPでは、常に取り付け方法の実行のポイントを示しています。
タンジェントポイント(ポイントカット)
述語のマッチングは、点(マッチポイントに参加すること述語)。アドバイスと特定のポイントカットに関連付けられているに参加し、一致点がポイントに加わる切断行います。在 Spring 中, 所有的方法都可以认为是 joinpoint, 但是我们并不希望在所有的方法上都添加 Advice, 而 pointcut 的作用就是提供一组规则(使用 AspectJ pointcut expression language 来描述) 来匹配joinpoint, 给满足规则的 joinpoint 添加 Advice.
春AOP、ISを行うには、すべての方法でポイントを結合します。ポイントカットが情報の記述である、それが変更されたポイントに参加、ポイントカットを経て、我々はポイントをアドバイスに織ることができる参加するかを決定することができます。だから、ポイントに参加し、基本的に2点の異なる緯度であるかについてのポイントカット。advice 是在 join point 上执行的, 而 point cut 规定了哪些 join point 可以执行哪些 advice
聴衆(ターゲット)
ターゲットオブジェクトのアドバイスを織っ。また、ターゲットオブジェクトと呼ばれます advised object
。因为 Spring AOP 使用运行时代理的方式来实现 aspect, 因此 adviced object 总是一个代理对象(proxied object)
注意, adviced object 指的不是原来的类, 而是织入 advice 后所产生的代理类.
ウィービング(ウィービング)
プロセス意志態様と一緒に他のオブジェクトとは異なる実装技術、3つの方法でAOP織りに従ってadvicedオブジェクトを作成します。
-
特別なJavaコンパイラを必要とコンパイラ、織り込ま。
-
特別なクラスローダを要求するクラスローディングのウィービング。
-
動的プロキシ製織、ターゲット・ランタイム・クラス生成モードサブクラス補強(アドバイス)を加える。春動的プロキシを編む、コンパイラーは、クラスローディングのAspectJの織り織りを使用します。
アドバイスの種類
-
ポイントに参加する前にアドバイスする前に、アドバイスを実行しました。が、ポイントに参加するが、実行を防ぐことができない例外が発生しない限り、我々のコードにアドバイスする前に、ではない人工的である(ポイントに参加する前にアドバイスが実行される前に、 )参加のポイントでコードを実行するために継続するかどうかを決定
-
通常の実行に復帰した後の戻りアドバイス、助言した後のポイントに参加
-
助言、アドバイスを投げた後、ポイントが実行スロー参加するとき
-
(最終的な)アドバイスした後、それが正常終了であるか、またはポイントに参加するかどうかをアドバイス例外が実行される起こります。
-
アドバイスを中心に、共同ポイント前後のアドバイスは、ポイント終了が実行されて参加します。これは、最も一般的なアドバイスです。
joinpoint
考えることができる 宾语
ではなく pointcut
、変更する同化することができます joinpoint
属性を、その全体を aspect
として記述することができます。 满足 pointcut 规则的 joinpoint 会被添加相应的 advice 操作.
前書き
追加のメソッドやフィールドタイプ。春AOPは私たちがすることを可能にする 目标对象
新しいインターフェース(および対応する実装)を導入。例えば、我々はするisModifiedインタフェースを実現するために豆の導入を使用して、キャッシュの実装を簡単にするためにすることができます。
AOPプロキシ
クラスに織り込まAOPがアドバイスされ、それは元のクラスの融合および拡張ロジックプロキシクラスであるクラス結果を生成する。春AOPは、AOPプロキシはプロキシオブジェクトまたはCGLIB JDKダイナミックプロキシオブジェクトです。
我々はすべてのインターフェイス剤であることができる、それを通して、AOPプロキシを達成するために、標準のJDKのダイナミックプロキシ(動的プロキシ)技術を使用しての春AOPのデフォルト如果需要为一个类实现代理, 那么可以使用 CGLIB 代理.
のビジネス・ロジック・オブジェクトがインタフェースを実装していないときは、その後、春AOPはとしてCGLIBをデフォルト設定されますAOPエージェント。私たちが必要な場合は、あるアドバイスに織りへの道であるが、この方法は、春AOPが提供するメソッドのインターフェースではありません動的プロキシCGLIBを実装するために、この時間を使用します。このような観点では、春AOPの勧告は、インターフェイスのプログラミングに基づいていますAOPはクラスではなくインターフェイスします。
@AspectJのサポート
@AspectJは、 Javaアノテーションを使ってAOPを実現するためのコーディングスタイルです。@AspectJスタイルAOP AspectJのプロジェクト5はAspectJの中に導入され、春にはまた@AspectJとAOPのスタイルをサポートしています
Javaを使用するコンフィギュレーションモードが有効に@AspectJ
@Configuration
@EnableAspectJAutoProxy
パブリッククラスのAppConfig {
}
@AspectJを有効にするためにXMLを使用する方法
<AOP:AspectJの-自動プロキシ/>
定義された態様(セクション)
注釈を使用する場合 @Aspectを ビーンをタグ付けした後に、Springフレームワークは自動的に豆を収集し、そのようなものとして、春AOPに追加します:
@Component
@Aspect
パブリッククラスのMyTest {
}
声明のポイントカット:
ポイントカット宣言は、2つの部分で構成さ:
-
メソッド名やパラメータを含むメソッドシグネチャ、
-
どの方法を指定するために使用されたポイントカット表現は、我々は(それがアドバイスに織ることができIE)に興味を持っている実行されます。
AOPの@AspectJスタイルでは、我々はすなわち、ポイントカットを記述するためのメソッドを使用します。
@Pointcut("execution(* com.xys.service.UserService.*(..))") // 切点表达式
private void dataAccessOperation() {} // 切点前面
这个方法必须无返回值.
这个方法本身就是 pointcut signature, pointcut 表达式使用@Pointcut 注解指定.
我々は、単にポイントカットを定義する上で、説明ポイントカットはされています内のすべてのパケットに一致するcom.xys.service.UserService すべての方法で行いました。
声明のポイントカット
ポイントカット宣言は、2つの部分で構成さ:
-
メソッド名やパラメータを含むメソッドシグネチャ、
-
どの方法を指定するために使用されたポイントカット表現は、我々は(それがアドバイスに織ることができIE)に興味を持っている実行されます。
AOPの@AspectJスタイルでは、我々はすなわち、ポイントカットを記述するためのメソッドを使用します。
@Pointcut("execution(* com.xys.service.UserService.*(..))") // 切点表达式
private void dataAccessOperation() {} // 切点前面
这个方法必须无返回值.
这个方法本身就是 pointcut signature, pointcut 表达式使用@Pointcut 注解指定.
我々は、単にポイントカットを定義する上で、説明ポイントカットはされています内のすべてのパケットに一致するcom.xys.service.UserService すべての方法で行いました。
切点指定子(指示)
AspectJ5(指示)や、「実行(AS動作パラメータによってカットポイント指定子発現 greetTo(..))」接点の発現は、 実行は 識別子であり、括弧内の数字 greetTo(..)であります運転パラメータ
実行
参加点マッチングは、全てのオブジェクト・クラスのための「実行(*ハロー(..))」一致ハローを表し、()メソッドは、例えば、実行される。これは、最も基本的なポイントカット識別子です。
以内に
一致が全て特定のパッケージ点を結合、例えば、 within(com.xys.*)
つつ、すなわちパッケージの全てのクラスの全てのメソッドは、すべての接続点com.xysパッケージを表す within(com.xys.service.*Service)
全てcom.xys.serviceパッケージで終わるすべてのサービスクラスを示します接続ポイント。
この与対象
この効果は、Bean(春AOPプロキシ)は、所与のタイプ(のインスタンス)の一例である豆を一致させることである。対象物(対象物、アドバイス元のクラスを織る、すなわち必要)とターゲットマッチ、このオブジェクトは、(インスタンスの)指定された型のインスタンスです。
豆
次の試合豆Bean名のためのすべての方法は、例えば、値を指定しました:
bean(*Service) // 匹配名字后缀为 Service 的 bean 下的所有方法
bean(myService) // 匹配名字为 myService 的 bean 下的所有方法
引数
満たすために必要な照合パラメータの方法例:
@Pointcut("within(com.xys.demo2.*)")
public void pointcut2() {
}
@Before(value = "pointcut2() && args(name)")
public void doSomething(String name) {
logger.info("---page: {}---", name);
}
@Service
public class NormalService {
private Logger logger = LoggerFactory.getLogger(getClass());
public void someMethod() {
logger.info("---NormalService: someMethod invoked---");
}
public String test(String name) {
logger.info("---NormalService: test invoked---");
return "服务一切正常";
}
}
NormalService.testを実行するとアドバイスが、 doSomething
実行され、試験方法パラメータ名が渡されます doSomething
。
一般的な例:
// 匹配只有一个参数 name 的方法
@Before(value = "aspectMethod() && args(name)")
public void doSomething(String name) {
}
// 匹配第一个参数为 name 的方法
@Before(value = "aspectMethod() && args(name, ..)")
public void doSomething(String name) {
}
// 匹配第二个参数为 name 的方法
Before(value = "aspectMethod() && args(*, name, ..)")
public void doSomething(String name) {
}
@Annotation
マッチングによって指定された方法は、例えば、マークの注釈します:
@Pointcut("@annotation(com.xys.demo1.AuthChecker)")
public void pointcut() {
}
注釈がで一致している AuthChecker
マークされたメソッド。
一般的な表現の接点
一致するメソッドのシグネチャ
// 匹配指定包中的所有的方法
execution(* com.xys.service.*(..))
// 匹配当前包中的指定类的所有方法
execution(* UserService.*(..))
// 匹配指定包中的所有 public 方法
execution(public * com.xys.service.*(..))
// 匹配指定包中的所有 public 方法, 并且返回值是 int 类型的方法
execution(public int com.xys.service.*(..))
// 匹配指定包中的所有 public 方法, 并且第一个参数是 String, 返回值是 int 类型的方法
execution(public int com.xys.service.*(String name, ..))
マッチ型シグネチャ
// 匹配指定包中的所有的方法, 但不包括子包
within(com.xys.service.*)
// 匹配指定包中的所有的方法, 包括子包
within(com.xys.service..*)
// 匹配当前包中的指定类中的方法
within(UserService)
// 匹配一个接口的所有实现类中的实现的方法
within(UserDao+)
Bean名の一致
// 匹配以指定名字结尾的 Bean 中的所有方法
bean(*Service)
カットポイント式の組み合わせ
// 匹配以 Service 或 ServiceImpl 结尾的 bean
bean(*Service || *ServiceImpl)
// 匹配名字以 Service 结尾, 并且在包 com.xys.service 中的 bean
bean(*Service) && within(com.xys.service.*)
文のアドバイス
アドバイスやポイントカットの発現と関連する、および/実行の点マッチング法に参加する前/後に周りに実行されます。 pointcut 表达式可以是简单的一个 pointcut 名字的引用, 或者是完整的 pointcut 表达式
。ここでは一例として、いくつかの簡単なアドバイスを持って、アドバイスを宣言する方法を見A。
アドバイスの前に
/**
* @author xiongyongshun
* @version 1.0
* @created 16/9/9 13:13
*/
@Component
@Aspect
public class BeforeAspectTest {
// 定义一个 Pointcut, 使用 切点表达式函数 来描述对哪些 Join point 使用 advise.
@Pointcut("execution(* com.xys.service.UserService.*(..))")
public void dataAccessOperation() {
}
}
@Component
@Aspect
public class AdviseDefine {
// 定义 advise
@Before("com.xys.aspect.PointcutDefine.dataAccessOperation()")
public void doBeforeAccessCheck(JoinPoint joinPoint) {
System.out.println("*****Before advise, method: " + joinPoint.getSignature().toShortString() + " *****");
}
}
ここでは、 @Beforeは ポイントカットを引用し、すなわち「com.xys.aspect.PointcutDefine.dataAccessOperationは()」することができます、構築されたポイントカットで、私たちのアドバイス場合はポイントカットの名前です。
@Component
@Aspect
public class AdviseDefine {
// 将 pointcut 和 advice 同时定义
@Before("within(com.xys.service..*)")
public void doAccessCheck(JoinPoint joinPoint) {
System.out.println("*****doAccessCheck, Before advise, method: " + joinPoint.getSignature().toShortString() + " *****");
}
}
周りのアドバイス
むしろ特別なアドバイスを中心に、それは前と異なる操作方法を後にする前に追加することができ、場合でも、どのようにしてマッチング方法を呼び出すかどうかを決定することができます。
@Component
@Aspect
public class AdviseDefine {
// 定义 advise
@Around("com.xys.aspect.PointcutDefine.dataAccessOperation()")
public Object doAroundAccessCheck(ProceedingJoinPoint pjp) throws Throwable {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
// 开始
Object retVal = pjp.proceed();
stopWatch.stop();
// 结束
System.out.println("invoke method: " + pjp.getSignature().getName() + ", elapsed time: " + stopWatch.getTotalTimeMillis());
return retVal;
}
}
アドバイスの周りにほとんどの前にアドバイスする前に、しかし、我々はノート持っ @Beforeの ように変更@Around アップ。