Spring-Aop核心技术
前言
spring一直以来都是我们Java开发中最核心的一个技术,其中又以ioc和aop为主要技术,本篇文章主要讲一下aop的核心技术,也就是ProxyFactory技术的使用,而基本的jdk动态代理和cglib代理技术并不涉及,如有需要,请自行寻找资料
背景
package com.zxc.boot.proxy;public class OrderService {public void create() {System.out.println("创建订单");}public void payOrder() {System.out.println("支付订单");}
}假设你有如上的对象,需要对两个方法前面都插入生成订单号的逻辑,如果是传统的方式就可以直接加入,但是过于麻烦,如果使用spring的话,就可以借助如下的工具类,如
ProxyFactory
package com.zxc.boot.proxy;import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.aop.framework.ProxyFactory;import java.lang.reflect.Method;public class Main {public static void main(String[] args) {//被代理对象OrderService orderService = new OrderService();ProxyFactory proxyFactory = new ProxyFactory();//设置代理对象proxyFactory.setTarget(orderService);//添加代理逻辑proxyFactory.addAdvice(new MethodBeforeAdvice() {@Overridepublic void before(Method method, Object[] objects, Object o) throws Throwable {System.out.println("-----生成订单号------");}});//获取代理对象OrderService orderServiceProxy = (OrderService) proxyFactory.getProxy();orderServiceProxy.create();orderServiceProxy.payOrder();}
}生成的结果如下(注:这里没有接口,肯定是使用cglib生成的代理对象)

是不是很简单呢,底层逻辑都是spring帮我们实现的,而MethodBeforeAdvice就是进行的代理逻辑,它的父接口是
Advice
这个简单理解就是对象被代理的逻辑,主要有以下的实现,如
MethodBeforeAdvice、AfterReturningAdvice、MethodInterceptor等等见名思义
但是这里有一个问题,我们两个方法都被进行了代理,那么是否有办法实现只代理某个方法,而某些方法不进行代理呢,答案是有的,代码如下
package com.zxc.boot.proxy;import org.aopalliance.aop.Advice;
import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.aop.Pointcut;
import org.springframework.aop.PointcutAdvisor;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.StaticMethodMatcherPointcut;import java.lang.reflect.Method;public class Main2 {public static void main(String[] args) {//被代理对象OrderService orderService = new OrderService();ProxyFactory proxyFactory = new ProxyFactory();//设置代理对象proxyFactory.setTarget(orderService);//添加代理逻辑proxyFactory.addAdvisor(new PointcutAdvisor() {@Overridepublic Pointcut getPointcut() {//哪些方法进行代理return new StaticMethodMatcherPointcut() {@Overridepublic boolean matches(Method method, Class<?> aClass) {//方法名为create进行代理return method.getName().equals("create");}};}//代理逻辑@Overridepublic Advice getAdvice() {return new MethodBeforeAdvice() {@Overridepublic void before(Method method, Object[] objects, Object o) throws Throwable {System.out.println("-----创建订单-----");}};}@Overridepublic boolean isPerInstance() {return false;}});//获取代理对象OrderService orderServiceProxy = (OrderService) proxyFactory.getProxy();orderServiceProxy.create();orderServiceProxy.payOrder();}
}

可以看到,只有创建订单的方法才会添加代理逻辑,而支付订单并不会加入这段逻辑,而核心的功能点就是依赖于Pointcut对象
Pointcut
Pointcut简单理解就是切掉,也就是用于判断要在哪些方法或者哪些类注入代理逻辑用的
Advisor
而Advisor简单理解就是Advice和Pointcut的组合,spring当中进行代理的逻辑也是用Advisor为维度进行处理的
以上,就是使用ProxyFactory进行代理逻辑的spring工具类,但是很明显这样使用相对来说还是比较麻烦的,所以spring提供了简易的方式让我们使用这种逻辑,如下
Spring提供的代理支持
ProxyFactoryBean
package com.zxc.boot.proxy;import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.aop.framework.ProxyFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;import java.lang.reflect.Method;@Configuration
@ComponentScan("com.zxc.boot.proxy")
public class AppConfig {@Beanpublic ProxyFactoryBean proxyFactoryBean() {ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean();proxyFactoryBean.setTarget(new OrderService());proxyFactoryBean.addAdvice(new MethodBeforeAdvice() {@Overridepublic void before(Method method, Object[] objects, Object o) throws Throwable {System.out.println("-------创建订单-------");}});return proxyFactoryBean;}
}package com.zxc.boot.proxy;import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class SpringApplication {public static void main(String[] args) {ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);OrderService orderService = applicationContext.getBean(OrderService.class);orderService.create();orderService.payOrder();}
}
只要进行如上的配置,就可以识别到了,这种方式其实跟原有的差不多,只不过spring帮我们处理了最终会返回对应的代理bean回去,但是还有更简单的方式,如下
DefaultPointcutAdvisor
package com.zxc.boot.proxy;import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.aop.support.NameMatchMethodPointcut;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;import java.lang.reflect.Method;@Configuration
@ComponentScan("com.zxc.boot.proxy")
public class AppConfig2 {@Beanpublic OrderService orderService() {return new OrderService();}@Beanpublic DefaultPointcutAdvisor defaultPointcutAdvisor() {//方法名称蓝机器NameMatchMethodPointcut nameMatchMethodPointcut = new NameMatchMethodPointcut();nameMatchMethodPointcut.addMethodName("create");//设置拦截和代理逻辑DefaultPointcutAdvisor defaultPointcutAdvisor = new DefaultPointcutAdvisor();defaultPointcutAdvisor.setPointcut(nameMatchMethodPointcut);defaultPointcutAdvisor.setAdvice(new MethodBeforeAdvice() {@Overridepublic void before(Method method, Object[] args, Object target) throws Throwable {System.out.println("-------创建订单------");}});return defaultPointcutAdvisor;}//核心类,一个BeanPostProccess后置处理器,用于把扫描到的Advisor进行代理@Beanpublic DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {return new DefaultAdvisorAutoProxyCreator();}
}package com.zxc.boot.proxy;import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class SpringApplication {public static void main(String[] args) {ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig2.class);OrderService orderService = applicationContext.getBean(OrderService.class);orderService.create();orderService.payOrder();}
}
不用我们多做其他处理,就可以对ioc容器中方法有create的类进行代理,你可以再添加一个类,如下
package com.zxc.boot.proxy;public class UserService {public void create() {System.out.println("用户service哦哦哦");}
}
package com.zxc.boot.proxy;import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class SpringApplication {public static void main(String[] args) {ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig2.class);OrderService orderService = applicationContext.getBean(OrderService.class);orderService.create();orderService.payOrder();UserService userService = applicationContext.getBean(UserService.class);userService.create();}
}
这样的方式就方便多了
优化处理
其实DefaultAdvisorAutoProxyCreator只是需要导入到ioc容器中,所以配置类可以使用import进行处理,效果是一样的,如下
package com.zxc.boot.proxy;import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.aop.support.NameMatchMethodPointcut;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;import java.lang.reflect.Method;@Configuration
@ComponentScan("com.zxc.boot.proxy")
@Import(DefaultAdvisorAutoProxyCreator.class)
public class AppConfig2 {@Beanpublic UserService userService() {return new UserService();}@Beanpublic OrderService orderService() {return new OrderService();}@Beanpublic DefaultPointcutAdvisor defaultPointcutAdvisor() {//方法名称蓝机器NameMatchMethodPointcut nameMatchMethodPointcut = new NameMatchMethodPointcut();nameMatchMethodPointcut.addMethodName("create");//设置拦截和代理逻辑DefaultPointcutAdvisor defaultPointcutAdvisor = new DefaultPointcutAdvisor();defaultPointcutAdvisor.setPointcut(nameMatchMethodPointcut);defaultPointcutAdvisor.setAdvice(new MethodBeforeAdvice() {@Overridepublic void before(Method method, Object[] args, Object target) throws Throwable {System.out.println("-------创建订单------");}});return defaultPointcutAdvisor;}// //核心类,一个BeanPostProccess后置处理器,用于把扫描到的Advisor进行代理
// @Bean
// public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
// return new DefaultAdvisorAutoProxyCreator();
// }
}如果你不导入DefaultAdvisorAutoProxyCreator对象,那么代理逻辑就不会生效,本质就是DefaultAdvisorAutoProxyCreator类就是一个BeanPostProcessor处理器,它会针对所有类进行判断然后处理
总结
到这里本篇文章就结束了,spring的aop核心技术就是最终会利用到这个对象进行代理,而这里先把底层的代理逻辑进行讲明,后面对整个aop流程进行理解就方便多了
相关文章:
Spring-Aop核心技术
前言spring一直以来都是我们Java开发中最核心的一个技术,其中又以ioc和aop为主要技术,本篇文章主要讲一下aop的核心技术,也就是ProxyFactory技术的使用,而基本的jdk动态代理和cglib代理技术并不涉及,如有需要ÿ…...
webpack常用优化原理剖析
webpack常用优化原理剖析 按需加载代码配置原理CDN加速-externals代码配置GZIP压缩代码配置原理Tree Shaking代码配置原理按需加载 把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件. 代码配置 //定义了一个异步函数,由于函数不调用不执行,所…...
【现在努力还不晚】--MySQL数据库的数据模型
目录 1、关系型数据库(RDBMS) 特点 2、数据模型 在学习MySQL之前要了解一下数据库的数据模型,我们就知道在MySQL当中,数据是如何存储的,我们了解一下概念! 1、关系型数据库(RDBMS࿰…...
二手商品交易网站
技术:Java、JSP等摘要:随着科学技术和信息通讯的飞速发展,Internet极大地丰富和改变着我们生活的各个行业。随着Internet的普及应用,人们可以跨越时间和空间的限制,足不出户便能通过网络完成信息交流,而完成…...
第三阶段04-同步请求和异步请求,get/post,Josn,pojo,Session/Cookie,过滤器Filter
文章目录同步请求和异步请求客户端如何发出异步请求自定义模板代码Get和Post请求异步版本的注册和登录商品管理系统(异步版本)商品列表步骤:前后端分离为什么需要前后端分离?为什么以后不再使用同步请求?JSONPOJO会话对象Session如何记住登录状态后端的MVC会话管理Cookie通过…...
Spark学习:spark相似算子解析
spark算子 一、Map、Flatmap和MapPartition二、repartition和coalesce三、reduceByKey和groupByKey四、collect、take和first一、Map、Flatmap和MapPartition 算子作用map接收一个高阶函数f,对每个算子进行f操作flatmap接收一个高阶函数f,对每个元素进行f操作,形成一个大的集合…...
MySQL操作数据表-----------创建数据表(一)
在MySQL中创建数据库完成后,需要使用USE 数据库名的形式指定进行操作的数据库,然后再去执行创建数据表的SQL语句,也可以直接使用数据库名.数据表名的形式创建数据表。 1.创建空数据表 语法格式:CREATE TABLE [IF EXISTS] 表名 &…...
Java “框架 = 注解 + 反射 + 设计模式” 之 注解详解
Java ”框架 注解 反射 设计模式“ 之 注解详解 每博一文案 刹那间我真想令时光停住,好让我回顾自己,回顾失去的年华,缅怀哪个穿一身短小的连衣裙 和瘦窄的短衫的小女孩。让我追悔少年时代,我心灵的愚钝无知,它轻易…...
特斯拉4D雷达方案首次曝光!高阶智驾市场比拼安全冗余
随着L2级智能驾驶进入普及阶段,L3/L4级赛道正在成为各家车企的下一个竞争焦点。背后的最大难题,就是如何在成本可控的前提下,保证足够的安全。 高工智能汽车研究院监测数据显示,2022年度中国市场(不含进出口ÿ…...
Echarts 每个柱子一种渐变色的象形柱状图
第023个点击查看专栏目录本示例是解决每个柱状图的每一个柱子都呈现一种渐变色,每个柱子的颜色都不同。这里同时采用了象形的柱状图效果。 文章目录示例效果示例源代码(共125行)相关资料参考专栏介绍示例效果 示例源代码(共125行&…...
叠氮试剂79598-53-1,6-Azidohexanoic Acid,6-叠氮基己酸,末端羧酸可与伯胺基反应
●中文名:6-叠氮基己酸●英文名:6-Azidohexanoic Acid,6-Azidohexanoic COOH●外观以及性质:西安凯新生物科技有限公司供应的6-Azidohexanoic Acid浅黄色或者无色油状,叠氮化物可使用铜催化的Click化学与末端炔烃共轭&…...
Nginx网站服务——编译安装、基于授权和客户端访问控制
文章目录一、Nginx概述1.1、Nginx的特点1.2、Nginx编译安装1.3、Nginx运行控制1.4、Nginx和Apache的区别二、编译安装Nginx服务的操作步骤2.1、关闭防火墙,将安装nginx所需软件包传到/opt目录下2.2、安装依赖包2.3、创建运行用户、组(Nginx 服务程序默认…...
Spring Boot 版本升级2.2.11.RELEASE至2.7.4
2.2.11.RELEASE > 2.7.4项目更新spring-boot-starter-parent 主依赖,导致项目跑不起了日志也没有输出有用信息,自己查看源码调试启动入口打断点,一步步进入方法定位项目停止代码我的项目执行到SpringApplication.class 的152行代码会停止项…...
OpenShift 4 - 使用辅助安装器安装单节点 OpenShift
文章目录单节点 OpenShift 和 OpenShift 辅助安装器单节点 OpenShiftOpenShift 辅助安装器使用辅助安装器安装单节点 OpenShift本文使用的安装环境准备环境在宿主机上安装 KVM 环境创建 SSH 证书根据集群配置,用辅助安装器生成 Discovery ISO用 Discovery ISO 启动 …...
Allegro如何快速锁定整板测试点操作指导
Allegro如何快速锁定整板测试点操作指导 在做PCB设计的时候,会需要给整板添加测试点,用于飞针测试,如下图 在测试点添加好之后,文件输出之前需要把测试点全部锁定,避免因为测试点模具开好,测试点被移动的情况出现 如果逐个锁定Via,容易遗漏 Allegro支持快速锁定整板测…...
系统分析师---知识产权标准化思维导图
保护范围以及对象(3星) 著作权法:不用申请,作品完整即保护绘画摄影作品,原件持有人只是所有权与展览权,著作权归原作者 专利法:专利权需要申请商标法:商标权需要申请反不正当竞争法…...
HiEV洞察 | 特斯拉HW4.0再爆猛料,高精定位、雷达均有变动
作者 | 查理斯 编辑 | 王博特斯拉 HW4.0 消息传出后,有人爆料说在硬件层面发生了巨大变化,引发行业轰动。大家都在猜测HW4.0 具体做了哪些改动。 2月16日,Twitter用户greentheonly爆出HW4.0的主板拆解照片。2月18日又爆出毫米波雷达的拆解照片…...
潜伏的 Linux Rootkit:Syslogk
Rootkit 是非常危险的恶意软件,一旦侵入就很难被发现。开发 Rootkit 通常更加困难,很多攻击者都倾向于重用开源项目。 Adore-Ng 是一个相对较老的、开源的 Linux 内核 Rootkit,最初针对内核 2.x 版本开发,但目前已更新为针对内核…...
JVM总结
1. 内存结构 线程私有区 程序计算器 作用:是一块较小的内存空间,存储的是当前线程所执行的字节码文件的序号特点:线程私有,不会出现内存空间溢出 虚拟机栈 虚拟机栈是管理JAVA方法执行的内存模型,每个方法执行时都…...
AOF:redis宕机,如何避免数据丢失
由于redis是基于内存的数据库,一旦宕机,数据就会丢失?如何解决? 目前,Redis 的持久化主要有两大机制,即 AOF(Append Only File)日志和 RDB(Redis DataBase) 快照。 AO…...
(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)
题目:3442. 奇偶频次间的最大差值 I 思路 :哈希,时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况,哈希表这里用数组即可实现。 C版本: class Solution { public:int maxDifference(string s) {int a[26]…...
从零实现富文本编辑器#5-编辑器选区模型的状态结构表达
先前我们总结了浏览器选区模型的交互策略,并且实现了基本的选区操作,还调研了自绘选区的实现。那么相对的,我们还需要设计编辑器的选区表达,也可以称为模型选区。编辑器中应用变更时的操作范围,就是以模型选区为基准来…...
Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...
前端倒计时误差!
提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...
【JVM】- 内存结构
引言 JVM:Java Virtual Machine 定义:Java虚拟机,Java二进制字节码的运行环境好处: 一次编写,到处运行自动内存管理,垃圾回收的功能数组下标越界检查(会抛异常,不会覆盖到其他代码…...
uniapp微信小程序视频实时流+pc端预览方案
方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度WebSocket图片帧定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐RTMP推流TRTC/即构SDK推流❌ 付费方案 (部分有免费额度&#x…...
智能仓储的未来:自动化、AI与数据分析如何重塑物流中心
当仓库学会“思考”,物流的终极形态正在诞生 想象这样的场景: 凌晨3点,某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径;AI视觉系统在0.1秒内扫描包裹信息;数字孪生平台正模拟次日峰值流量压力…...
浅谈不同二分算法的查找情况
二分算法原理比较简单,但是实际的算法模板却有很多,这一切都源于二分查找问题中的复杂情况和二分算法的边界处理,以下是博主对一些二分算法查找的情况分析。 需要说明的是,以下二分算法都是基于有序序列为升序有序的情况…...
2025季度云服务器排行榜
在全球云服务器市场,各厂商的排名和地位并非一成不变,而是由其独特的优势、战略布局和市场适应性共同决定的。以下是根据2025年市场趋势,对主要云服务器厂商在排行榜中占据重要位置的原因和优势进行深度分析: 一、全球“三巨头”…...
JS手写代码篇----使用Promise封装AJAX请求
15、使用Promise封装AJAX请求 promise就有reject和resolve了,就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...
