Spring 之使用AspectJ实现动态代理

  1. 原理,导入AspectJ的jar包,并且在spring的配置文件中做以下声明,这一句是告诉Spring如果创建对象的时候符合切面类的筛选条件(其实就是切入点表达式)时候,Spring不会创建原生的对象,而是会创建出一个代理对象。
    <aop:aspectj-autoproxy/>

     

  2. jar包链接:https://pan.baidu.com/s/1mgiprsaUUQz3kBcDgBF60g      提取码:38is 

  3. 程序结构                                                                                                                     

  4. 程序

    <?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:context="http://www.springframework.org/schema/context"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
    
        <!--组件扫描-->
        <context:component-scan base-package="com.aspectj.annotation"/>
    
        <!--生成代理-->
        <aop:aspectj-autoproxy/>
    
    
    </beans>
    package com.aspectj.annotation.calculator;
    
    public interface Calculator1 {
        int add(int a, int b);
        int sub(int a, int b);
        int div(int a, int b);
    }
    
    package com.aspectj.annotation.calculator;
    
    import org.springframework.stereotype.Component;
    
    @Component
    public class CalculatorIImpl implements Calculator1 {
        @Override
        public int add(int a, int b) {
            return a+b;
        }
    
        @Override
        public int sub(int a, int b) {
            return a-b;
        }
    
        @Override
        public int div(int a, int b) {
            return a / b;
        }
    }
    
    package com.aspectj.annotation;
    
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.*;
    import org.springframework.stereotype.Component;
    
    import java.util.Arrays;
    
    /**
     * 日志切面
     */
    @Component  //标志为一个组件
    @Aspect  //标识为一个切面
    public class LoggingAspect {
        /**
         * 前置通知:  在目标方法(连接点)执行之前执行的方法
         */
        @Before("execution(public int com.aspectj.annotation.calculator.CalculatorIImpl.add(int, int))")
        public void beforeMethod(JoinPoint joinPoint){
            Object [] methodArgs = joinPoint.getArgs();
            System.out.println("前置方法 LogginAspect==> the method start args:  " + Arrays.asList(methodArgs) );
            String methodName =  joinPoint.getSignature().getName();
            System.out.println("前置方法 LoginAspect ==> the method  : "+ methodName + "is start.") ;
        }
    
        /**
         * 后置通知:   在目标方法执行之后执行,特点: 不管目标方法是否抛出异常都会执行
         * 不能获得方法的结果的!!!!!!!!!!!!
         *   1、* com.as                这个星号代表任意修饰符任意返回值
         *   2、CalculatorIImpl.*  这个星号代表任意方法名
         *   3、calculator.*           这个包下任何类
         *   4、 (..)                          代表任意参数列表
         *
         *
         *   连接点对象
         */
        @After("execution(* com.aspectj.annotation.calculator.*.*(..))")
        public void afterMethod(JoinPoint joinPoint){
            String methodName =  joinPoint.getSignature().getName();
            System.out.println("后置方法  LoginAspect ==> the method: "+ methodName + "is end");
        }
        /**
         * 返回方法,在目标方法正常执行后,可以获取到该方法的返回值
         * 通过returning指定一个名字,这个名字必须和方法的一个参数名字一样
         */
        @AfterReturning(value = "execution(* com.aspectj.annotation.calculator.*.*(..))", returning = "result")
        public  void afterReturning(JoinPoint joinPoint, Object result){
            String methodName = joinPoint.getSignature().getName();
            System.out.println("返回值方法  Loggin the method" + methodName + "end, it’s result is " + result);
        }
        /**
         * 异常方法,在方法抛出异常的时候执行
         * 和返回值处理方法相似,要在注解中加入一个和入参名字相同的设置
         * 可以通过入参中指定异常的类型来指定抛出指定异常的时候才执行
         */
        @AfterThrowing(value = "execution(* com.aspectj.annotation.calculator.*.*(..))", throwing = "ex")
        public void afterThrowing(JoinPoint joinPoint, ArithmeticException ex){
            System.out.println("异常处理方法 " + joinPoint.getSignature().getName() +
                                   "该异常是 :" +  ex ) ;
        }
    
        /**
         * 环绕通知: 环绕着目标方法执行,可以理解为上边四种方法的结合体,
         *                  更像是动态代理的整个过程
         */
        @Around(value = "execution(* com.aspectj.annotation.calculator.*.*(..))")
        public Object aroundMethod (ProceedingJoinPoint pjp){
    //        执行动态方法
            try{
    //            前置通知
                System.out.println("前置, 方法名为" + pjp.getSignature().getName()
                         + "参数列表为" + Arrays.asList(pjp.getArgs()) );
                Object result  = pjp.proceed();
                System.out.println();
                return result;
            }catch (Throwable e){
    //             异常通知
                System.out.println("环绕通知异常" + e);
            }finally {
    //            后置通知
                System.out.println("环绕通知后置");
            }
                return  null;
        }
    }
    
    package com.aspectj.annotation.calculator;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class Main {
        public static void main(String []args){
            ApplicationContext  applicationContext
                     = new ClassPathXmlApplicationContext("spring.xml");
    //        获取
            Calculator1 calculator1 = applicationContext.getBean("calculatorIImpl", Calculator1.class);
            System.out.println(calculator1.getClass().getName());
    //        int   result  = calculator1.add(1,1);
            int   result1 = calculator1.div(1, 0);
    //        System.out.println(result);
        }
    }
    

     

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值