• Spring --- AOP 操作 - AspectJ注解


        AOP(Aspect Oriented Programming)字面翻译为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。
        这样的翻译,如果大家不了解这项技术的话,肯定会发懵。其实,面向切面编程,简单地理解就是为了降低代码耦合度,减少重复代码量,增加系统灵活性而采用的一种编程规范。主要用到的技术就是动态代理,分为JDK动态代理,和CGLIB动态代理。关于JDK动态代理,小编在前面的文章:Java — 动态代理 完整步骤 有介绍到,有兴趣的小伙伴可以去翻看一下。这篇文章咱们先把AOP动态代理放一下,小编先演示一下如何通过AspectJ 注解方式来实现AOP操作,其他内容在后续的文章中会一一展示。好了,话不多说,Let go!

    1,编写 连接点(aop术语),即切入的某个方法所在的实体类

    @Component //需要加@Component注解,这样会被IOC容器管理
    public class Skill {
    //    自定义方法
        public void eat(){
            System.out.println("eat rice");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    2,编写 增强类(aop术语),即aop代码所在的类

    @Component //需要加@Component注解,这样会被IOC容器管理
    @Aspect //加@Aspect注解,被ioc识别为增强类
    public class AopClass {
    
    	/**
         * 切入点表达式:
         * execution([权限修饰符][返回类型][类全路径][方法名称]([参数列表]))
         * eat(..) 表示 eat方法及参数列表
         */
         
        /**
         * 前置增强,即在调用被切入方法 Skill.eat() 之前调用的方法
         */
        @Before(value = "execution(* com.chaoge.nacos.demo.test.spring.entity.Skill.eat(..))")
        public void before(){
            System.out.println("Aop:前置");
        }
    
        /**
         * 后置增强,即在调用被切入方法 Skill.eat() 之后调用的方法
         */
        @After(value = "execution(* com.chaoge.nacos.demo.test.spring.entity.Skill.eat(..))")
        public void after(){
            System.out.println("Aop:后置");
        }
    
        /**
         * 后置返回增强,即在调用被切入方法 Skill.eat() 返回结果之后调用的方法
         */
        @AfterReturning(value = "execution(* com.chaoge.nacos.demo.test.spring.entity.Skill.eat(..))")
        public void afterReturning(){
            System.out.println("Aop:后置返回");
        }
    
        /**
         * 环绕增强,即在调用被切入方法 Skill.eat() 前后都会调用的方法
         * @param joinPoint
         * @throws Throwable
         */
        @Around(value = "execution(* com.chaoge.nacos.demo.test.spring.entity.Skill.eat(..))")
        public void round(ProceedingJoinPoint joinPoint) throws Throwable {
            System.out.println("Aop:环绕前");
            joinPoint.proceed();
            System.out.println("Aop:环绕后");
        }
    
        /**
         * 异常增强,即在调用被切入方法 Skill.eat() 出现异常时候调用的方法
         */
        @AfterThrowing(value = "execution(* com.chaoge.nacos.demo.test.spring.entity.Skill.eat(..))")
        public void excetion(){
            System.out.println("Aop:异常");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54

    3,编写Spring 配置文件:AopConfig.xml。文件头部包括 自定义 xmlns:context,xmlns:aop 的编写,如果有疑惑的小伙伴,可以翻看小编之前的文章:Spring — IOC 容器 之 Bean管理XML方式(外部属性文件)
    进行对比观察,即可理解。

    
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           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.chaoge.nacos.demo.test.spring.entity"/>
    
        <aop:aspectj-autoproxy/>
    beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    4,使用

    public class BeanTest {
    	@Test
        public void test8(){
            ApplicationContext context = new  ClassPathXmlApplicationContext("com/chaoge/nacos/demo/test/spring/beanConfig/AopConfig.xml");
            Skill skill = context.getBean("skill", Skill.class);
            skill.eat();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    5,输出

    D:\jdk\jdk1.8.0_171\bin\java.exe
    Aop:环绕前
    Aop:前置
    eat rice
    Aop:后置返回
    Aop:后置
    Aop:环绕后
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    6,改进
    在上面2步骤中,增强类中每一个增强方法都配置了切入点表达式,这样就显得冗余,为了简化代码,可以使用@Pointcut注解对切入点进行统一管理

    @Component
    @Aspect
    public class AopClass {
    
        @Pointcut(value = "execution(* com.chaoge.nacos.demo.test.spring.entity.Skill.eat(..))")
        public void point(){
    
        }
    
        /**
         * 切入点表达式:
         * execution([权限修饰符][返回类型][类全路径][方法名称]([参数列表]))
         * eat(..) 表示 eat方法及参数列表
         */
    
        /**
         * 前置增强,即在调用被切入方法 Skill.eat() 之前调用的方法
         */
        @Before(value = "point()")
        public void before(){
            System.out.println("Aop:前置");
        }
    
        /**
         * 后置增强,即在调用被切入方法 Skill.eat() 之后调用的方法
         */
        @After(value = "point()")
        public void after(){
            System.out.println("Aop:后置");
        }
    
        /**
         * 后置返回增强,即在调用被切入方法 Skill.eat() 返回结果之后调用的方法
         */
        @AfterReturning(value = "point()")
        public void afterReturning(){
            System.out.println("Aop:后置返回");
        }
    
        /**
         * 环绕增强,即在调用被切入方法 Skill.eat() 前后都会调用的方法
         * @param joinPoint
         * @throws Throwable
         */
        @Around(value = "point()")
        public void round(ProceedingJoinPoint joinPoint) throws Throwable {
            System.out.println("Aop:环绕前");
            joinPoint.proceed();
            System.out.println("Aop:环绕后");
        }
    
        /**
         * 异常增强,即在调用被切入方法 Skill.eat() 出现异常时候调用的方法
         */
        @AfterThrowing(value = "point()")
        public void excetion(){
            System.out.println("Aop:异常");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59

    7,如果这篇文章有帮助到你,麻烦再动动你的小手,给小编点个赞和关注吧!谢谢!

  • 相关阅读:
    函数的基本概念
    linux网络编程epoll内核实现代码分析
    logback(二)springboot配置日志文件格式、logback-spring配置文件详解
    python 多线程
    JavaWeb:Maven常识性总结
    【51单片机】智能百叶窗项目
    2.1 设置大小
    【数据库原理与应用(第3版)】第一章:数据库系统概论(选择与填空)
    [网站部署03]宝塔+worldPress部署Ripro主题网站
    31.10.2 配置半同步复制
  • 原文地址:https://blog.csdn.net/yuanchenglong/article/details/126087292