文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

一文吃透 Spring 中的 AOP 编程

2023-09-14 09:28

关注

在这里插入图片描述

✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。
🍎个人主页:Java Fans的博客
🍊个人信条:不迁怒,不贰过。小知识,大智慧。
💞当前专栏:SSM 框架从入门到精通
✨特色专栏:国学周更-心性养成之路
🥭本文内容:一文吃透 Spring 中的 AOP 编程

文章目录


在这里插入图片描述

AOP 概述

AOPAspect Oriented Programming 的缩写,是面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOPOOP 的延续,是软件开发中的一个热点,也是 Spring 框架中的一个重要内容,是函数式编程的一种衍生范型

AOP 可以分离业务代码和关注点代码(重复代码),在执行业务代码时,动态的注入关注点代码。切面就是关注点代码形成的类。Spring AOP 中的动态代理主要有两种方式,JDK 动态代理和 CGLIB 动态代理。JDK 动态代理通过反射来接收被代理的类,并且要求被代理的类必须实现一个接口

在这里插入图片描述

AOP 实现分类

AOP 要达到的效果是,保证开发者不修改源代码的前提下,去为系统中的业务组件添加某种通用功能,按照 AOP 框架修改源代码的时机,可以将其分为两类:

AOP 术语

通知的类型

Spring 方面可以使用下面提到的五种通知工作:

通知描述
前置通知在一个方法执行之前,执行通知。
最终通知在一个方法执行之后,不考虑其结果,执行通知。
后置通知在一个方法执行之后,只有在方法成功完成时,才能执行通知。
异常通知在一个方法执行之后,只有在方法退出抛出异常时,才能执行通知。
环绕通知在一个方法调用之前和之后,执行通知。

基于 Aspectj 实现 AOP 操作

基于 Aspectj 实现 AOP 操作,经历了下面三个版本的变化,注解版是我们最常用的。

切入点表达式

作用:声明对哪个类中的哪个方法进行增强

语法:

execution([访问权限修饰符] 返回值 [ 类的全路径名 ] 方法名 (参数列表)[异常])

在这里插入图片描述

第一版:基于xml(aop:config)配置文件

使用 Spring AOP 接口方式实现 AOP, 可以通过自定义通知来供 Spring AOP 识别对应实现的接口是:

  1. 前置通知:MethodBeforeAdvice
  2. 返回通知:AfterReturningAdvice
  3. 异常通知:ThrowsAdvice
  4. 环绕通知:MethodInterceptor

实现步骤:

1、定义业务接口

package cn.kgc.spring05.entity;public interface Teacher {    String teachOnLine(String course);    String teachOffLine(Integer course);}

2、定义实现类

package cn.kgc.spring05.entity;public class TeacherA implements Teacher{    @Override    public String teachOnLine(String course) {        System.out.println("TeacherA开始"+course+"课程线上教学");        if(course.equals("java")){            throw new RuntimeException("入门到放弃!");        }        return course+"课程线上教学";    }    @Override    public String teachOffLine(Integer course) {        System.out.println("TeacherA开始"+course+"课程线下教学");        return course+"课程线下教学";    }}

3、实现接口定义通知类

前置通知类

package cn.kgc.spring05.advice;import org.springframework.aop.MethodBeforeAdvice;import java.lang.reflect.Method;//前置通知public class MyMethodBeforeAdvice implements MethodBeforeAdvice {    @Override    public void before(Method method, Object[] objects, Object o) throws Throwable {        System.out.println("------------spring aop 前置通知------------");    }}

后置通知类

package cn.kgc.spring05.advice;import org.springframework.aop.AfterReturningAdvice;import java.lang.reflect.Method;public class MyAfterReturnAdvice implements AfterReturningAdvice {    @Override    public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {        System.out.println("------------spring aop 后置通知------------");    }}

4、XML 配置方式

<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"       xsi:schemaLocation="http://www.springframework.org/schema/beans       http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">        <bean id="after" class="cn.kgc.spring05.advice.MyAfterReturnAdvice">bean>    <bean id="before" class="cn.kgc.spring05.advice.MyMethodBeforeAdvice">bean>    <bean id="teacherA" class="cn.kgc.spring05.entity.TeacherA">bean>        <aop:config>                <aop:pointcut id="pt" expression="execution(* *(..))"/>        <aop:advisor advice-ref="before" pointcut-ref="pt">aop:advisor>        <aop:advisor advice-ref="after" pointcut-ref="pt">aop:advisor>    aop:config>beans>

5、测试

package cn.kgc.spring05;import cn.kgc.spring05.entity.Teacher;import junit.framework.TestCase;import junit.framework.TestSuite;import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.test.context.ContextConfiguration;import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration("classpath:spring-config.xml")public class AppTest{    @Autowired    Teacher teacher;    @Test    public void teachOnLine() {        System.out.println(teacher.getClass());        String s = teacher.teachOnLine("java");        System.out.println("s = " + s);    }}

6、运行结果

在这里插入图片描述

第二版:基于xml(aop:aspect)配置文件

基于 xml(aop:config) 配置文件的方式,增加几个通知,就会创建几个通知类,那我们能否将这些通知类写在一个类中呢?下面就让我来带你们找到解决之法!

配置 AspectJ 标签解读表

在这里插入图片描述

实现步骤:

1、定义业务接口

package cn.kgc.spring05.entity;public interface Teacher {    String teachOnLine(String course);    String teachOffLine(Integer course);}

2、定义实现类

