创建自定义注解
1.连接点(Joinpoint) 描述的是位置
2.切点(Pointcut) 本质上就是方法
3.通知(Advice) 通知又叫增强 就是具体增强的代码
4.切面(Aspect) 切点+通知
5.织入(Weaving) 通知应用到对象上的过程
6.代理对象(Proxy) 一个目标对象织入通知后产生的对象
7.目标对象(Target)被织入通知的对象
import java.lang.annotation.*;
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface TestAno {
//String类型
public String info1() default "";
//支持基本类型 封装类不可以
public int info2() default 0;
//枚举类型 必须定义枚举
public EnumInfo info3() default EnumInfo.No;
public enum EnumInfo{
No(1),YES(2);
private final int value;
EnumInfo(int val){
value=val;
}
public int value(){return this.value;}
}
}
#切面处理
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
@Aspect
@Order(1)//指定切面的优先级 数值越小越优先
@Component
public class TestAnoAspect {
/**
* execution(注解(非必)?修饰符(非必)?返回值类型(非必) 类型声明(非必)?方法名((必填)参数)异常(非必)?)
* execution(*(返回类型) 类路径.方法(参数 ..标识任意参数))
* execution(* cn.school.Studnet.*(..)) Studnet这个类下的所有方法都执行
* execution(* cn.school..*(..)) cn.school包下所有子包
* @annotation(使用注解的路径)
*/
@Pointcut("@annotation(com.movedatasource.config.TestAno)")
// @Pointcut("execution(* cn.school..*(..)")
public void doPointcut() {
/**
public interface JoinPoint {
String toString(); //连接点所在位置的相关信息
String toShortString(); //连接点所在位置的简短相关信息
String toLongString(); //连接点所在位置的全部相关信息
Object getThis(); //返回AOP代理对象
Object getTarget(); //返回目标对象
Object[] getArgs(); //返回被通知方法参数列表
Signature getSignature(); //返回当前连接点签名
SourceLocation getSourceLocation();//返回连接点方法所在类文件中的位置
String getKind(); //连接点类型
StaticPart getStaticPart(); //返回连接点静态部分
}
public interface ProceedingJoinPoint extends JoinPoint {
public Object proceed() throws Throwable;
public Object proceed(Object[] args) throws Throwable;
}
public interface StaticPart {
Signature getSignature(); //返回当前连接点签名
String getKind(); //连接点类型
int getId(); //唯一标识
String toString(); //连接点所在位置的相关信息
String toShortString(); //连接点所在位置的简短相关信息
String toLongString(); //连接点所在位置的全部相关信息
}
*/
}
/**
* 前置方法,在目标方法执行前执行
* @param joinPoint 封装了代理方法信息的对象,若用不到则可以忽略不写
*/
@Before("doPointcut()")
public void beForeChange(JoinPoint joinPoint){
System.err.println("-------执行了@Before");
//获得注解
TestAno annotation = getAnnotation(joinPoint, TestAno.class);
System.out.println("目标方法名为:" + joinPoint.getSignature().getName());
System.out.println("目标方法所属类的简单类名:" + joinPoint.getSignature().getDeclaringType().getSimpleName());
System.out.println("目标方法所属类的类名:" + joinPoint.getSignature().getDeclaringTypeName());
System.out.println("目标方法声明类型:" + Modifier.toString(joinPoint.getSignature().getModifiers()));
//获取传入目标方法的参数
Object[] args = joinPoint.getArgs();
for (int i = 0; i < args.length; i++) {
System.out.println("第" + (i+1) + "个参数为:" + args[i]);
}
System.out.println("被代理的对象:" + joinPoint.getTarget());
System.out.println("代理对象自己:" + joinPoint.getThis());
}
/**
* 后置通知:在目标方法执行后(无论是否发生异常),执行的通知
* @param joinPoint
*/
@After("doPointcut()")
public void afterChange(JoinPoint joinPoint){
System.err.println("-------执行了@@After");
TestAno annotation = getAnnotation(joinPoint, TestAno.class);
}
/**
* 返回通知:方法正常结束后执行,返回通知是可以访问到方法的返回值的!!!
* @param joinPoint
* @param result
*/
@AfterReturning(value = "doPointcut()",returning = "result")
public void afterReturningChange(JoinPoint joinPoint,Object result){
System.err.println("-------执行了@AfterReturning");
System.out.println(result);
}
/**
* 异常通知:可以访问到异常对象:且可以!!指定在出现特定异常时在执行通知!!,如果是修改为nullPointerException里,只有空指针异常才会执行
* @param joinPoint
* @param except
*/
@AfterThrowing(value = "doPointcut()", throwing = "except")
public void afterThrowingChange(JoinPoint joinPoint, Exception except){
System.err.println("-------执行了@AfterThrowing");
System.out.println(except.getMessage());
}
/**
* 5、环绕通知 需要携带 ProceedingJoinPoint 类型的参数.
* 环绕通知类似于动态代理的全过程: ProceedingJoinPoint 类型的参数可以决定是否执行目标方法.
* 且环绕通知必须有返回值, 返回值即为目标方法的返回值
* Object proceed(Object[] var1) throws Throwable 传入的新的参数去执行目标方法
*/
@Around("doPointcut()")
public Object aroundChange(ProceedingJoinPoint point) throws InterruptedException {
Object result = null;
Thread.sleep(2000);
System.err.println("-------执行了@Around");
try {
//前置通知
System.out.println("方法执行前...");
//获得注解参数
TestAno annotation = getAnnotation(point, TestAno.class);
System.out.println("注解参数:"+annotation.info1());
System.out.println("注解参数:"+annotation.info2());
System.out.println("注解参数:"+annotation.info3().value());
//获取请求参数
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
request.getParameterMap().forEach((k,v)->{
System.out.println("k:"+k + "v:" + v);
});
//执行目标方法
//result = pjd.proeed();
//用新的参数值执行目标方法
result = point.proceed(new Object[]{"newSpring"});
//返回通知
System.out.println("方法返回结果后...");
} catch (Throwable e) {
//异常通知
System.out.println("执行方法异常后...");
throw new RuntimeException(e);
}
//后置通知
System.out.println("方法执行后...");
return result;
}
/**
* 是否存在注解,如果存在就获取
*/
private <T extends Annotation> T getAnnotation(JoinPoint joinPoint, Class<T> clazz) {
try{
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
Method method = methodSignature.getMethod();
String[] parameterNames = methodSignature.getParameterNames();
if (method != null) {
return method.getAnnotation(clazz);
}
return null;
}catch (Exception e){
e.printStackTrace();
return null;
}
}
}