1. JoinPoint クラス、Proceedingjoinpoint クラス
1. springboot を使用して AOP を記述する場合、プロキシ クラスとプロキシ クラスに関する情報を取得するために使用されるJoinPoint クラスがあります。
JointPointはプログラム実行中に識別可能なポイントであり、AOP エントリ ポイントとして使用できます。JointPoint オブジェクトには、カットに関連する多くの情報が含まれています。エントリ ポイント オブジェクト、メソッド、プロパティなど。リフレクションを通じてこれらのポイントのステータスと情報を取得できます。これは、ロギング アプリケーション情報の追跡と記録に使用されます。
# 返回目标对象,即被代理的对象
Object getTarget();
# 返回切入点的参数
Object[] getArgs();
# 返回切入点的Signature
Signature getSignature();
# 返回切入的类型,比如method-call,field-get等等,感觉不重要
String getKind();
2.後続のjoinpointはJoinPointを継承します。continue メソッドは JoinPoint に基づいて公開されます。
サラウンド通知 = 事前 + ターゲット メソッドの実行 + 事後通知. continue メソッドは、ターゲット メソッドの実行を開始するために使用されます。このメソッドを公開すると、aop:around などの側面をサポートできます。
( Proceedingjoinpoint はサラウンド通知 @Around のみをサポートし、他のアスペクトは JoinPoint のみを使用する必要があります。これは、サラウンド通知と事前通知および事後通知メソッドの最大の違いでもあります。これはアスペクト タイプに関連します)
注:
joinpoint.getSignature(): 拡張メソッドに関する情報を取得します。
joinpoint.getSignature で取得したオブジェクトを実装クラス MethodSignature に強制変換した後、内部の getReturnType() メソッドを使用して対象メソッドの戻り値の型を取得できます。
@Before("customerJoinPointerExpression()")
public void beforeMethod(JoinPoint joinPoint){
// 前置通知
joinPoint.getSignature().getName(); // 获取目标方法名
joinPoint.getSignature().getDeclaringType().getSimpleName(); // 获取目标方法所属类的简单类名
joinPoint.getSignature().getDeclaringTypeName(); // 获取目标方法所属类的类名
joinPoint.getSignature().getModifiers(); // 获取目标方法声明类型(public、private、protected)
Object[] args = joinPoint.getArgs(); // 获取传入目标方法的参数,返回一个数组
joinPoint.getTarget(); // 获取被代理的对象
joinPoint.getThis(); // 获取代理对象自己
}
// 匹配方法执行连接点方式
@Around(value = "execution(* *..SomeserviceImpl.Dofirst(..))")
public Object myAspectJ(ProceedingJoinPoint point) throws Throwable {
//拦截的实体类
Object target = point.getTarget();
//拦截的方法名称
String methodName = point.getSignature().getName();
//拦截的方法参数
Object[] args = point.getArgs();
//拦截的放参数类型
Class[] parameterTypes = ((MethodSignature)point.getSignature()).getMethod().getParameterTypes();
object = point.proceed(); //目标方法的执行
return null;
}
2. アノテーション情報を取得するための AOP サラウンド通知
1.コンセプト
注釈はソース コードに記述された情報です。コードを超えた追加情報を提供できます。独自の構造を持っています。ツールを使用して、この構造化された情報を抽出できます。
簡単に言えば、アノテーションはプログラムの上に書かれた構造化されたコメントであり、Java はその構造に従ってメッセージを読み取り、対応する操作を実行します。
たとえば、メソッドに @Override アノテーションがマークされている場合、Java はコンパイル中に現在のメソッドが親クラスのメソッドをオーバーロードするかどうかをチェックし、そうでない場合はエラーが報告されます。
Java には標準のアノテーションが付いています
。@Override: 現在のメソッド定義が親クラスのメソッドをオーバーライドすることを示します。@
Deprecated: コードが非推奨であることを示し、@Deprecated アノテーションが付けられたコードが使用されるとコンパイラは警告を発行します
。 SuppressWarnings: コンパイラの警告メッセージをオフにすることを示します。
上記のアノテーションを使用して独自のアノテーションを生成します。クラスを自分で定義するのと同じように、@interface を通じてカスタム アノテーションを作成できます。
[@Target] //限定注解可以标注的位置:ANNOTATION_TYPE、CONSTRUCTOR 、FIELD 、LOCAL_VARIABLE 、METHOD 、PACKAGE 、PARAMETER 、TYPE
[@Retention] //说明了这个注解的存活时间 :SOURCE,CLASS ,RUNTIME
[@Documented] // 将注解中的元素包含到 Javadoc 中去
[@Inherited] //子类自动拥有父类的注解
public @interface [名称] {
// 元素
String value() default "hello";
}
[@Retention]
RetentionPolicy.SOURCE: 注釈はソース コード段階でのみ保持され、コンパイラーのコンパイル時に破棄および無視されます。 RetentionPolicy.CLASS
: 注釈はコンパイルが進行中であるまでのみ保持され、保持されません。 ; RetentionPolicy.RUNTIME
: アノテーションはプログラムが実行されるまで保持され、JVM にロードされるため、プログラムの実行中にアノテーションを取得できます。
2. コード例
注釈:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AopCache
{
/**
* 每个方法唯一的key
*/
String key();
}
セクションタイプ:
@Aspect //标注增强处理类(切面类)
@Component //交由Spring容器管理
@Order(0) //设置优先级,值越低优先级越高
public class MyaspectJ {
//定义增强,pointcut连接点使用@annotation(xxx)进行定义
@Pointcut(value = "@annotation(xx.xx.xx.AopCache)")
public void methodPointcut(){}
// 匹配方法执行连接点方式
@Around("methodPointcut()")
public Object myAspectJ(ProceedingJoinPoint point) throws Throwable {
// 获取方法上的注解
MethodSignature methodSignature = (MethodSignature) point.getSignature();
Method method = methodSignature.getMethod();
AopCache annotation = method.getAnnotation(AopCache.class);
//获取key
String key = annotation.key();
object = point.proceed(); // 1. 目标方法的调用
return null;
}
}
メソッドがこのアノテーションを使用する場合、アスペクト拡張を直接実行します。
@AopCache(key = "自定义key值")
public String getAllType(){
return "";
}