Java AOP

news2024/11/27 5:25:18

1 概述

1.1 定义

  • AOP(Aspect Oriented Programming),即面向切面编程 。在不修改原有代码的基础上,对代码进行增强。

1.2 术语

1.3 底层原理

入门案例

  • 项目名:day049_spring_aop

  • 坐标:web、test、aop


    <!--确定spring boot版本-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.5.RELEASE</version>
        <relativePath/>
    </parent>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>


    <dependencies>
        <!--web开发启动器-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--test 启动器-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>

        <!--aop 启动器-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>


    </dependencies>

基本代码 

  • 配置文件:application.yml (可选)

  • 启动类:AopApplication

package com.czxy;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * @author 桐叔
 * @email liangtong@itcast.cn
 * @description
 */
@SpringBootApplication
public class AopApplication {
    public static void main(String[] args) {
        SpringApplication.run(AopApplication.class, args);
    }
}

目标类:UserService、UserServiceImpl

UserService接口

package com.czxy.service;

/**
 * @author 桐叔
 * @email liangtong@itcast.cn
 * @description
 */
public interface UserService {
    public Integer insert();

    public Integer update(String text);
}

 UserServiceImpl实现类

package com.czxy.service.impl;

import com.czxy.service.UserService;
import org.springframework.stereotype.Service;

/**
 * @author 桐叔
 * @email liangtong@itcast.cn
 * @description
 */
@Service
public class UserServiceImpl implements UserService {
    @Override
    public Integer insert() {
        System.out.println("user service impl insert");
        return 1;
    }

    @Override
    public Integer update(String text) {
        System.out.println("user service impl update: " + text);
        return 100;
    }
}

测试类:TestUserService

package com.czxy;

import com.czxy.service.UserService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import javax.annotation.Resource;

/**
 * @author 桐叔
 * @email liangtong@itcast.cn
 * @description
 */
@RunWith(SpringRunner.class)
@SpringBootTest(classes = AopApplication.class)
public class TestUserService {

    @Resource
    private UserService userService;

    @Test
    public void testInsert() {
        Integer result = userService.insert();
        System.out.println(result);
    }

    @Test
    public void testUpdate() {
        Integer result = userService.update("溜溜溜");
        System.out.println(result);
    }


}

AOP代码

ackage com.czxy.aspect;

import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

/**
 * @author 桐叔
 * @email liangtong@itcast.cn
 * @description
 */
@Component              //将当前类,加载到Spring容器
@Aspect                 //声明切面类
public class MyAspect {

    //前置通知注解
    @Before("execution(* com.czxy.service..*.*(..))")
    public void before() {
        System.out.println("开启事务");
    }

    //后置通知
    @AfterReturning("execution(* com.czxy.service..*.*(..))")
    public void ar() {
        System.out.println("提交事务");
    }
}

通知类型

try {
    //1.前置通知 @Before				//3.环绕通知(前) @Around
    // 业务代码
    //2.后置通知 @AfterReturning		//3.环绕通知(后) @Around
} catch (Exception e) {
    //4.抛出异常通知 @AfterThrowing
} finally {
    //5.最终通知  @After
}
package com.czxy.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;


@Component              //将当前类,加载到Spring容器
@Aspect                 //声明切面类
public class MyAspect {

    //前置通知注解
    @Before("execution(* com.czxy.service..*.*(..))")
    public void before(JoinPoint joinPoint) {
        // 通过连接点(joinPoint)获得方法签名(Signature),从而获得方法的名称
        System.out.println("前置通知: " + joinPoint.getSignature().getName());
    }

    //后置通知,可以获得返回值的,通过returning设置变量名
    @AfterReturning(value = "execution(* com.czxy.service..*.*(..))", returning = "r")
    public void ar(JoinPoint joinPoint, Object r) {
        System.out.println("后置通知:" + joinPoint.getSignature().getName() + ", 返回值:" + r);
    }

    //环绕通知:需要手动执行目标方法,返回值类型Object
    @Around("execution(* com.czxy.service..*.*(..))")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("环绕前:" + proceedingJoinPoint.getSignature().getName());
        //手动执行目标方法
        Object r = proceedingJoinPoint.proceed();
        System.out.println("环绕后");
        return r;
    }

    //抛出异常通知,获得异常类型,通过throwing设置变量名
    @AfterThrowing(value = "execution(* com.czxy.service..*.*(..))", throwing = "e")
    public void afterThrowing(Exception e) {
        System.out.println("抛出异常通知:" + e.getMessage());
    }

    //最终异常
    @After("execution(* com.czxy.service..*.*(..))")
    public void after() {
        System.out.println("最终通知");
    }
}

切入点表达式

  • 切入点指示符用来指示切入点表达式目的。将通知作用到哪里?

  • AspectJ提供多种指示符:

  • 本章节主要学习:execution

  • 语法:execution(访问修饰符? 返回值 包名.类名.方法名(方法参数) throws 异常?)

    • 其中带 ?的表示可以省略的部分

    • 表达式中支持使用一些特殊符号进行模糊匹配

    • * 用于匹配1个或多个位置

    • ..用于匹配0个或多个位置

