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…...
RISC-V开源指令集架构:从设计哲学到商业落地的芯片设计新范式
1. 开源指令集架构的浪潮:从RISC-V研讨会看芯片设计新范式2015年6月底,加州大学伯克利分校的一场研讨会,意外地成为了半导体行业一个微小但意义深远的注脚。这场以RISC-V——一个源自伯克利的开源指令集架构——为主题的会议,不仅…...
诛仙手游多开最多几开?用什么云手机比较好?
很多喜欢玩诛仙手游的朋友们都喜欢多开,但是今天小编告诉你们多开也不能开太多哦,要选择合适的云手机多开才行,不然同一个ip多开很容易封号,今天小宝就来给大家分析诛仙多开几个比较合适,以及用什么云手机多开不容易封…...
Linux驱动开发避坑指南:手把手教你实现三种mmap内存映射(附完整代码)
Linux驱动开发实战:三种mmap内存映射方案深度解析与性能对比 在嵌入式系统和图形处理领域,直接访问内核内存的需求日益增长。想象一下这样的场景:你正在开发一个视频处理驱动,需要将摄像头采集的高清帧数据传输到用户空间进行实时…...
PyQt5实战:从Designer拖拽到打包exe,手把手打造你的第一个多页面桌面应用
PyQt5实战:从Designer拖拽到打包exe,手把手打造你的第一个多页面桌面应用 在数字化浪潮席卷各行各业的今天,图形用户界面(GUI)开发已成为程序员必备技能之一。而PyQt5作为Python最强大的GUI框架,凭借其丰富…...
Box64终极指南:5分钟学会在ARM设备上运行x86_64程序
Box64终极指南:5分钟学会在ARM设备上运行x86_64程序 【免费下载链接】box64 Box64 - Linux Userspace x86_64 Emulator with a twist, targeted at ARM64, RV64 and LoongArch Linux devices 项目地址: https://gitcode.com/gh_mirrors/bo/box64 你是否曾经梦…...
从人工到有机:数字健康AI的范式转变与工程实践
1. 从“人工”到“有机”:一次关于智能本质的范式转变在数字健康领域,我们每天都在与“人工智能”打交道。从辅助医生阅片的影像分析系统,到预测患者风险的算法模型,AI似乎已经成为推动医疗革新的核心引擎。然而,当我们…...
Matplotlib保存图片尺寸总不对?搞懂bbox_inches=‘tight‘与figsize的‘相爱相杀’,一篇就够了
Matplotlib保存图片尺寸总不对?搞懂bbox_inchestight与figsize的‘相爱相杀’,一篇就够了 当你精心设计了一个数据可视化图表,设置了完美的figsize(10, 8)和dpi100,期待得到一张1000x800像素的精美图片,却在保存时发现…...
D3KeyHelper:5个技巧让暗黑破坏神3操作效率翻倍的智能宏工具完全指南
D3KeyHelper:5个技巧让暗黑破坏神3操作效率翻倍的智能宏工具完全指南 【免费下载链接】D3keyHelper D3KeyHelper是一个有图形界面,可自定义配置的暗黑3鼠标宏工具。 项目地址: https://gitcode.com/gh_mirrors/d3/D3keyHelper 你是否曾在《暗黑破…...
企业如何通过Taotoken实现API Key的统一管理与审计
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 企业如何通过Taotoken实现API Key的统一管理与审计 在将大模型能力集成到企业业务流程的过程中,一个常见的挑战是如何安…...
如何轻松备份微信聊天记录:iOS用户的终极解决方案
如何轻松备份微信聊天记录:iOS用户的终极解决方案 【免费下载链接】WeChatExporter 一个可以快速导出、查看你的微信聊天记录的工具 项目地址: https://gitcode.com/gh_mirrors/wec/WeChatExporter 你是否曾经因为手机损坏或更换设备而丢失了珍贵的微信聊天记…...
