【第五章 AOP概述,底层原理,AOP术语,切入点表达式,AOP操作(基于注解方式,基于xml配置文件)】
第五章 AOP概述,底层原理,AOP术语,切入点表达式,AOP操作(基于注解方式,基于xml配置文件)
1.AOP概述:
(1)什么是AOP:
①面向切面编程(方面),利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分间的耦合度降低,提高程序的可重用性,同时提高开发的效率。
②通俗描述:不通过修改源代码方式,在主干功能里面添加新功能。
(2)底层原理:
①AOP底层使用动态代理:有两种情况动态代理。
第一种,有接口情况:使用jdk动态代理;
创建接口实现类代理对象,增强类的方法。
第二种,没有接口情况,使用CGLIB动态代理。
创建子类的代理对象,增强类的方法。
②AOP(jdk动态代理):
a.使用jdk动态代理,使用Proxy类里面的方法创建代理对象。
调用newProxyInstance方法
方法有三个参数:
第一个参数:类加载器。
第二个参数:增强方法所在类,这个类实现的接口,支持多个接口。
第三个参数:实现这个接口InvocationHandler,创建代理对象,写增强的方法。
b.编写jdk动态代理代码。
第一步:创建接口,定义方法;
public interface UserDao {public int add(int a,int b);public String update(String id);
}
第二步:创建接口实现类,实现方法;
public class UserDaoImpl implements UserDao {@Overridepublic int add(int a, int b) {System.out.println("add方法执行了");return a+b;}@Overridepublic String update(String id) {System.out.println("update方法执行了");return id;}
}
第三步:使用Proxy类创建接口代理对象;
public class JDKProxy {public static void main(String[] args) {//创建接口实现类代理对象Class[] interfaces={UserDao.class};UserDaoImpl userDao=new UserDaoImpl();UserDao dao = (UserDao) Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new UserDaoProxy(userDao));int result = dao.add(1, 2);System.out.println("result"+result);}
}
//创建代理对象代码
class UserDaoProxy implements InvocationHandler{//把创建的是谁的代理对象,把谁传递过来//有参数的构造进行传递private Object obj;public UserDaoProxy( Object obj){this.obj=obj;}//增强的逻辑@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//方法之前System.out.println("方法之前执行"+method.getName()+":传递参数--->"+ Arrays.toString(args));//被增强的方法执行Object res = method.invoke(obj, args);//方法之后System.out.println("在方法之后执行"+obj);return res;}
}
(3)AOP术语:
①连接点:类里面哪些方法可以被增强,这些方法称为连接点。
②切入点:实际被真正增强的方法,称为切入点。
③通知(增强):实际增强的逻辑部分称为通知(增强)
通知有多种类型:前置通知、后置通知、环绕通知、异常通知、最终通知(类似于try-catch中的finally)
④切面:把通知应用到切入点的过程。
2.AOP操作(准备工作):
(1)在spring框架中一般基于AspectJ实现AOP操作。
AspectJ:不是spring组成部分,独立AOP框架,一般把AspectJ和spring框架一起使用,进行AOP操作。
(2)基于AspectJ实现AOP操作。
①基于xml配置文件实现;
②基于注解方式实现。
(3)在项目中引入AOP依赖:
(4)切入点表达式:
①切入点表达式作用:知道要对哪个类里面的哪个方法进行增强。
②语法结构:
execution([权限修饰符] [返回类型] [类全路径名] [方法名称] [参数列表])
举例1:对demo1.dao.BookDao类里面的add进行增强
execution(* demo1.dao.BookDao.add(..))
举例2:对demo1.dao.BookDao类里面的所有方法进行增强
execution(* demo1.dao.BookDao.*(..))
举例3:对demo1.dao.包里面的所有类,类里面的所有方法进行增强
execution(* demo1.dao.*.*(..))
3.AOP操作(AspectJ 基于注解方式)
(1)创建类,在类里面定义方法;
//被增强类
public class User {public void add(){System.out.println("add......");}
}
(2)创建增强类,编写增强逻辑
①在增强类里面,创建方法,让不同的方法代表不同通知类型。
//增强类
public class UserProxy {//前置通知public void before(){System.out.println("before....");}
}
(3)进行通知的配置
①在spring配置文件中,开启注解的扫描
<?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.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"><!--开启注解扫描--><context:component-scan base-package="aopano"></context:component-scan>
②使用注解创建User和UserProxy对象
@Component
public class User {}
@Component
public class UserProxy {}
③在增强类上面添加注解@Aspect
@Component
@Aspect
public class UserProxy {}
④在spring配置文件中开启生成代理对象
<!--开启Aspect生成代理对象--><aop:aspectj-autoproxy></aop:aspectj-autoproxy>
(4)配置不同类型的通知
①在增强类里面,在作为通知方法上面添加通知类型注解,使用切入点表达式配置
//增强类
@Component
@Aspect
public class UserProxy {//前置通知@Before(value = "execution(* aopano.User.add(..))")public void before(){System.out.println("before....");}
}
测试的时候执行的是被增强的方法@Testpublic void testAopno(){ApplicationContext applicationContext=new ClassPathXmlApplicationContext("bean2.xml");User user = applicationContext.getBean("user", User.class);user.add();}

//前置通知@Before(value = "execution(* aopano.User.add(..))")public void before(){System.out.println("before....");}//最终通知@After(value = "execution(* aopano.User.add(..))")public void after(){System.out.println("after....");}//后置通知@AfterReturning(value = "execution(* aopano.User.add(..))")public void afterReturning(){System.out.println("afterReturning....");}//异常通知@AfterThrowing(value = "execution(* aopano.User.add(..))")public void afterThrowing(){System.out.println("afterThrowing....");}//环绕通知@Around(value = "execution(* aopano.User.add(..))")public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {System.out.println("环绕之前");//被增强的方法执行proceedingJoinPoint.proceed();System.out.println("环绕之后");}
(5)公共切入点进行抽取:
//相同切入点进行抽取@Pointcut(value = "execution(* aopano.User.add(..))")public void pointdemo(){}//前置通知@Before(value = "pointdemo()")public void before(){System.out.println("before....");}
(6)有多个增强类对同一个方法进行增强,设置增强类优先级。
在增强类的上面添加注解@Order(数字类型值),数字类型值越小,优先级越高。
@Component
@Aspect
@Order(1)
public class personProxy {@Before(value = "execution(* aopano.User.add(..))")public void afterReturning(){System.out.println("person before ....");}
}
4.AOP操作(AspectJ 基于xml配置文件方式)(了解)
(1)创建两个类,增强类和被增强类,创建方法;
public class Book {public void buy(){System.out.println("buy.....");}
}
public class BookProxy {public void before(){System.out.println("before....");}
}
(2)在spring配置文件中创建两个类对象;
<!--创建两个类的对象--><bean id="book" class="aopxml.Book"></bean><bean id="bookProxy" class="aopxml.BookProxy"></bean>
(3)在spring配置文件中配置切入点。
<!--aop的增强--><aop:config ><!--切入点--><aop:pointcut id="p" expression="execution(* aopxml.Book.buy(..))"/><!--配置切面--><aop:aspect ref="bookProxy"><!--增强作用在具体的方法上--><aop:before method="before" pointcut-ref="p"></aop:before></aop:aspect></aop:config>
相关文章:
【第五章 AOP概述,底层原理,AOP术语,切入点表达式,AOP操作(基于注解方式,基于xml配置文件)】
第五章 AOP概述,底层原理,AOP术语,切入点表达式,AOP操作(基于注解方式,基于xml配置文件) 1.AOP概述: (1)什么是AOP: ①面向切面编程(…...
面试官: 你知道 JWT、JWE、JWS 、JWK嘛?
想起了 之前做过的 很多 登录授权 的项目 它相比原先的session、cookie来说,更快更安全,跨域也不再是问题,更关键的是更加优雅 ,所以今天总结了一篇文章来介绍他 JWT 指JSON Web Token,如果在项目中通过 jjwt 来支持 J…...
基于企业微信应用消息的每日早安推送
基于企业微信应用消息的每日早安推送 第一步:注册企业微信 企业微信注册地址:https://work.weixin.qq.com/wework_admin/register_wx 按照正常流程填写信息即可,个人也可以注册企业微信,不需要公司 注册完成后,登录…...
【数字IC基础】黑盒验证、白盒验证、 灰盒验证
文章目录 一、黑盒验证二、白盒验证三、灰盒验证一、黑盒验证 1、黑盒验证:大多数基于仿真的验证环境都是黑盒验证;2、不需要知道设计的内部结构和特性,只需要在输入端口打激励,观察输出即可;3、验证工程师学习设计的规格,然后编写验证环境中的 drivers, monitors, check…...
管理的本质是达成目标
“没有目标,其实就没有管理学存在的意义。要有效地使用管理学的智慧,首先要建立清晰的目标。” - 《宁向东的管理学课》 起源 最近开始刷很久之前就在得到上买了的已经起灰了的课程,看到这句话觉得很有道理。 思考 这里面有一个很重要的词…...
【数字IC基础】IC(Integrated Circuit,集成电路)常用缩写
文章目录 1、集成电路:2、数字IC设计相关步骤:3、数字设计相关概念:4、验证相关:5、语言类:6、IC设计相关工具:7、存储器相关:8、总线协议类:9、文件格式类:10、标准和规范:11、其它:1、集成电路: 缩写全称中文翻译LSILarge-scale intergrated circuit大规模集成电…...
JavaScript 高级1 :面向对象
JavaScript 高级1 :面向对象 Date: January 16, 2023 Text: 面向对象、ES6中类和对象、类的继承、面向对象案例 目标: 能够说出什么是面向对象 能够说出类和对象的关系 能够使用 class 创建自定义类型 能够说出什么是继承 面向对象编程介绍 面向过…...
C语言结构体对齐
1. 结构体对齐 要点 变量只能存储在他的长度的整数倍地址上结构体整体对齐跟他的最长的字段整数倍对齐 栗子1 struct Example1 {char a; //1个字节int c; //4个字节short b; //2个字节 };std::cout << sizeof(Example1 ) << std::endl; // 12 std::cout &…...
Bootstrap系列之导航
Bootstrap导航 可以在 ul 元素上添加 .nav类,在每个 li 选项上添加 .nav-item 类,在每个链接上添加 .nav-link 类: 基本的导航 <div class"container mt-3"><h2>导航</h2><p>简单的水平导航:</p><ul class&…...
Java EE|TCP/IP协议栈之应用层协议DNS详解
文章目录一、对DNS的感性认识简介特点一些常见疑问二、DNSDNS域名结构域名的分级三、域名服务器四、域名解析过程参考一、对DNS的感性认识 简介 DNS,即Domain Name System,是域名系统的简称。它是Internet上解决网上机器命名的一种系统。 TCP/IP中的IP地址是由四…...
【MyBatis】作用域生命周期(四)
🚗MyBatis学习第四站~ 🚩起始站:MyBatis概述&环境搭建(一) 🚩本文已收录至专栏:数据库学习之旅 👍希望您能有所收获 一.引入 为了使用方便,我们经常能看到各种教程都将MyBatis抽离为工具类…...
腾讯一面—Android 系统启动流程详解
正文AMS 是 Android 中最核心的服务之一,主要负责系统中四大组件的启动、切换、调度及应用进程的管理和调度等工作,其职责与操作系统中的进程管理和调度模块相类似,它本身也是一个 Binder 的实现类,应用进程能通过 Binder 机制调用…...
【Python知识点桂电版】02组合数据类型
一、序列序列简介序列是指一种包含多项数据的数据结构,分为不可变序列和可变序列。可变序列可修改序列内的元素如列表,二不可变序列一旦建立就不能修改其中的元素,字符串和元组属于不可变序列。列表和元组的创建列表:列表名 [元素…...
LeetCode100_100. 相同的树
LeetCode100_100. 相同的树 一、描述 给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同。 如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。 示例 1: 输入:p [1,2,3], q […...
javaEE 初阶 — 网络层中 IP 协议 的报文结构
文章目录IP 协议报文4位版本号4位首部长度8位服务类型16位总长度(字节数)8位生存时间(TTL)与 8位协议16位首部校验和32位源 IP 地址与32位目标 IP 地址动态分配的 IP 地址NAT 网络地址转换IPv6IP 协议报文 4位版本号 这里的 IP 协…...
iOS swift UICollectionView
文章目录1.纯代码自定义UICollectionViewCell2.禁止滑动(弹簧效果)3.UICollectionView的长按拖动2.在一个控制器中放两个UICollectionView或者UITableView,代理方法要怎么写1.纯代码自定义UICollectionViewCell import UIKitclass NewDeviceBottomColle…...
计算机三级数据库 填空题汇总
计算机三级 数据库 IDEF0需求建模方法由箭头和(活动/方框/矩形)两种元素构成。、从安全性角度考虑,防火墙技术是用来保证数据库应用系统的(网络)环境安全的。在UML的状态机图中,状态之间的转移是由&#x…...
【Java学习】初识Java
JavaSEJava初识1. Java简介2.Java环境的安装与配置3. 开发第一个Java程序Java初识 学前疑问:(带着疑问去学习,在学习中自行探索答案) Java是什么?能做什么?发展前景如何?需要学习哪些内容&…...
LabVIEW网络服务安全
LabVIEW网络服务安全如何保护Web服务?当许多人考虑安全性时,他们会考虑加密、用户ID和密码。用户ID和密码用于授权(告诉目标谁在发出请求)。加密保护客户端和服务器之间的通信流量,以便未经授权的个人无法拦截和读取发…...
基于MaixBit(K210芯片)的图像识别猜拳手势博弈装置
本文介绍了一种基于嵌入式平台开发的图像识别部署装置,其主要功能包括实现机器与人的“猜拳博弈”,其组成分为三个部分:手势检测数据集图像识别模型训练模型格式部署maixbit开发板部署手势检测数据集:本项目的数据集包括三种标签&…...
在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module
1、为什么要修改 CONNECT 报文? 多租户隔离:自动为接入设备追加租户前缀,后端按 ClientID 拆分队列。零代码鉴权:将入站用户名替换为 OAuth Access-Token,后端 Broker 统一校验。灰度发布:根据 IP/地理位写…...
spring:实例工厂方法获取bean
spring处理使用静态工厂方法获取bean实例,也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下: 定义实例工厂类(Java代码),定义实例工厂(xml),定义调用实例工厂ÿ…...
【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)
升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点,但无自动故障转移能力,Master宕机后需人工切换,期间消息可能无法读取。Slave仅存储数据,无法主动升级为Master响应请求ÿ…...
让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比
在机器学习的回归分析中,损失函数的选择对模型性能具有决定性影响。均方误差(MSE)作为经典的损失函数,在处理干净数据时表现优异,但在面对包含异常值的噪声数据时,其对大误差的二次惩罚机制往往导致模型参数…...
人工智能(大型语言模型 LLMs)对不同学科的影响以及由此产生的新学习方式
今天是关于AI如何在教学中增强学生的学习体验,我把重要信息标红了。人文学科的价值被低估了 ⬇️ 转型与必要性 人工智能正在深刻地改变教育,这并非炒作,而是已经发生的巨大变革。教育机构和教育者不能忽视它,试图简单地禁止学生使…...
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...
深入理解Optional:处理空指针异常
1. 使用Optional处理可能为空的集合 在Java开发中,集合判空是一个常见但容易出错的场景。传统方式虽然可行,但存在一些潜在问题: // 传统判空方式 if (!CollectionUtils.isEmpty(userInfoList)) {for (UserInfo userInfo : userInfoList) {…...
MySQL 主从同步异常处理
阅读原文:https://www.xiaozaoshu.top/articles/mysql-m-s-update-pk MySQL 做双主,遇到的这个错误: Could not execute Update_rows event on table ... Error_code: 1032是 MySQL 主从复制时的经典错误之一,通常表示ÿ…...
小木的算法日记-多叉树的递归/层序遍历
🌲 从二叉树到森林:一文彻底搞懂多叉树遍历的艺术 🚀 引言 你好,未来的算法大神! 在数据结构的世界里,“树”无疑是最核心、最迷人的概念之一。我们中的大多数人都是从 二叉树 开始入门的,它…...
消息队列系统设计与实践全解析
文章目录 🚀 消息队列系统设计与实践全解析🔍 一、消息队列选型1.1 业务场景匹配矩阵1.2 吞吐量/延迟/可靠性权衡💡 权衡决策框架 1.3 运维复杂度评估🔧 运维成本降低策略 🏗️ 二、典型架构设计2.1 分布式事务最终一致…...
