JointPoint是程序运行过程中可识别的点,这个点可以用来作为AOP切入点。JointPoint对象则包含了和切入相关的很多信息。比如切入点的对象,方法,属性等。我们可以通过反射的方式获取这些点的状态和信息,用于追踪tracing和记录logging应用信息。
# 返回目标对象,即被代理的对象
Object getTarget();
# 返回切入点的参数
Object[] getArgs();
# 返回切入点的Signature
Signature getSignature();
# 返回切入的类型,比如method-call,field-get等等,感觉不重要
String getKind();
环绕通知 = 前置 + 目标方法执行 + 后置通知,proceed方法就是用于启动目标方法的执行。暴露出这个方法,就能支持 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;
}
注解(Annotation)是撰写在原始码中的资讯,可以提供代码以外的额外资讯,本身有其结构,你可以使用工具提取这些结构化讯息。
简单来说注解就是写在程序上方的结构化注释,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 :注解只被保留到编译进行的时候,它并不会被加载到 JVM 中;
RetentionPolicy.RUNTIME :注解可以保留到程序运行的时候,它会被加载进入到 JVM 中,所以在程序运行时可以获取到注解。
注解:
@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 "";
}