package cn.kgc.spring05.entity;public class TeacherA implements Teacher{    @Override    public String teachOnLine(String course) {        System.out.println("TeacherA开始"+course+"课程线上教学");        if(course.equals("java")){            throw new RuntimeException("入门到放弃!");        }        return course+"课程线上教学";    }    @Override    public String teachOffLine(Integer course) {        System.out.println("TeacherA开始"+course+"课程线下教学");        return course+"课程线下教学";    }}

3、实现接口定义通知类

package cn.kgc.spring05.advice;public class AllAdvice {    public void before(){System.out.println("------------前置通知--------------");}    public void afterReturning(){System.out.println("------------后置通知--------------");}    public void afterThrowing(){System.out.println("------------异常通知--------------");}    public void after(){System.out.println("------------最终通知--------------");}    public void around(){System.out.println("------------环绕通知--------------");}}

4、XML 配置方式

<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"       xsi:schemaLocation="http://www.springframework.org/schema/beans       http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">        <bean id="all" class="cn.kgc.spring05.advice.AllAdvice">bean>    <bean id="teacherA" class="cn.kgc.spring05.entity.TeacherA">bean>        <aop:config>                <aop:pointcut id="pt" expression="execution(* *(String))"/>        <aop:aspect ref="all">            <aop:before method="before" pointcut-ref="pt">aop:before>            <aop:after-returning method="afterReturning" pointcut-ref="pt">aop:after-returning>            <aop:after-throwing method="afterThrowing" pointcut-ref="pt">aop:after-throwing>            <aop:after method="after" pointcut-ref="pt">aop:after>        aop:aspect>    aop:config>beans>

5、测试

package cn.kgc.spring05.advice;import cn.kgc.spring05.entity.Teacher;import junit.framework.TestCase;import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.test.context.ContextConfiguration;import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration("classpath:spring-config2.xml")public class AllAdviceTest{    @Autowired    Teacher teacher;    @Test    public void test01() {        System.out.println(teacher.getClass());        String s = teacher.teachOnLine("java");        System.out.println("s = " + s);    }}

6、运行结果

在这里插入图片描述

第三版:基于注解实现通知

实现步骤:

1、定义业务接口

package cn.kgc.spring05.entity;public interface Teacher {    String teachOnLine(String course);    String teachOffLine(Integer course);}

2、定义注解

package cn.kgc.spring05.advice;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface AnnoAdvice {}

3、定义实现类

package cn.kgc.spring05.entity;import cn.kgc.spring05.advice.AnnoAdvice;import org.springframework.stereotype.Component;@Componentpublic class TeacherA implements Teacher{    @Override    @AnnoAdvice    public String teachOnLine(String course) {        System.out.println("TeacherA开始"+course+"课程线上教学");        if(course.equals("java")){            throw new RuntimeException("入门到放弃!");        }        return course+"课程线上教学";    }    @Override    @AnnoAdvice    public String teachOffLine(Integer course) {        System.out.println("TeacherA开始"+course+"课程线下教学");        return course+"课程线下教学";    }}

4、实现接口定义切面类

首先在类上面添加 @Aspect 注解,将该类转化为切面类,再在类中的各个方法上面使用各自的 “通知” 注解即可实现。

package cn.kgc.spring05.advice;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.*;import org.springframework.stereotype.Component;@Component@Aspectpublic class AllAdvice {    @Pointcut("@annotation(AnnoAdvice)")    public void point(){}    @Before("point()")    public void before(){System.out.println("------------前置通知--------------");}    @AfterReturning("point()")    public void afterReturning(){System.out.println("------------后置通知--------------");}    @AfterThrowing("point()")    public void afterThrowing(){System.out.println("------------异常通知--------------");}    @After("point()")    public void after(){System.out.println("------------最终通知--------------");}    @Around("point()")    public Object aroundAdvice(ProceedingJoinPoint joinPoint){        Object proceed = null;        try {            System.out.println("----------spring aop 环绕 前通知-----------");            proceed = joinPoint.proceed();            System.out.println("----------spring aop 环绕 后通知-----------");        } catch (Throwable throwable) {            throwable.printStackTrace();            System.out.println("----------spring aop 环绕 异常通知-----------");        }finally {            System.out.println("----------spring aop 环绕 最终通知-----------");        }        return proceed;    }}

5、XML 配置方式

开启包扫描和aspectj自动代理

<?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/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">    <!--开启包扫描-->    <context:component-scan base-package="cn.kgc.spring05"></context:component-scan>    <!--开启aspectj自动代理-->    <aop:aspectj-autoproxy></aop:aspectj-autoproxy></beans>

6、测试

package cn.kgc.spring05.advice;import cn.kgc.spring05.entity.Teacher;import junit.framework.TestCase;import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.test.context.ContextConfiguration;import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration("classpath:spring-config3.xml")public class AllAdviceTest{    @Autowired    Teacher teacher;    @Test    public void test01() {        System.out.println(teacher.getClass());        String s = teacher.teachOnLine("html");        System.out.println("s = " + s);    }}

7、运行效果

在这里插入图片描述


  码文不易,本篇文章就介绍到这里,如果想要学习更多Java系列知识点击关注博主,博主带你零基础学习Java知识。与此同时,对于日常生活有困扰的朋友,欢迎阅读我的第四栏目《国学周更—心性养成之路》,学习技术的同时,我们也注重了心性的养成。

在这里插入图片描述

来源地址:https://blog.csdn.net/hh867308122/article/details/129147900

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