//实例
//返回值任意   报名.            当前包及其子包   类名任意    方法名任意   参数任意
    *        com.czxy.service      ..        *       .      *     (..)
    
//各个成员取值:
返回值:
    int、String 等,具体的类型
    *            任意类型
包名:
    com.czxy            具体的包
    com.czxy..            当前包及其子包
    com.czxy.*service    以Service结尾的包
类名:
    User*                以User为前缀
    *Service            以Service为后缀
    *                    任意
方法名
    select*                以select开头
    save*                以save开头
参数
    int                    一个参数
    int,int                两个参数
    ..                    任意

  • 参考:https://www.cnblogs.com/cunkouzh/p/5844816.html

  • 参考2:https://blog.csdn.net/qq_63815371/article/details/127785377

 抽取切入点

package com.czxy.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;


@Component              //将当前类,加载到Spring容器
@Aspect                 //声明切面类
public class MyAspect2 {

    // 抽取切入点表达式
    @Pointcut("execution(* com.czxy.service..*.*(..))")
    private void myPointcut(){

    }
    @Before("myPointcut()")
    public void before(JoinPoint joinPoint) {
        System.out.println("前置通知2: " + joinPoint.getSignature().getName());
    }

    @AfterReturning(value = "myPointcut()", returning = "r")
    public void ar(JoinPoint joinPoint, Object r) {
        System.out.println("后置通知2:" + joinPoint.getSignature().getName() + ", 返回值:" + r);
    }

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1341931.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

浅谈安科瑞智能照明系统在马来西亚国家石油公司项目的应用

摘要&#xff1a;随着社会经济的发展及网络技术、通信技术的提高&#xff0c;人们对照明设计提出了新的要求&#xff0c;它不仅要控制照明光源的发光时间、 亮度&#xff0c;而且与其它系统来配合不同的应用场合做出相应的灯光场景。本文介绍了马亚西亚石油公司智能照明项目的应…

磁盘LVM逻辑卷和扩容

一、LVM介绍 1、LVM是Linux中对硬盘分区的一种管理机制。 2、工作原理&#xff1a; ①动态调整磁盘&#xff0c;提高磁盘管理的灵活性 ②/boot分区用于存放引导文件&#xff0c;不能基于LVM创建 ③图形界面管理工具 3、LVM机制的基本概念 ①物理卷&#xff1a;将硬盘转船…

2023年度五大容灾关键词

当前&#xff0c;云计算已成为推动企业数字化转型的关键技术之一。它已逐步渗透进入各个行业&#xff0c;如互联网、政务、金融和制造业&#xff0c;企业上云的比例和应用深度也大幅提升。与此同时&#xff0c;不可抗力因素带来的灾害风险仍然持续&#xff0c;战争、地震、海啸…

Weblogic反序列化远程命令执行(CVE-2019-2725)

漏洞描述&#xff1a; CVE-2019-2725是一个Oracle weblogic反序列化远程命令执行漏洞&#xff0c;这个漏洞依旧是根据weblogic的xmldecoder反序列化漏洞&#xff0c;通过针对Oracle官网历年来的补丁构造payload来绕过。 复现过程&#xff1a; 1.访问ip&#xff1a;port 2.可…

一文浅谈旋转变换:旋转矩阵、旋转向量、欧拉角、四元数

目录 一、旋转矩阵 1.1 定义和推导 1.2 旋转矩阵的缺点 二、旋转向量 2.1 定义和推导 2.1.1 旋转向量转旋转矩阵 2.1.2 旋转矩阵转旋转向量 2.2 旋转向量的缺陷 三、欧拉角 3.1 定义和推导 3.1.1 欧拉角与旋转矩阵 3.1.1.1 欧拉角转旋转矩阵 3.1.1.2 旋转矩阵转欧…

关于“Python”的核心知识点整理大全49

目录 16.2.10 加亮颜色主题 16.3 小结 第&#xff11;7 章 使用API 17.1 使用 Web API 17.1.1 Git 和 GitHub 17.1.2 使用 API 调用请求数据 17.1.3 安装 requests 17.1.4 处理 API 响应 python_repos.py 注意 17.1.5 处理响应字典 python_repos.py import json i…

Python 内置高阶函数练习(Leetcode500.键盘行)

Python 内置高阶函数练习&#xff08;Leetcode500.键盘行&#xff09; 【一】试题 &#xff08;1&#xff09;地址&#xff1a; 500. 键盘行 - 力扣&#xff08;LeetCode&#xff09; &#xff08;2&#xff09;题目 给你一个字符串数组 words &#xff0c;只返回可以使用在…

阿里云数据库polardb怎么收费?

阿里云数据库PolarDB租用价格表&#xff0c;云数据库PolarDB MySQL版2核4GB&#xff08;通用&#xff09;、2个节点、60 GB存储空间55元5天&#xff0c;云数据库 PolarDB 分布式版标准版2核16G&#xff08;通用&#xff09;57.6元3天&#xff0c;阿里云百科aliyunbaike.com分享…

AI数字员工的出现:不是取代,而是让技术更好地服务于人类_光点科技

在人工智能技术迅猛发展的今天&#xff0c;AI数字员工的出现成为了企业和组织关注的热点。与传统观念中的机器人或自动化设备不同&#xff0c;AI数字员工是集成了最新AI技术&#xff0c;如自然语言处理、机器学习和情感分析等功能的虚拟助手&#xff0c;它们能够完成复杂的工作…

.Net FrameWork总结

.Net FrameWork总结 介绍.Net公共语言运行库CLI的组成.NET Framework的主要组成.NET Framework的优点CLR在运行期管理程序的执行&#xff0c;包括以下内容CLR提供的服务FCL的组成 或 服务&#xff08;这个其实就是我们编码时常用到的类库&#xff09;&#xff1a;&#xff08;下…

ERROR: No matching distribution found for torch==2.0.1解决方案

大家好&#xff0c;我是水滴~~ 本文主要介绍在安装 stable-diffusion-webui 时出现的 ERROR: No matching distribution found for torch2.0.1 问题的解决方案&#xff0c;希望能对你有所帮助。 《Python入门核心技术》专栏总目录・点这里 文章目录 问题描述解决方案离线安装 …

WeakMap 和 Map 的区别,WeakMap 原理,为什么能被 GC?

垃圾回收机制 我们知道&#xff0c;程序运行中会有一些垃圾数据不再使用&#xff0c;需要及时释放出去&#xff0c;如果我们没有及时释放&#xff0c;这就是内存泄露 JS 中的垃圾数据都是由垃圾回收&#xff08;Garbage Collection&#xff0c;缩写为 GC&#xff09;器自动回…

MyBatis的基本使用及常见问题

MyBatis 前言MyBatis简介MyBatis快速上手Mapper代理开发增删改查环境准备配置文件完成增删改查查询添加修改删除 参数传递注解完成增删改查 前言 JavaWeb JavaWeb是用Java技术来解决相关Web互联网领域的技术栈。 MySQL数据库与SQL语言 MySQL&#xff1a;开源的中小型数据库。…

【银行测试】金融银行-理财项目面试/分析总结(二)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 银行理财相关的项…

【温故而知新】vue运用之探讨下单页面应用(SPA)与多页面应用(MPA)

一、概念 1.单页面应用SPA(Single page application) Vue单页面应用是一种采用Vue.js框架开发的Web应用程序,它仅有一个HTML文件,通过前端路由实现页面的切换和渲染。与传统的多页面应用相比,Vue单页面应用在用户体验和开发效率方面有着明显的优势。 在Vue单页面应用中…

winsock.h与winsock2.h出现重定义或不同的链接 问题解决

在编译qt windows项目时出现错误 方法&#xff11;&#xff1a; 在pro文件中添加宏 DEFINES WIN32_LEAN_AND_MEAN方法&#xff12;&#xff1a; 在使用了包含头文件前#include<windows.h>加上 #include<WinSock2.h>

SpringCloud(H版alibaba)框架开发教程之nacos做配置中心——附源码(2)

上篇主要讲了使用eureka&#xff0c;zk&#xff0c;nacos当注册中心 这篇内容是nacos配置中心 代码改动部分mysql驱动更新到8.0&#xff0c;数据库版本升级到了8.0&#xff0c;nacos版本更新到了2.x nacos2.x链接 链接&#xff1a;https://pan.baidu.com/s/11nObzgTjWisAfOp…

JMeter逻辑控制器之While控制器

JMeter逻辑控制器之While控制器 1. 背景2.目的3. 介绍4.While示例4.1 添加While控制器4.2 While控制器面板4.3 While控制器添加请求4.3 While控制器应用场景 1. 背景 存在一些使用场景&#xff0c;比如&#xff1a;某个请求必须等待上一个请求正确响应后才能开始执行。或者&…

Android Studio修改创建新布局时默认根布局

将Android Studio默认布局ConstraintLayout切换成LinearLayout 打开设置&#xff0c; Editor> File and Code Templates > Other > layoutResourceFile.xml 备注&#xff1a;创建时提示根布局仍然为ConstraintLayout&#xff0c;不用管这个&#xff0c;实际创建的…

NXP实战笔记(一):基于RTD-SDK新建一个S32DS工程

目录 1、概述 2、操作步骤 2.1、新建Application工程 2.2、命名工程、选择芯片型号、选择编译器GCC版本 2.3、配置基本参数 3、文件描述 3.1、文件结构描述 3.2、编译之后 4、下载调试 1、概述 安装了S32DS之后&#xff0c;导入SDK插件&#xff0c;这个步骤不赘述&…