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");
    }
}

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:异常");
    }
}

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

<?xml version="1.0" encoding="UTF-8"?>
<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">

<!--    xmlns:context="http://www.springframework.org/schema/context"-->
<!--    xmlns:aop="http://www.springframework.org/schema/aop"-->
<!--    为自定义配置上下文管理-->

<!--    开启注解扫描,扫描有 @Controller @Service @Component @Repository 等注解的类,识别其为bean-->
<!--    base-package标签指明需要扫描有注解的类所在包路径-->
    <context:component-scan base-package="com.chaoge.nacos.demo.test.spring.entity"/>
<!--    开启aspectJ扫描 扫描有@Aspect注解的类,识别其为增强类-->
    <aop:aspectj-autoproxy/>
</beans>

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();
    }
}

5,输出

D:\jdk\jdk1.8.0_171\bin\java.exe
Aop:环绕前
Aop:前置
eat rice
Aop:后置返回
Aop:后置
Aop:环绕后

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:异常");
    }
}

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

皮皮克克

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值