Spring AOP+annotation注解的整合使用

创建自定义注解

     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;
        }
    }

}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值