通知SpringAOPとどのようにいくつかの種類は、単純な通知を作成することを言って、アドレスを参照してください
まず、開始点は何ですか
前の例では、我々は、ターゲットクラスを取得し、その後、通知を作成するProxyFactory方法を作成することができます。通知の異なる種類を通して、あなたは、これらのメソッドに異なることを行うことができます。しかし、この方法ですべてのメソッドは、クラス全体での役割が、我々は、このクラスの通知処理をしたい方法の一部に多くの時間を持つことになります、正確に特定のメソッドへのエントリポイントを制御するために使用されるだろう
- 言い換えれば、私たちの開始点は、いくつかのルールの定義と同様のクラス(正確な方法)を決定するために、そしてクラスと一致するルールを見つけるために、このことを知って、はるかに簡単見下し使用方法であり、 A。
第二に、分類のエントリポイント
あなたは春にエントリポイントを作成したい場合は、ポイントカットのクラスを実現します。
package org.springframework.aop;
public interface Pointcut{
ClassFilter getClassFilter();
MethodMatcher getMethodMacher();
}
二つ以上のクラスのメソッドは、以下のソースコードを返します。
- ClassFilter
package org.springframework.aop;
/**
* 这是一个函数式接口,就是传入一个类,
* 如果这个类满足我们的要求,就返回true
* 也就是说这个切入点适用于这个类(也就是这个类不匹配我们的规则)
*/
@FunctionalInterface
public interface ClassFilter {
boolean matches(Class<?> var1);
}
- MethodMatcher
package org.springframework.aop;
import java.lang.reflect.Method;
/**
* 这个当然就是用来匹配方法了,
* 有两种类型,动态和静态,这个由isRuntime()的返回值来决定,true就是动态,false就是静态。这个类型就是决定了这个切入点是动态的还是静态的
*
*/
public interface MethodMatcher {
MethodMatcher TRUE = TrueMethodMatcher.INSTANCE;
//用于静态匹配,就是和方法的参数无关
boolean matches(Method var1, Class<?> var2);
boolean isRuntime();
//用于动态匹配,也就是和方法的参数有关,因为参数是会变的
boolean matches(Method var1, Class<?> var2, Object... var3);
}
要約すると、出発点は、追加費用をもたらす要件を満たしていない二つのタイプ、静的および動的エントリポイントエントリポイント、各引数の動的検査方法へのエントリ・ポイントに分割されます。あなたができるならば、あなたは、静的なエントリポイントを使用しようとすることができます。
第三に、8つの実装クラスのエントリポイント
実装クラス | 説明 |
---|---|
org.springframework.aop.support.annotation.AnnotationMatchingPointcut | クラスやメソッドの特定のノートを見つけ、あなたはJDK5以上を必要とします |
org.springframework.aop.aspectj.AspectJExpressionPointcut | AspectJのは織工式のAspectJのポイントカット構文文を評価するために使用しました |
org.springframework.aop.support.ComposablePointcut | 組合せ中に2個以上のこのような組合のようなエントリポイント()と交点()操作などを用い |
org.springframework.aop.support.ControlFlowPointcut | フロー制御方法のあらゆる他の方法、すなわち一致特別なエントリポイントは、直接的または間接的に呼び出される別の方法の方法のいずれかの結果として、あります |
org.springframework.aop.support.JdkRegexpMethodPointcut | メソッド名JDK4以上にエントリポイントを定義するために正規表現を使用して |
org.springframework.aop.support.NameMatchMethodPointcut | 名前が示すように、これは名前のリストを一致させる簡単な方法であり、 |
org.springframework.aop.support.DynamicMethodMatcherPointcut | ダイナミックエントリポイントを作成するための基本クラスとしてクラス |
org.springframework.aop.support.StaticMethodMatcherPointcut | エントリポイントとして基底クラスの位置を作成します |
第四に、静的なエントリポイントを作成するために使用StaticMethodMatcherPointcut
- 、2つのメソッドをクラスを作成します。私たちの目標は、1つを出力する、アドバイスを周りに作成するためにのみ徒歩()メソッドにある「私はかわいい猫です。」
public class Cat {
public void sleep(){
System.out.println("sleep....");
}
public void walk(){
System.out.println("walking....");
}
}
- エントリポイントを作成します
public class MethodPointcutDemo extends StaticMethodMatcherPointcut {
@Override
public boolean matches(Method method, Class<?> aClass) {
return method.getName().equals("walk");
}
@Override
public ClassFilter getClassFilter() {
return clz -> clz == Cat.class;
// 上边的lambda表达式等于下边的这个
// return new ClassFilter() {
// @Override
// public boolean matches(Class<?> clz) {
// return clz == Cat.class;
// }
// };
}
}
ラムダ式のトップを見ることができhttps://www.cnblogs.com/Lyn4ever/p/11967959.htmlだけ書き込みラムダ式が背後にあるときに発生する、と記載されていません
この方法トップで、当然のことながら、私たちは、この方法は、より高いレベルを介して実装されているので、私たちはこのクラスでは裁判官に直接行くことができ、getClassFilter()メソッドを達成することはできませんCat.classはメソッドと一致しません
- 通知クラス(これはサラウンド通知を作成し、前のものと同じです)
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
public class CatAdvisor implements MethodInterceptor{
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
//最不靠谱的方法,我们可以在这里判断这个method的是不是walk,从而要不要进行通知
System.out.println("I am a cute Cat.");
Object proceed = invocation.proceed();
return proceed;
}
}
もちろん、ここで我々はまた、メソッド名とクラス名を決定し、なぜエントリポイントはまだ使用することができます。しかし、これは、我々はより柔軟で通知するためのメソッドのエントリポイントクラス、、を介して制御され、当社のロジック・コード、ここで認識する必要があり、飛ぶことはありません。
- 試験方法
public static void main(String[] args) {
Cat cat = new Cat();
Pointcut pointcut = new MethodPointcutDemo();//切入点实例
Advice advice = new CatAdvisor();//通知类实例(就是我们的通知代码存放的类的对象)
Advisor advisor = new DefaultPointcutAdvisor(pointcut, advice);//切面类,就是切入点和通知类的集合
ProxyFactory proxyFactory = new ProxyFactory();
//和之前代码的区别就是这一句,这里我们使用的是切入点控制,如果把这句注释了,就要用设置通知类
proxyFactory.addAdvisor(advisor);//设置切面类,包含切入点(控制通知点)和通知类(逻辑代码)
//如果注释了上面一句,用这一句的话,就会对这个类中的所有方法都通知
// proxyFactory.addAdvice(advice);//设置通知类
proxyFactory.setTarget(cat);
Cat proxy = (Cat) proxyFactory.getProxy();
proxy.sleep();
proxy.walk();
}
業績は、私たちがそれを望むものを肯定します
sleep....
I am a cute Cat.
walking....
第五に、使用することは、ダイナミックなエントリーポイントを作成DyanmicMatcherPointcut
通知が実行され、上部および静的エントリポイントは同じであるが、メソッドに渡されたパラメータは、特定の要件を満たすための時間を可能にすることです。スペースの都合のために、私はあなたが読んで、この記事の末尾にコードをダウンロードすることができ、書いてはいけません。
実装クラスの六、ポイントカットの他のタイプ
1.単純な名前マッチング(NameMatchMethodPointcut)
ターゲットクラスまたはクラスの前にして、Catクラスの通知、実装クラスの前にエントリポイントが書いていない、このクラスはデフォルトの実装を行っているので、そのソースコードに興味を持って缶の外観は、非常にシンプルな、クラス名と一致することであり、私たちは、ほぼ静的なエントリポイントを作成しました。
public class NameMatchPointcutDemo {
public static void main(String[] args) {
Cat cat = new Cat();
//这个类已经是个实现类,我们就不需要再去写实现类了
NameMatchMethodPointcut pointcut = new NameMatchMethodPointcut();
pointcut.addMethodName("walk");
Advisor advisor = new DefaultPointcutAdvisor(pointcut,new CatAdvisor());
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.addAdvisor(advisor);
proxyFactory.setTarget(cat);
Cat proxy = (Cat) proxyFactory.getProxy();
proxy.sleep();
proxy.walk();
}
}
2.エントリポイントを作成するための正規表現(JdkRegexpMethodPointcut)
ただ、テストクラスを作成し、他は同じトップです
public class JdkRegexpPointcutDemo {
public static void main(String[] args) {
Cat cat = new Cat();
JdkRegexpMethodPointcut pointcut = new JdkRegexpMethodPointcut();
pointcut.setPattern(".*ee.*");//匹配中间有ee字母的,sleep()
Advisor advisor = new DefaultPointcutAdvisor(pointcut,new CatAdvisor());
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.addAdvisor(advisor);
proxyFactory.setTarget(cat);
Cat proxy = (Cat) proxyFactory.getProxy();
proxy.sleep();
proxy.walk();
}
}
3. AspectJのエントリポイントを作成するためのポイントカット式(AspectJExpressionPointcut)
AspectJのを使用している場合、その依存関係に参加するには
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.1</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.1</version>
</dependency>
public class AspectJExpressionPointcutDemo {
public static void main(String[] args) {
Cat cat = new Cat();
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression("execution(* walk*(..))");
Advisor advisor = new DefaultPointcutAdvisor(pointcut, new CatAdvisor());
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.addAdvisor(advisor);
proxyFactory.setTarget(cat);
Cat proxy = (Cat) proxyFactory.getProxy();
proxy.sleep();
proxy.walk();
}
}
散歩のどれ始まり、任意の方法で任意のパラメータと戻り値を有する:式の実行は、この手段
4.作成注釈一致するエントリポイント(AnnotationMatchingPointcut)
まず、本当に理解していない場合は、参照カスタム注釈Javaのカスタムクラスのノート、および使用それらの
/**
* 这个注解是用于运行时期、可用于类、方法上
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.METHOD})
public @interface MyAdvice {
}
そして、ターゲットメソッドに(通知するように)メモを追加
/**
* 为了不与之前的冲突,就新写了一个方法
*/
@MyAdvice
public void eat(){
System.out.println("eating....");
}
そして、mainメソッド内のコメントの名前を指定します。
public class AnnotationPointcutDemo {
public static void main(String[] args) {
Cat cat = new Cat();
AnnotationMatchingPointcut pointcut = AnnotationMatchingPointcut
.forMethodAnnotation(MyAdvice.class);
//这个类还有一个.forClassAnnotation()方法,就是指定类的
Advisor advisor = new DefaultPointcutAdvisor(pointcut, new CatAdvisor());
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.addAdvisor(advisor);
proxyFactory.setTarget(cat);
Cat proxy = (Cat) proxyFactory.getProxy();
proxy.sleep();//不会被通知
proxy.walk();//不会被通知
proxy.eat();//会被通知
}
}