• Spring-AOP


    一.动态代理

    1.创建一个接口

    ArithmeticCalculator 
    package com.atguigu.spring.aop.helloworld;
    
    public interface ArithmeticCalculator {
    
        int add(int i ,int j);
        int sub(int i ,int j);
        int mul(int i ,int j);
        int div(int i ,int j);
    
    }

    2.创建接口的实现类

    package com.atguigu.spring.aop.helloworld;
    
    public class ArithmeticCalculatorImpl implements ArithmeticCalculator {
    
        @Override
        public int add(int i, int j) {
            int result = i +j;
            return result;
        }
    
        @Override
        public int sub(int i, int j) {
            int result = i - j;
            return result;
        }
    
        @Override
        public int mul(int i, int j) {
            int result = i * j;
            return result;
        }
    
        @Override
        public int div(int i, int j) {
            int result = i / j;
            return result;
        }
    
    }

    3.创建代理类

    package com.atguigu.spring.aop.helloworld;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    import java.util.Arrays;
    
    public class ArithmeticCalculatorLoggingProxy {
        //要代理的对象
        private ArithmeticCalculator target;
        
        
        public ArithmeticCalculatorLoggingProxy(ArithmeticCalculator target) {
            this.target = target;
        }
    
    
        public ArithmeticCalculator getLoggingProxy(){
            ArithmeticCalculator proxy = null;
            //代理对象由哪一个类加载器负责加载
            ClassLoader loader = target.getClass().getClassLoader();
            //代理对象的类型,即其中有哪些方法
            Class[] interfaces = new Class[]{ArithmeticCalculator.class}; 
            
            //当调用代理对象其中的方法时,该执行的代码
            InvocationHandler h = new InvocationHandler() {
                /**
                 * proxy:正在返回的那个代理对象,一般情况下,在invoke方法中都不使用该对象
                 * method:正在被调用的方法
                 * args:调用方法时,传入的参数
                 */
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    String methodName = method.getName();
                    //日志
                    System.out.println("【before】The method" + method + "begins with "+Arrays.asList(args));
                    //执行方法
                    Object result = null;
                    try {
                        //前置通知
                        result = method.invoke(target, args);
                        //返回通知
                    } catch (Exception e) {
                        e.printStackTrace();    
                        //异常通知,可以访问到方法出现的异常
                    }
                        
                    //后置通知  因为方法可能会抛异常,所以访问不到方法的返回值
                    //日志
                    System.out.println("【ends】The method" + method + "ends with "+ result);
                    return result;
                }
            };
            proxy = (ArithmeticCalculator)Proxy.newProxyInstance(loader, interfaces, h);
            return proxy;
        }
        
        
    }

    4.测试类

    package com.atguigu.spring.aop.helloworld;
    
    public class Main {
    
        public static void main(String[] args) {
            ArithmeticCalculator target = new ArithmeticCalculatorImpl();
            ArithmeticCalculator proxy = new ArithmeticCalculatorLoggingProxy(target).getLoggingProxy();
            int result = proxy.add(2, 3);
            //System.out.println("-->"+result);
        }
    }

    5.配置文件

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:aop="http://www.springframework.org/schema/aop"
        xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
    
        <!-- 自动扫描的包 -->
        <context:component-scan base-package="com.atguigu.spring.aop"></context:component-scan>
    
        <!-- 使 AspectJ 的注解起作用 ,自动为匹配的类生成代理对象-->
        <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    
    </beans>

    二,Spring  AOP

    1.定义接口

    package com.atguigu.spring.aop.impl;
    
    public interface ArithmeticCalculator {
    
        int add(int i ,int j);
        int sub(int i ,int j);
        int mul(int i ,int j);
        int div(int i ,int j);
    
    }

    2.创建接口的实现类

    package com.atguigu.spring.aop.impl;
    
    import org.springframework.stereotype.Component;
    
    @Component
    public class ArithmeticCalculatorImpl implements ArithmeticCalculator {
    
        @Override
        public int add(int i, int j) {
            int result = i +j;
            return result;
        }
    
        @Override
        public int sub(int i, int j) {
            int result = i - j;
            return result;
        }
    
        @Override
        public int mul(int i, int j) {
            int result = i * j;
            return result;
        }
    
        @Override
        public int div(int i, int j) {
            int result = i / j;
            return result;
        }
    
    }

    3.创建切面

    package com.atguigu.spring.aop.impl;
    
    import java.util.Arrays;
    import java.util.List;
    
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.After;
    import org.aspectj.lang.annotation.AfterReturning;
    import org.aspectj.lang.annotation.AfterThrowing;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.springframework.stereotype.Component;
    
    //把这个类生命为一个切面:需要先把该类放到IOC容器中,在声明为一个切面
    @Component
    @Aspect
    public class LoggingAspect {
    
        //声明该方法是一个前置通知:在目标方法开始之前执行
        @Before(value = "execution(public int com.atguigu.spring.aop.impl.ArithmeticCalculator.*(int,int))")
        public void beforeMethod(JoinPoint joinPoint){
            String methodName = joinPoint.getSignature().getName();
            List<Object> args = Arrays.asList(joinPoint.getArgs());
            System.out.println("The method"+methodName+" begins. with.."+args);
        }
        
        
        
        //后置通知:在目标方法执行后(无论是否发生异常),执行的通知
        //在后置通知中还不能访问目标方法执行的结果
        @After(value = "execution(* com.atguigu.spring.aop.impl.*.*(int,int))")
        public void afterMethod(JoinPoint joinPoint){
            String methodName = joinPoint.getSignature().getName();
            System.out.println("后置通知---The method  "+methodName+"  ends ");
    
        }
        
        /**
         * 在方法正常结束之后执行的代码
         * 返回通知 是可以返回目标方法执行的结果
         * @param joinPoint
         */
        @AfterReturning(value = "execution(* com.atguigu.spring.aop.impl.*.*(int,int))",returning = "result")
        public void afterReturning(JoinPoint joinPoint,Object result){
            String methodName = joinPoint.getSignature().getName();
            System.out.println("返回通知---The method   " + methodName + "  ends with  " + result);
        }
        
        /**
         * 在目标方法出现异常时会执行的代码  
         * 可以访问到异常对象,且可以指定在出现特定异常时在执行的代码
         * 例如:测试的时候使用100/0   会报java.lang.ArithmeticException: / by zero  异常,
         * 但在接受的时候使用的是NullPointerException,(afterThrowing(JoinPoint joinPoint,NullPointerException ex))
         * 那么将不会执行方法
         * @param joinPoint
         * @param ex
         */
        @AfterThrowing(value = "execution(* com.atguigu.spring.aop.impl.*.*(int,int))",
                throwing = "ex")
        public void afterThrowing(JoinPoint joinPoint,Exception ex){ 
            String methodName = joinPoint.getSignature().getName();
            System.out.println("异常通知---The method   " + methodName + " occurs exception  with  " + ex);
        }
        
        /**
         * 环绕通知需要携带ProceedingJoinPoint类型的参数
         * 环绕通知类似于动态代理的全过程:ProceedingJoinPoint类型的参数可以决定是否执行目标方法
         * 且环绕通知必须有返回值,返回值即为目标方法的返回值。
         * @param pjd
         */
        @Around("execution(* com.atguigu.spring.aop.impl.*.*(int,int))")
        public Object aroundMethod(ProceedingJoinPoint pjd){
            Object result = null;
            String methodName = pjd.getSignature().getName();
            //执行目标方法
            try {
                //前置通知
                System.out.println("The method " + methodName + "begins with" + Arrays.asList(pjd.getArgs()));
                //执行目标方法
                result = pjd.proceed();
                //返回通知
                System.out.println("The method " + methodName + "ends with" +result);
            } catch (Throwable e) {
                //异常通知
                System.out.println("异常通知---The method   " + methodName + " occurs exception  with  " + e);
                e.printStackTrace();
            }
            //后置通知
            System.out.println("The method " + methodName + "ends");
            return result;
        }
        
        
    }

    4.测试类

    package com.atguigu.spring.aop.impl;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class Main {
    
        public static void main(String[] args) {
            
            //1.创建Spring的IOC容器
            ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
            //2.从IOC容器中获取Bean的实例
            ArithmeticCalculator arith = app.getBean(ArithmeticCalculator.class);
            //3.使用Bean
            int result = arith.add(3, 6);
            System.out.println("result:" + result);
            result = arith.div(100, 0);
            System.out.println("result:" + result);
    
        }
    }

    5.配置文件

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:aop="http://www.springframework.org/schema/aop"
        xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
    
        <!-- 自动扫描的包 -->
        <context:component-scan base-package="com.atguigu.spring.aop"></context:component-scan>
    
        <!-- 使 AspectJ 的注解起作用 ,自动为匹配的类生成代理对象-->
        <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    
    </beans>

    6.使用的jar文件:

  • 相关阅读:
    洛谷P1508 Likecloud-吃、吃、吃 [2017年4月计划 动态规划10]
    洛谷P1855 榨取kkksc03 [2017年4月计划 动态规划 09]
    洛谷P1164 小A点菜 [2017年4月计划 动态规划08]
    洛谷P1244 [NOI2000] 青蛙过河 [2017年4月计划 动态规划07]
    洛谷P1757 通天之分组背包 [2017年4月计划 动态规划06]
    洛谷P1877 [HAOI2012]音量调节 [2017年4月计划 动态规划05]
    洛谷P1474 [USACO 2.3]货币系统 Money Systems [2017年4月计划 动态规划04]
    洛谷P1832 A+B Problem(再升级) [2017年4月计划 动态规划03]
    洛谷P1968 美元汇率[2017年4月计划 动态规划02]
    洛谷P2347 砝码称重 [2017年4月计划 动态规划01]
  • 原文地址:https://www.cnblogs.com/zqLoveSym/p/10902225.html
Copyright © 2020-2023  润新知