• SpringAOP入门案例


    在这里插入图片描述

    package com.elf.spring.aop.aspectj;
    /**
     * @author 45
     * @version 1.0
     */
    public interface UsbInterface {
        public void work();
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    package com.elf.spring.aop.aspectj;
    import org.springframework.stereotype.Component;
    /**
     * @author 45
     * @version 1.0
     */
    @Component //把Phone对象当做一个组件注入容器
    public class Phone implements UsbInterface{
        @Override
        public void work() {
            System.out.println("手机开始工作了....");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    package com.elf.spring.aop.aspectj;
    import org.springframework.stereotype.Component;
    /**
     * @author 45
     * @version 1.0
     */
    @Component //将Camera注入到spring容器
    public class Camera implements UsbInterface {
        @Override
        public void work() {
            System.out.println("相机开始工作...");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    package com.elf.spring.aop.aspectj;
    
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.Signature;
    import org.aspectj.lang.annotation.*;
    import org.springframework.core.annotation.Order;
    import org.springframework.stereotype.Component;
    
    import java.util.Arrays;
    
    /**
     * @author 45
     * @version 1.0
     * 切面类 , 类似于我们以前自己写的MyProxyProvider,但是功能强大很多
     *
     */
    @Order(value = 2)//表示该切面类执行的顺序, value的值越小, 优先级越高
    @Aspect //表示是一个切面类[底层切面编程的支撑(动态代理+反射+动态绑定...)]
    @Component //会注入SmartAnimalAspect到容器
    public class SmartAnimalAspect {
    
    
        //定义一个切入点, 在后面使用时可以直接引用, 提高了复用性
        @Pointcut(value = "execution(public float com.elf.spring.aop.aspectj.SmartDog.getSum(float, float)))")
        public void myPointCut() {
        }
    
        //希望将f1方法切入到SmartDog-getSum前执行-前置通知
    
        /**
         * 解读
         * 1. @Before 表示前置通知:即在我们的目标对象执行方法前执行
         * 2. value = "execution(public float com.elf.spring.aop.aspectj.SmartDog.getSum(float, float)
         * 指定切入到哪个类的哪个方法  形式是: 访问修饰符 返回类型 全类名.方法名(形参列表),
         *     带形参列表是因为方法名可能相同,参数个数不同构成重载,以便区分.
         * 3. showBeginLog方法可以理解成就是一个切入方法, 这个方法名是可以程序员指定  比如:showBeginLog
         * 4. JoinPoint joinPoint 在底层执行时,由AspectJ切面框架, 会给该切入方法传入 joinPoint对象
         * , 通过该方法,程序员可以获取到 相关信息
         *
         * @param joinPoint
         */
        //@Before(value = "execution(public float com.elf.spring.aop.aspectj.SmartDog.getSum(float, float))")
        //这里我们使用定义好的切入点
        @Before(value = "myPointCut()")
        //如果说是一个切入方法,那么形参是JoinPoint joinPoint,用aop来做的开发主要是由aspectj框架来支撑的
        public void showBeginLog(JoinPoint joinPoint) {
            //通过连接点对象joinPoint 可以获取方法签名
            Signature signature = joinPoint.getSignature();
            //signature.getName()方法签名指的是:com.elf.spring.aop.aspectj.SmartDog.getSum
            System.out.println("SmartAnimalAspect-切面类showBeginLog()[使用的myPointCut()]-方法执行前-日志-方法名-" + signature.getName() + "-参数 "
                    + Arrays.asList(joinPoint.getArgs()));//(float, float)
        }
    
        //返回通知:即把showSuccessEndLog方法切入到目标对象方法正常执行完毕后的地方
        //老韩解读
        //1. 如果我们希望把目标方法执行的结果,返回给切入方法
        //2. 可以再 @AfterReturning 增加属性 , 比如 returning = "res"
        //3. 同时在切入方法增加 Object res
        //4. 注意: returning = "res" 和 Object res 的 res名字一致
        //@AfterReturning(value = "execution(public float com.elf.spring.aop.aspectj.SmartDog.getSum(float, float))", returning = "res")
        //使用切入点
        @AfterReturning(value = "myPointCut()", returning = "res")
        public void showSuccessEndLog(JoinPoint joinPoint, Object res) {
            Signature signature = joinPoint.getSignature();
            System.out.println("SmartAnimalAspect-切面类showSuccessEndLog()-方法执行正常结束-日志-方法名-" + signature.getName() + " 返回的结果是=" + res);
        }
    
    
        //异常通知:即把showExceptionLog方法切入到目标对象方法执行发生异常的的catch{}
        //@AfterThrowing(value = "execution(public float com.elf.spring.aop.aspectj.SmartDog.getSum(float, float))", throwing = "throwable")
        //直接使用切入点表达式
        @AfterThrowing(value = "myPointCut()", throwing = "throwable")
        public void showExceptionLog(JoinPoint joinPoint, Throwable throwable) {
            Signature signature = joinPoint.getSignature();
            System.out.println("SmartAnimalAspect-切面类showExceptionLog()-方法执行异常-日志-方法名-" + signature.getName() + " 异常信息=" + throwable);
        }
    
        //最终通知:即把showFinallyEndLog方法切入到目标方法执行后(不管是否发生异常,都要执行 finally{})
        //@After(value = "execution(public float com.elf.spring.aop.aspectj.SmartDog.getSum(float, float))")
        //直接使用切入点
        @After(value = "myPointCut()")
        public void showFinallyEndLog(JoinPoint joinPoint) {
            Signature signature = joinPoint.getSignature();
            System.out.println("SmartAnimalAspect-切面类showFinallyEndLog()-方法最终执行完毕-日志-方法名-" + signature.getName());
        }
    
        //新的前置通知
        //@Before(value = "execution(public void com.elf.spring.aop.aspectj.Phone.work()) || execution(public void com.elf.spring.aop.aspectj.Camera.work())")
        //public void hi(JoinPoint joinPoint) {
        //    Signature signature = joinPoint.getSignature();
        //    System.out.println("切面类的hi()-执行的目标方法-" + signature.getName());
        //}
    
        //切入表达式也可以指向接口的方法, 这时切入表达式会对实现了接口的类/对象生效
        //比如下面我们是对UsbInterface 切入,那么对实现类Phone 和 Camera对象都作用了
        @Before(value = "execution(public void com.elf.spring.aop.aspectj.UsbInterface.work())")
        public void hi(JoinPoint joinPoint) {
            Signature signature = joinPoint.getSignature();
            System.out.println("切面类的hi()-执行的目标方法-" + signature.getName());
        }
    
    
        //给Car配置一个前置通知,即将ok1()方法切入到Car类的run()方法前
        @Before(value = "execution(public void Car.run())")
        public void ok1(JoinPoint joinPoint) {
    
            Signature signature = joinPoint.getSignature();
            System.out.println("切面类的ok1()-执行的目标方法-" + signature.getName());
    
        }
    
        //返回通知
        @AfterReturning(value = "execution(public void Car.run())")
        public void ok2(JoinPoint joinPoint) {
    
            Signature signature = joinPoint.getSignature();
            System.out.println("切面类的ok2()-执行的目标方法-" + signature.getName());
    
        }
    
        //异常通知
        @AfterThrowing(value = "execution(public void Car.run())")
        public void ok3(JoinPoint joinPoint) {
    
            Signature signature = joinPoint.getSignature();
            System.out.println("切面类的ok3()-执行的目标方法-" + signature.getName());
    
        }
    
        //后置通知
        @After(value = "execution(public void Car.run())")
        public void ok4(JoinPoint joinPoint) {
    
    
            Signature signature = joinPoint.getSignature();
            System.out.println("切面类的ok4()-执行的目标方法-" + signature.getName());
            //演示一下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(); // 获取代理对象自己
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    package com.elf.spring.aop.aspectj;
    import org.junit.jupiter.api.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    /**
     * @author 45
     * @version 1.0
     */
    public class AopAspectjTest {
    
        @Test
        public void smartDogTestByProxy() {
    
            //得到spring容器
            ApplicationContext ioc =
                    new ClassPathXmlApplicationContext("beans08.xml");
            //这里我们需要通过接口类型来获取到注入的SmartDog对象-就是代理对象
            SmartAnimalable smartAnimalable =
                    ioc.getBean(SmartAnimalable.class);
    
            //SmartAnimalable smartAnimalable =
            //        (SmartAnimalable)ioc.getBean("smartDog");
    
            smartAnimalable.getSum(10, 2);
    
            System.out.println("smartAnimalable运行类型="
                    + smartAnimalable.getClass());
    
            System.out.println("=============================");
    
            //smartAnimalable.getSub(100, 20);
    
        }
    
        @Test
        public void smartDogTestByProxy2() {
    
            //得到spring容器
            ApplicationContext ioc =
                    new ClassPathXmlApplicationContext("beans08.xml");
    
            UsbInterface phone = (UsbInterface) ioc.getBean("phone");
            UsbInterface camera = (UsbInterface) ioc.getBean("camera");
    
            phone.work();
    
            System.out.println("==================");
    
            camera.work();
    
        }
    
        @Test
        public void test3() {
            //得到spring容器
            ApplicationContext ioc =
                    new ClassPathXmlApplicationContext("beans08.xml");
    
            Car car = ioc.getBean(Car.class);
    
            //说明: car对象仍然是代理对象
            System.out.println("car的运行类型=" + car.getClass());
    
            car.run();
    
        }
    
        @Test
        public void testDoAround() {
            //得到spring容器
            ApplicationContext ioc =
                    new ClassPathXmlApplicationContext("beans08.xml");
    
    
            SmartAnimalable smartAnimalable =
                    ioc.getBean(SmartAnimalable.class);
    
            smartAnimalable.getSum(10, 2);
        }
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
  • 相关阅读:
    Hadoop中的Yarn 生产环境核心参数配置案例、Yarn 案例实操(一)
    数据结构学习笔记
    雪花算法(snowflake)
    文件管理革命:突破限制,实现无限次复制粘贴
    整型int的拼接和拆分
    【C语言】程序环境和预处理
    Java多线程探究【四线程协作】
    手把手教你电机FOC控制【三】
    SpringBoot 多模块 多环境 项目 单元测试
    多线程&并发篇---第十篇
  • 原文地址:https://blog.csdn.net/weixin_45036508/article/details/133069272