Spring-AOP

慈云数据 7个月前 (04-27) 技术支持 40 0

文章目录

    • 1.基本介绍
        • 1.什么是AOP?
        • 2.示意图
        • 3.五种通知
        • 2.AOP快速入门
            • 1.入门案例
              • 1.导入jar包
              • 2.Cal.java 接口
              • 3.CalImpl.java 实现类
              • 4.CalAspect.java 切面类
              • 5.beans06.xml 开启注解功能
              • 6.测试
              • 2.细节说明
              • 3.AOP理解(重点)
                • 1.使用场景
                • 2.代理对象理解
                • 3.AOP的实现方式
                • 4.简化的AOP实现方式
                • 4.课后练习
                  • 1.题目
                  • 2.答案
                    • 1.UsbInterface.java
                    • 2.Camera.java
                    • 3.Phone.java
                    • 4.Aspect.java
                    • 5.beans06.xml
                    • 6.测试
                    • 3.切入表达式
                        • 1.基本介绍
                        • 2.举例说明
                        • 3.注意事项和细节(重点)
                          • 1.切入表达式格式
                            • **注意:**
                            • 2.细节
                            • 3.Proxy和CGlib的区别
                            • 4.JoinPoint常用方法
                                • 1.基本介绍
                                • 2.代码实例(使用普通对象)
                                  • 1.Car.java
                                  • 2.Aspect02.java
                                  • 3.beans06.xml
                                  • 4.test.java
                                  • 5.返回通知获取结果
                                      • 代码实例
                                        • 修改Aspect02.java
                                        • 6.异常通知获取异常
                                            • 代码实例
                                              • 1.修改Car.java
                                              • 2.修改Aspect02.java
                                              • 7.环绕通知
                                                  • 代码实例
                                                    • 1.Dog.java
                                                    • 2.Aspect03.java
                                                    • 3.beans06.xml
                                                    • 4.Test.java
                                                    • 8.切入表达式重用
                                                        • 代码实例
                                                          • 1.Car.java
                                                          • 2.Aspect02.java
                                                          • 3.beans06.xml
                                                          • 4.测试
                                                          • 9.AOP多切面优先级问题
                                                                • 解释
                                                                • 10.根据xml配置AOP
                                                                    • 代码实例
                                                                      • 1.UsbInterface.java
                                                                      • 2.Camera.java
                                                                      • 3.Aspect.java
                                                                      • 4.beans07.xml
                                                                      • 5.测试
                                                                      • 11.课后练习
                                                                          • 1.注解实现
                                                                            • 1.Cal.java
                                                                            • 2.CalImpl.java
                                                                            • 3.Aspect_ann.java
                                                                            • 4.beans06.xml
                                                                            • 5.测试
                                                                            • 2.xml实现
                                                                              • 1.Cal.java
                                                                              • 2.CalImpl.java
                                                                              • 3.Aspect_xml.java
                                                                              • 4.beans08.xml
                                                                              • 5.测试

                                                                                1.基本介绍

                                                                                1.什么是AOP?

                                                                                image-20240220103241229

                                                                                2.示意图

                                                                                image-20240220105205993

                                                                                image-20240220105239393

                                                                                3.五种通知

                                                                                image-20240220110125266

                                                                                image-20240220110136565

                                                                                2.AOP快速入门

                                                                                1.入门案例
                                                                                1.导入jar包

                                                                                image-20240220110639212

                                                                                2.Cal.java 接口
                                                                                package com.sxs.spring.aop.aspectj;
                                                                                /**
                                                                                 * 计算数量的接口
                                                                                 *
                                                                                 * @author 孙显圣
                                                                                 * @version 1.0
                                                                                 */
                                                                                public interface Cal {
                                                                                    public double getSub(double num1, double num2);
                                                                                    public double getSum(double num1, double num2);
                                                                                }
                                                                                
                                                                                3.CalImpl.java 实现类
                                                                                package com.sxs.spring.aop.aspectj;
                                                                                import org.springframework.stereotype.Component;
                                                                                /**
                                                                                 * @author 孙显圣
                                                                                 * @version 1.0
                                                                                 */
                                                                                @Component //注解创建bean对象
                                                                                public class CalImpl implements Cal {
                                                                                    @Override
                                                                                    public double getSub(double num1, double num2) {
                                                                                        System.out.println("方法内部打印:" + (num1 - num2));
                                                                                        return num1 - num2;
                                                                                    }
                                                                                    @Override
                                                                                    public double getSum(double num1, double num2) {
                                                                                        System.out.println("方法内部打印:" + (num1 + num2));
                                                                                        return num1 + num2;
                                                                                    }
                                                                                }
                                                                                
                                                                                4.CalAspect.java 切面类
                                                                                package com.sxs.spring.aop.aspectj;
                                                                                import org.aspectj.lang.JoinPoint;
                                                                                import org.aspectj.lang.Signature;
                                                                                import org.aspectj.lang.annotation.*;
                                                                                import org.springframework.stereotype.Component;
                                                                                import java.lang.reflect.Method;
                                                                                import java.util.Arrays;
                                                                                /**
                                                                                 * 切面类
                                                                                 *
                                                                                 * @author 孙显圣
                                                                                 * @version 1.0
                                                                                 */
                                                                                @Component //自动创建bean对象
                                                                                @Aspect //切面类
                                                                                public class CalAspect {
                                                                                    /**
                                                                                     * @param joinPoint 保存了要切入的方法的信息
                                                                                     * @Before 前置通知
                                                                                     * execution(。。。) 切入表达式,表明要切入的方法,格式:格式:访问修饰符+返回类型 全类名 方法名(参数类型)
                                                                                     */
                                                                                    @Before(value = "execution(public double com.sxs.spring.aop.aspectj.CalImpl.getSub(double, double))")
                                                                                    public void before(JoinPoint joinPoint) {
                                                                                        //获取方法签名
                                                                                        Signature signature = joinPoint.getSignature();
                                                                                        System.out.println("方法执行开始-日志-方法名-" + signature.getName()
                                                                                                + "-参数" + Arrays.asList(joinPoint.getArgs()));
                                                                                    }
                                                                                    /**
                                                                                     * @param joinPoint 保存了要切入的方法的信息
                                                                                     * @AfterReturning 返回通知
                                                                                     */
                                                                                    @AfterReturning(value = "execution(public double com.sxs.spring.aop.aspectj.CalImpl.getSub(double, double))")
                                                                                    public void afterReturning(JoinPoint joinPoint) {
                                                                                        Signature signature = joinPoint.getSignature();
                                                                                        System.out.println("方法执行正常结束-日志-方法名-" + signature.getName()
                                                                                        );
                                                                                    }
                                                                                    /**
                                                                                     * @param joinPoint
                                                                                     * @AfterThrowing 异常通知
                                                                                     */
                                                                                    @AfterThrowing(value = "execution(public double com.sxs.spring.aop.aspectj.CalImpl.getSub(double, double))")
                                                                                    public void throwing(JoinPoint joinPoint) {
                                                                                        Signature signature = joinPoint.getSignature();
                                                                                        System.out.println("方法出现异常-日志-方法名-" + signature.getName()
                                                                                        );
                                                                                    }
                                                                                    /**
                                                                                     * @param joinPoint
                                                                                     * @After 后置通知
                                                                                     */
                                                                                    @After(value = "execution(public double com.sxs.spring.aop.aspectj.CalImpl.getSub(double, double))")
                                                                                    public void after(JoinPoint joinPoint) {
                                                                                        Signature signature = joinPoint.getSignature();
                                                                                        System.out.println("方法最终执行完毕-日志-方法名-" + signature.getName()
                                                                                        );
                                                                                    }
                                                                                }
                                                                                
                                                                                5.beans06.xml 开启注解功能
                                                                                
                                                                                
                                                                                    
                                                                                
                                                                                    
                                                                                
                                                                                
                                                                                6.测试
                                                                                package com.sxs.spring.aop.aspectj;
                                                                                import org.springframework.context.ApplicationContext;
                                                                                import org.springframework.context.support.ClassPathXmlApplicationContext;
                                                                                /**
                                                                                 * @author 孙显圣
                                                                                 * @version 1.0
                                                                                 */
                                                                                public class AopAspectjTest {
                                                                                    public static void main(String[] args) {
                                                                                        ApplicationContext ioc = new ClassPathXmlApplicationContext("beans06.xml");
                                                                                        //注意:这里需要使用接口类型来获取代理对象,然后使用代理对象来执行方法,才能实现切面编程
                                                                                        Cal bean = ioc.getBean(Cal.class);
                                                                                        bean.getSub(1,22);
                                                                                    }
                                                                                }
                                                                                

                                                                                image-20240220144144990

                                                                                2.细节说明

                                                                                image-20240220145619074

                                                                                3.AOP理解(重点)
                                                                                1.使用场景

                                                                                需要对接口对象/普通对象的方法进行额外的操作而不想修改源代码时使用

                                                                                2.代理对象理解

                                                                                从接口类型或者接口对象id获取的bean对象的运行类型都是代理对象,编译类型是接口类型,最终执行方法的对象是代理对象

                                                                                一个代理对象对应一个接口对象,在只有一个接口对象的时候才能使用类型来获取

                                                                                3.AOP的实现方式
                                                                                1. 编写接口
                                                                                2. 编写实现类,使用注解自动创建bean对象
                                                                                3. 编写切面类,使用注解
                                                                                  1. 自动创建bean对象
                                                                                  2. 标识切面类
                                                                                  3. 通知 + 切入表达式(切点)
                                                                                4. 编写xml文件
                                                                                  1. 扫描普通注解
                                                                                  2. 开启aop注解功能
                                                                                5. 使用方式
                                                                                  1. 使用id或者类型获取针对接口的代理对象
                                                                                  2. 使用代理对象执行方法
                                                                                4.简化的AOP实现方式
                                                                                1. 接口,接口对象(注解)
                                                                                2. 切面(注解),切面对象(注解)
                                                                                3. 通知 + 切点
                                                                                4. 使用方式
                                                                                  1. 使用id或者类型获取针对接口的代理对象
                                                                                  2. 使用代理对象执行方法
                                                                                4.课后练习
                                                                                1.题目

                                                                                image-20240220150422379

                                                                                2.答案
                                                                                1.UsbInterface.java
                                                                                package com.sxs.spring.aop.homework01;
                                                                                /**
                                                                                 * @author 孙显圣
                                                                                 * @version 1.0
                                                                                 */
                                                                                public interface UsbInterface {
                                                                                    public void work();
                                                                                }
                                                                                
                                                                                2.Camera.java
                                                                                package com.sxs.spring.aop.homework01;
                                                                                import org.springframework.stereotype.Component;
                                                                                /**
                                                                                 * @author 孙显圣
                                                                                 * @version 1.0
                                                                                 */
                                                                                @Component
                                                                                public class Camera implements UsbInterface{
                                                                                    @Override
                                                                                    public void work() {
                                                                                        System.out.println("相机正在工作。。。。。。");
                                                                                    }
                                                                                }
                                                                                
                                                                                3.Phone.java
                                                                                package com.sxs.spring.aop.homework01;
                                                                                import org.springframework.stereotype.Component;
                                                                                /**
                                                                                 * @author 孙显圣
                                                                                 * @version 1.0
                                                                                 */
                                                                                @Component
                                                                                public class Phone implements UsbInterface{
                                                                                    @Override
                                                                                    public void work() {
                                                                                        System.out.println("手机正在工作。。。。。。");
                                                                                    }
                                                                                }
                                                                                
                                                                                4.Aspect.java
                                                                                package com.sxs.spring.aop.homework01;
                                                                                import org.aspectj.lang.JoinPoint;
                                                                                import org.aspectj.lang.Signature;
                                                                                import org.aspectj.lang.annotation.Before;
                                                                                import org.springframework.stereotype.Component;
                                                                                /**
                                                                                 * @author 孙显圣
                                                                                 * @version 1.0
                                                                                 */
                                                                                @Component
                                                                                @org.aspectj.lang.annotation.Aspect
                                                                                public class Aspect {
                                                                                    @Before(value = "execution(* com.sxs.spring.aop.homework01.*.*(..))")
                                                                                    public void before(JoinPoint joinPoint) {
                                                                                        Signature signature = joinPoint.getSignature();
                                                                                        System.out.println("日志-方法执行前-方法名-" + signature.getName());
                                                                                    }
                                                                                }
                                                                                
                                                                                5.beans06.xml
                                                                                
                                                                                
                                                                                    
                                                                                
                                                                                    
                                                                                
                                                                                
                                                                                6.测试
                                                                                package com.sxs.spring.aop.homework01;
                                                                                import org.springframework.context.ApplicationContext;
                                                                                import org.springframework.context.support.ClassPathXmlApplicationContext;
                                                                                /**
                                                                                 * @author 孙显圣
                                                                                 * @version 1.0
                                                                                 */
                                                                                public class test {
                                                                                    public static void main(String[] args) {
                                                                                        ApplicationContext ioc = new ClassPathXmlApplicationContext("beans06.xml");
                                                                                        //通过id获取代理对象
                                                                                        UsbInterface bean1 = (UsbInterface) ioc.getBean("camera");
                                                                                        //执行方法
                                                                                        bean1.work();
                                                                                        //通过id获取代理对象
                                                                                        UsbInterface bean2 = (UsbInterface) ioc.getBean("phone");
                                                                                        //执行方法
                                                                                        bean2.work();
                                                                                    }
                                                                                }
                                                                                

                                                                                image-20240220154136556

                                                                                3.切入表达式

                                                                                1.基本介绍

                                                                                image-20240220154944257

                                                                                2.举例说明

                                                                                image-20240220155134259

                                                                                image-20240220155150216

                                                                                3.注意事项和细节(重点)
                                                                                1.切入表达式格式
                                                                                *(访问修饰符(空格)返回类型)(空格)*(全类名/接口名/简单类名/简单接口名).*(方法名)(..)(参数类型)
                                                                                简称: 星 星点星(点点)    
                                                                                
                                                                                注意:
                                                                                • 访问修饰符和返回类型可以使用单个*****来表示任意的,必须满足中间有空格,比如 public * …
                                                                                • 使用简单类名/简单接口名则必须与切面类在同一个包下
                                                                                • 如果配置了接口类型,则包括接口对象的所有方法
                                                                                  2.细节

                                                                                  image-20240220161248432

                                                                                  3.Proxy和CGlib的区别
                                                                                  • Proxy是针对接口的代理对象,可以执行接口的所有方法
                                                                                  • CGlib是针对父类的代理对象,可以执行该类的所有法

                                                                                    4.JoinPoint常用方法

                                                                                    1.基本介绍

                                                                                    image-20240220162304414

                                                                                    2.代码实例(使用普通对象)
                                                                                    1.Car.java
                                                                                    package com.sxs.spring.aop.joinpoint;
                                                                                    import org.springframework.stereotype.Component;
                                                                                    /**
                                                                                     * @author 孙显圣
                                                                                     * @version 1.0
                                                                                     */
                                                                                    @Component
                                                                                    public class Car {
                                                                                        public void run() {
                                                                                            System.out.println("Car在运行!");
                                                                                        }
                                                                                    }
                                                                                    
                                                                                    2.Aspect02.java
                                                                                    package com.sxs.spring.aop.joinpoint;
                                                                                    import org.aspectj.lang.JoinPoint;
                                                                                    import org.aspectj.lang.Signature;
                                                                                    import org.aspectj.lang.annotation.AfterReturning;
                                                                                    import org.springframework.stereotype.Component;
                                                                                    /**
                                                                                     * @author 孙显圣
                                                                                     * @version 1.0
                                                                                     */
                                                                                    @Component
                                                                                    @org.aspectj.lang.annotation.Aspect
                                                                                    public class Aspect02 {
                                                                                        //返回通知
                                                                                        @AfterReturning(value = "execution(* Car.run())")
                                                                                        public void afterReturning(JoinPoint joinPoint) {
                                                                                            System.out.println("方法执行完毕!");
                                                                                            Signature signature = joinPoint.getSignature();
                                                                                            System.out.println("name=" + signature.getName());
                                                                                            System.out.println("simpleName=" + signature.getDeclaringType().getSimpleName());
                                                                                            System.out.println("该方法所属类的类名=" + signature.getDeclaringTypeName());
                                                                                            System.out.println("参数=" + joinPoint.getArgs());
                                                                                        }
                                                                                    }
                                                                                    
                                                                                    3.beans06.xml
                                                                                    
                                                                                    
                                                                                        
                                                                                    
                                                                                        
                                                                                    
                                                                                    
                                                                                    4.test.java
                                                                                    package com.sxs.spring.aop.joinpoint;
                                                                                    import org.springframework.context.ApplicationContext;
                                                                                    import org.springframework.context.support.ClassPathXmlApplicationContext;
                                                                                    /**
                                                                                     * @author 孙显圣
                                                                                     * @version 1.0
                                                                                     */
                                                                                    public class test {
                                                                                        public static void main(String[] args) {
                                                                                            //获取针对父类的代理对象
                                                                                            ApplicationContext ioc = new ClassPathXmlApplicationContext("beans06.xml");
                                                                                            Car bean = ioc.getBean(Car.class);
                                                                                            bean.run();
                                                                                        }
                                                                                    }
                                                                                    

                                                                                    5.返回通知获取结果

                                                                                    代码实例
                                                                                    修改Aspect02.java
                                                                                    package com.sxs.spring.aop.joinpoint;
                                                                                    import org.aspectj.lang.JoinPoint;
                                                                                    import org.aspectj.lang.Signature;
                                                                                    import org.aspectj.lang.annotation.AfterReturning;
                                                                                    import org.springframework.stereotype.Component;
                                                                                    /**
                                                                                     * @author 孙显圣
                                                                                     * @version 1.0
                                                                                     */
                                                                                    @Component
                                                                                    @org.aspectj.lang.annotation.Aspect
                                                                                    public class Aspect02 {
                                                                                        /**
                                                                                         * 返回通知获取结果
                                                                                         *
                                                                                         * @param joinPoint
                                                                                         * @param res 参数名必须与returning的一致
                                                                                         */
                                                                                        @AfterReturning(value = "execution(* Car.run())", returning = "res")
                                                                                        public void afterReturning(JoinPoint joinPoint, Object res) {
                                                                                            System.out.println("返回结果为=" + res);
                                                                                        }
                                                                                    }
                                                                                    

                                                                                    image-20240220170459897

                                                                                    6.异常通知获取异常

                                                                                    代码实例
                                                                                    1.修改Car.java

                                                                                    image-20240220172325445

                                                                                    2.修改Aspect02.java
                                                                                        /**
                                                                                         * 异常通知获取异常
                                                                                         *
                                                                                         * @param joinPoint
                                                                                         * @param throwable 参数名必须与throwing一致
                                                                                         */
                                                                                        @AfterThrowing(value = "execution(* Car.run())", throwing = "throwable")
                                                                                        public void afterThrowing(JoinPoint joinPoint, Throwable throwable) {
                                                                                            System.out.println("异常通知获取异常:" + throwable);
                                                                                        }
                                                                                    

                                                                                    image-20240220172407848

                                                                                    7.环绕通知

                                                                                    代码实例
                                                                                    1.Dog.java
                                                                                    package com.sxs.spring.aop.doArround;
                                                                                    import org.springframework.stereotype.Component;
                                                                                    /**
                                                                                     * @author 孙显圣
                                                                                     * @version 1.0
                                                                                     */
                                                                                    @Component
                                                                                    public class Dog {
                                                                                        public String sayHi(String name) {
                                                                                            System.out.println(name + "wang,wang!");
                                                                                            return name + "wang,wang!";
                                                                                        }
                                                                                    }
                                                                                    
                                                                                    2.Aspect03.java
                                                                                    package com.sxs.spring.aop.doArround;
                                                                                    import org.aspectj.lang.ProceedingJoinPoint;
                                                                                    import org.aspectj.lang.annotation.Around;
                                                                                    import org.aspectj.lang.annotation.Aspect;
                                                                                    import org.springframework.stereotype.Component;
                                                                                    import java.util.Arrays;
                                                                                    import java.util.List;
                                                                                    /**
                                                                                     * 环绕通知
                                                                                     *
                                                                                     * @author 孙显圣
                                                                                     * @version 1.0
                                                                                     */
                                                                                    @Component
                                                                                    @Aspect
                                                                                    public class Aspect03 {
                                                                                        /**
                                                                                         * @param joinPoint 连接点对象
                                                                                         * @return 返回结果
                                                                                         */
                                                                                        @Around(value = "execution(public String sayHi(String))")
                                                                                        public Object doArround(ProceedingJoinPoint joinPoint) {
                                                                                            Object result = null;
                                                                                            String methodName = joinPoint.getSignature().getName();
                                                                                            try {
                                                                                                Object[] args = joinPoint.getArgs();
                                                                                                List list = Arrays.asList(args);
                                                                                                //1.前置通知
                                                                                                System.out.println("AOP环绕通知-前置通知-方法名=" + methodName + "-参数-" + list);
                                                                                                //执行方法
                                                                                                result = joinPoint.proceed();
                                                                                                //2.返回通知
                                                                                                System.out.println("AOP环绕通知-返回通知-方法名=" + methodName + "-结果为=" + result);
                                                                                            } catch (Throwable e) {
                                                                                                //3.异常通知
                                                                                                System.out.println("AOP环绕通知-异常通知-方法名=" + methodName + "-异常=" + e);
                                                                                            } finally {
                                                                                                //4.后置通知
                                                                                                System.out.println("AOP环绕通知-后置通知-方法名=" + methodName);
                                                                                            }
                                                                                            return result;
                                                                                        }
                                                                                    }
                                                                                    
                                                                                    3.beans06.xml
                                                                                    
                                                                                    
                                                                                        
                                                                                    
                                                                                        
                                                                                    
                                                                                    
                                                                                    4.Test.java
                                                                                    package com.sxs.spring.aop.doArround;
                                                                                    import org.springframework.context.ApplicationContext;
                                                                                    import org.springframework.context.support.ClassPathXmlApplicationContext;
                                                                                    /**
                                                                                     * @author 孙显圣
                                                                                     * @version 1.0
                                                                                     */
                                                                                    public class Test {
                                                                                        public static void main(String[] args) {
                                                                                            //读取配置文件获取容器
                                                                                            ApplicationContext ioc = new ClassPathXmlApplicationContext("beans06.xml");
                                                                                            //获取针对父类的代理对象
                                                                                            Dog bean = ioc.getBean(Dog.class);
                                                                                            //执行方法
                                                                                            bean.sayHi("小白");
                                                                                        }
                                                                                    }
                                                                                    

                                                                                    image-20240220184215190

                                                                                    8.切入表达式重用

                                                                                    代码实例
                                                                                    1.Car.java
                                                                                    package com.sxs.spring.aop.joinpoint;
                                                                                    import org.springframework.stereotype.Component;
                                                                                    /**
                                                                                     * @author 孙显圣
                                                                                     * @version 1.0
                                                                                     */
                                                                                    @Component
                                                                                    public class Car {
                                                                                        public void run() {
                                                                                            System.out.println("Car在运行!");
                                                                                        }
                                                                                    }
                                                                                    
                                                                                    2.Aspect02.java
                                                                                    package com.sxs.spring.aop.joinpoint;
                                                                                    import org.aspectj.lang.JoinPoint;
                                                                                    import org.aspectj.lang.annotation.*;
                                                                                    import org.springframework.stereotype.Component;
                                                                                    /**
                                                                                     * @author 孙显圣
                                                                                     * @version 1.0
                                                                                     */
                                                                                    @Component
                                                                                    @org.aspectj.lang.annotation.Aspect
                                                                                    public class Aspect02 {
                                                                                        //定义切点函数,实现切入表达式重用
                                                                                        @Pointcut(value = "execution(* Car.run())") //设置切入表达式
                                                                                        public void pointCut() {
                                                                                        }
                                                                                        /**
                                                                                         * 前置通知
                                                                                         *
                                                                                         * @param joinPoint
                                                                                         */
                                                                                        @Before(value = "pointCut()")
                                                                                        public void before(JoinPoint joinPoint) {
                                                                                            System.out.println("前置通知");
                                                                                        }
                                                                                        /**
                                                                                         * 返回通知获取结果
                                                                                         *
                                                                                         * @param joinPoint
                                                                                         * @param res       参数名必须与returning的一致
                                                                                         */
                                                                                        @AfterReturning(value = "pointCut()", returning = "res")
                                                                                        public void afterReturning(JoinPoint joinPoint, Object res) {
                                                                                            System.out.println("返回结果为=" + res);
                                                                                        }
                                                                                        /**
                                                                                         * 异常通知获取异常
                                                                                         *
                                                                                         * @param joinPoint
                                                                                         * @param throwable 参数名必须与throwing一致
                                                                                         */
                                                                                        @AfterThrowing(value = "pointCut()", throwing = "throwable")
                                                                                        public void afterThrowing(JoinPoint joinPoint, Throwable throwable) {
                                                                                            System.out.println("异常通知获取异常:" + throwable);
                                                                                        }
                                                                                        /**
                                                                                         * 后置通知
                                                                                         * @param joinPoint
                                                                                         */
                                                                                        @After(value = "pointCut()")
                                                                                        public void after(JoinPoint joinPoint) {
                                                                                            System.out.println("后置通知");
                                                                                        }
                                                                                    }
                                                                                    
                                                                                    3.beans06.xml
                                                                                    
                                                                                    
                                                                                        
                                                                                    
                                                                                        
                                                                                    
                                                                                    
                                                                                    4.测试
                                                                                    package com.sxs.spring.aop.joinpoint;
                                                                                    import org.springframework.context.ApplicationContext;
                                                                                    import org.springframework.context.support.ClassPathXmlApplicationContext;
                                                                                    /**
                                                                                     * @author 孙显圣
                                                                                     * @version 1.0
                                                                                     */
                                                                                    public class test {
                                                                                        public static void main(String[] args) {
                                                                                            //获取针对父类的代理对象
                                                                                            ApplicationContext ioc = new ClassPathXmlApplicationContext("beans06.xml");
                                                                                            Car bean = ioc.getBean(Car.class);
                                                                                            bean.run();
                                                                                        }
                                                                                    }
                                                                                    

                                                                                    image-20240220185731772

                                                                                    9.AOP多切面优先级问题

                                                                                    image-20240220190818126

                                                                                    解释
                                                                                    1. 多个切面同时切一个方法
                                                                                    2. 可以给切面类配置Order注解,数值越小,前置通知先执行
                                                                                    3. 执行完前置通知之后执行目标方法
                                                                                    4. 然后按照相反的顺序执行多个切面的返回通知、异常通知、最终通知

                                                                                    10.根据xml配置AOP

                                                                                    代码实例
                                                                                    1.UsbInterface.java
                                                                                    package com.sxs.spring.aop.xml;
                                                                                    /**
                                                                                     * @author 孙显圣
                                                                                     * @version 1.0
                                                                                     */
                                                                                    public interface UsbInterface {
                                                                                        public void work();
                                                                                    }
                                                                                    
                                                                                    2.Camera.java
                                                                                    package com.sxs.spring.aop.xml;
                                                                                    /**
                                                                                     * @author 孙显圣
                                                                                     * @version 1.0
                                                                                     */
                                                                                    public class Camera implements UsbInterface {
                                                                                        @Override
                                                                                        public void work() {
                                                                                            System.out.println("相机正在工作。。。。。。");
                                                                                        }
                                                                                    }
                                                                                    
                                                                                    3.Aspect.java
                                                                                    package com.sxs.spring.aop.xml;
                                                                                    import org.aspectj.lang.JoinPoint;
                                                                                    import org.aspectj.lang.Signature;
                                                                                    import org.aspectj.lang.annotation.After;
                                                                                    import org.aspectj.lang.annotation.AfterReturning;
                                                                                    import org.aspectj.lang.annotation.AfterThrowing;
                                                                                    import org.aspectj.lang.annotation.Before;
                                                                                    import org.springframework.stereotype.Component;
                                                                                    import java.util.Arrays;
                                                                                    /**
                                                                                     * @author 孙显圣
                                                                                     * @version 1.0
                                                                                     */
                                                                                    public class Aspect {
                                                                                        /**
                                                                                         * @param joinPoint 保存了要切入的方法的信息
                                                                                         * @Before 前置通知
                                                                                         * execution(。。。) 切入表达式,表明要切入的方法,格式:访问修饰符+返回类型 全类名 方法名(参数类型)
                                                                                         */
                                                                                        public void before(JoinPoint joinPoint) {
                                                                                            //获取方法签名
                                                                                            Signature signature = joinPoint.getSignature();
                                                                                            System.out.println("方法执行开始-日志-方法名-" + signature.getName()
                                                                                                    + "-参数" + Arrays.asList(joinPoint.getArgs()));
                                                                                        }
                                                                                        /**
                                                                                         * @param joinPoint 保存了要切入的方法的信息
                                                                                         * @AfterReturning 返回通知
                                                                                         */
                                                                                        public void afterReturning(JoinPoint joinPoint, Object res) {
                                                                                            Signature signature = joinPoint.getSignature();
                                                                                            System.out.println("方法执行正常结束-日志-方法名-" + signature.getName()
                                                                                            );
                                                                                        }
                                                                                        /**
                                                                                         * @param joinPoint
                                                                                         * @AfterThrowing 异常通知
                                                                                         */
                                                                                        public void throwing(JoinPoint joinPoint, Throwable throwable) {
                                                                                            Signature signature = joinPoint.getSignature();
                                                                                            System.out.println("方法出现异常-日志-方法名-" + signature.getName()
                                                                                            );
                                                                                        }
                                                                                        /**
                                                                                         * @param joinPoint
                                                                                         * @After 后置通知
                                                                                         */
                                                                                        public void after(JoinPoint joinPoint) {
                                                                                            Signature signature = joinPoint.getSignature();
                                                                                            System.out.println("方法最终执行完毕-日志-方法名-" + signature.getName()
                                                                                            );
                                                                                        }}
                                                                                    
                                                                                    4.beans07.xml
                                                                                    
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                            
                                                                                            
                                                                                            
                                                                                            
                                                                                                
                                                                                                
                                                                                                
                                                                                                
                                                                                                
                                                                                                
                                                                                                
                                                                                                
                                                                                            
                                                                                        
                                                                                    
                                                                                    
                                                                                    5.测试
                                                                                    package com.sxs.spring.aop.xml;
                                                                                    import org.springframework.context.ApplicationContext;
                                                                                    import org.springframework.context.support.ClassPathXmlApplicationContext;
                                                                                    /**
                                                                                     * @author 孙显圣
                                                                                     * @version 1.0
                                                                                     */
                                                                                    public class Test {
                                                                                        public static void main(String[] args) {
                                                                                            ApplicationContext ioc = new ClassPathXmlApplicationContext("beans07.xml");
                                                                                            //获得针对接口的代理对象
                                                                                            UsbInterface bean = ioc.getBean(UsbInterface.class);
                                                                                            bean.work();
                                                                                        }
                                                                                    }
                                                                                    

                                                                                    image-20240220195346934

                                                                                    11.课后练习

                                                                                    image-20240220202013336

                                                                                    1.注解实现
                                                                                    1.Cal.java
                                                                                    package com.sxs.spring.aop.homework02;
                                                                                    /**
                                                                                     * @author 孙显圣
                                                                                     * @version 1.0
                                                                                     */
                                                                                    public interface Cal {
                                                                                        public void cal1(int n);
                                                                                        public void cal2(int n);
                                                                                    }
                                                                                    
                                                                                    2.CalImpl.java
                                                                                    package com.sxs.spring.aop.homework02;
                                                                                    import org.springframework.stereotype.Component;
                                                                                    /**
                                                                                     * @author 孙显圣
                                                                                     * @version 1.0
                                                                                     */
                                                                                    @Component
                                                                                    public class CalImpl implements Cal{
                                                                                        /**
                                                                                         * 计算1到n的和
                                                                                         * @param n
                                                                                         */
                                                                                        @Override
                                                                                        public void cal1(int n) {
                                                                                            int sum = 0;
                                                                                            for (int i = 1; i 
                                                                                                sum += i;
                                                                                            }
                                                                                            System.out.println("1到n的和=" + sum);
                                                                                        }
                                                                                        /**
                                                                                         * 计算1乘到n
                                                                                         * @param n
                                                                                         */
                                                                                        @Override
                                                                                        public void cal2(int n) {
                                                                                            int accumulate = 1;
                                                                                            for (int i = 1; i 
                                                                                                accumulate *= i;
                                                                                            }
                                                                                            System.out.println("1到n的积=" + accumulate);
                                                                                        }
                                                                                    }
                                                                                    
                                                                                        //切入表达式重用
                                                                                        @Pointcut(value = "execution(* CalImpl.*(..))")
                                                                                        public void pointCut() {
                                                                                        }
                                                                                        //前置通知
                                                                                        @Before(value = "pointCut()")
                                                                                        public void before(JoinPoint joinPoint) {
                                                                                            //获取目前的毫秒数
                                                                                            long start = System.currentTimeMillis();
                                                                                            //获取函数名
                                                                                            String name = joinPoint.getSignature().getName();
                                                                                            System.out.println(name + "开始时间=" + start);
                                                                                        }
                                                                                        //返回通知
                                                                                        @AfterReturning(value = "pointCut()")
                                                                                        public void afterReturning(JoinPoint joinPoint) {
                                                                                            //获取目前的毫秒数
                                                                                            long end = System.currentTimeMillis();
                                                                                            //获取函数名
                                                                                            String name = joinPoint.getSignature().getName();
                                                                                            System.out.println(name + "结束=" + end);
                                                                                        }
                                                                                    }
                                                                                    
                                                                                        
                                                                                        
                                                                                        public static void main(String[] args) {
                                                                                            ApplicationContext ioc = new ClassPathXmlApplicationContext("beans06.xml");
                                                                                            Cal bean = ioc.getBean(Cal.class);
                                                                                            bean.cal1(5);
                                                                                            System.out.println("===========================");
                                                                                            bean.cal2(5);
                                                                                        }
                                                                                    }
                                                                                    
                                                                                        public void cal1(int n);
                                                                                        public void cal2(int n);
                                                                                    }
                                                                                    
                                                                                        /**
                                                                                         * 计算1到n的和
                                                                                         * @param n
                                                                                         */
                                                                                        @Override
                                                                                        public void cal1(int n) {
                                                                                            int sum = 0;
                                                                                            for (int i = 1; i 
                                                                                                sum += i;
                                                                                            }
                                                                                            System.out.println("1到n的和=" + sum);
                                                                                        }
                                                                                        /**
                                                                                         * 计算1乘到n
                                                                                         * @param n
                                                                                         */
                                                                                        @Override
                                                                                        public void cal2(int n) {
                                                                                            int accumulate = 1;
                                                                                            for (int i = 1; i 
                                                                                                accumulate *= i;
                                                                                            }
                                                                                            System.out.println("1到n的积=" + accumulate);
                                                                                        }
                                                                                    }
                                                                                    
                                                                                        //前置通知
                                                                                        public void before(JoinPoint joinPoint) {
                                                                                            //获取目前的毫秒数
                                                                                            long start = System.currentTimeMillis();
                                                                                            //获取函数名
                                                                                            String name = joinPoint.getSignature().getName();
                                                                                            System.out.println(name + "开始时间=" + start);
                                                                                        }
                                                                                        //返回通知
                                                                                        public void afterReturning(JoinPoint joinPoint) {
                                                                                            //获取目前的毫秒数
                                                                                            long end = System.currentTimeMillis();
                                                                                            //获取函数名
                                                                                            String name = joinPoint.getSignature().getName();
                                                                                            System.out.println(name + "结束=" + end);
                                                                                        }
                                                                                    }
                                                                                    
                                                                                        
                                                                                        
                                                                                        
                                                                                            
                                                                                            
                                                                                        public static void main(String[] args) {
                                                                                            ApplicationContext ioc = new ClassPathXmlApplicationContext("beans08.xml");
                                                                                            //获取针对接口的代理对象
                                                                                            Cal proxy = ioc.getBean("calImpl", Cal.class);
                                                                                            proxy.cal1(100);
                                                                                            System.out.println("=========================");
                                                                                            proxy.cal2(5);
                                                                                        }
                                                                                    }
                                                                                    
微信扫一扫加客服

微信扫一扫加客服

点击启动AI问答
Draggable Icon