代理(主要是动态)和SpringAOP

代理

  • 静态代理基于继承实现
  • 动态代理是基于接口实现
业务层每次实现转账都需要执行,可以把他们拿出来当成一个切面,自己写出一个代理类,让业务层只执行业务的逻辑,重复的代码代理类来完成,然后调用代理类来执行。
代理类
package com.qcby.utils;import com.qcby.service.AccountService;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;//传入目标对象,生成该对象的代理对象,返回。对目标对象的方法进行增强
public class ProxyUtils {//获取代理对象,返回,增强目标对象的方法public static Object getProxy(final AccountService accountService){//使用jdk动态dialing生成代理对象Object proxy = Proxy.newProxyInstance(ProxyUtils.class.getClassLoader(), accountService.getClass().getInterfaces(), new InvocationHandler() {//调用代理对象的方法,invoke方法就会去执行public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//目标对象的方法Object result = null;try {//开启事务TxUtils.startTransaction();//目标对象的方法进行增强,作为结果返回result = method.invoke(accountService,args);//事务提交TxUtils.commit();}catch (Exception e){e.printStackTrace();//事务回滚TxUtils.rollback();}finally {//资源关闭TxUtils.close();}return result;}});return proxy;}
}
测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class Demo2 {@Autowiredprivate AccountService accountService;@Testpublic void run1(){Account account1 = new Account();account1.setName("aaa");Account account2 = new Account();account2.setName("bbb");//创建代理对象AccountService proxy = (AccountService) ProxyUtils.getProxy(accountService);proxy.saveAll(account1,account2);}
}

     AOP

    配置文件形式:(IOC也是用的配置文件形式)
    配置文件
    <?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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd"><!--将目标类配置到spring中--><bean id="userService" class="com.qcby.demo1.UserServiceImpl"/><!--将切面类配置到spring中--><bean id="myXmlAspect" class="com.qcby.demo1.MyXmlAspect"/><!--配置AOP的增强--><aop:config><!--配置切面 = 通知+切入点组成--><aop:aspect ref="myXmlAspect"><!--通用写法--><!--<aop:before method="log" pointcut="execution(public * com.qcby.*.*ServiceImpl.*(..))"/>--><!--前置通知:无论方法成功与否都执行--><!--<aop:before method="log" pointcut="execution(public void com.qcby.demo1.UserServiceImpl.save())"/>--><!--最终通知:失败成功都执行--><!--<aop:after method="log" pointcut="execution(public void com.qcby.demo1.UserServiceImpl.save())"/>--><!--后置通知:方法成功执行之后执行--><!--<aop:after-returning method="log" pointcut="execution(public * com.qcby.*.*ServiceImpl.*(..))"/>--><!--异常通知:有异常才执行--><!--<aop:after-throwing method="log" pointcut="execution(public void com.qcby.demo1.UserServiceImpl.save())"/>--><!--环绕通知:目标方法执行前后都执行  执行方法成功与否对执行前的增强不影响(方法执行不成功也执行前置的)--><aop:around method="aroundLog" pointcut="execution(public * com.qcby.demo1.*ServiceImpl.*(..))"/></aop:aspect></aop:config></beans>
    切面类
    package com.qcby.demo1;import org.aspectj.lang.ProceedingJoinPoint;/*定义切面类 = 切入点(表达式)+通知*/
    //在配置文件里配置成切面类=增强的方法(通知)+需要增强的方法(切入点)
    public class MyXmlAspect {/*通知*/public void log(){//发送手机短信//发送邮件、记录日志、事务管理System.out.println("增强的方法执行了....");}public void log1(){//发送手机短信//发送邮件、记录日志、事务管理System.out.println("前置增强的方法执行了....");}public void log2(){//发送手机短信//发送邮件、记录日志、事务管理System.out.println("后置增强的方法执行了....");}/*环绕通知*/public void aroundLog(ProceedingJoinPoint proceedingJoinPoint){try {log1();proceedingJoinPoint.proceed();log2();} catch (Throwable throwable) {throwable.printStackTrace();}}
    }
    测试类
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = "classpath:applicationContext.xml")
    public class Demo1 {@Autowiredprivate UserService userService;/*测试*/@Testpublic void run1(){userService.save();}
    }
    半注解方式
    切面类=通知+切入点(现在的切面类已经在通知上添加了切入点)
    package com.qcby.demo2;import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.*;
    import org.springframework.stereotype.Component;@Component  // 把该类交给 IOC 去管理
    @Aspect // 声明是切面类 == <aop:aspect ref="myXmlAspect">
    public class MyAnnoAspect {//@Before(value = "execution(public * com.qcby.*.*ServiceImpl.*(..))")public void log1(){System.out.println("前置通知增强的方法执行...");}//@AfterReturning(value = "execution(public * com.qcby.*.*ServiceImpl.*(..))")public void log2(){System.out.println("后置通知增强的方法执行...");}//@After(value = "execution(public * com.qcby.*.*ServiceImpl.*(..))")public void log3(){System.out.println("最终通知增强的方法执行...");}//@AfterThrowing(value = "execution(public * com.qcby.*.*ServiceImpl.*(..))")public void log4(){System.out.println("异常通知增强的方法执行...");}@Around(value = "execution(public * com.qcby.*.*ServiceImpl.*(..))")public void log5(ProceedingJoinPoint proceedingJoinPoint){try {log1();proceedingJoinPoint.proceed();log2();} catch (Throwable throwable) {throwable.printStackTrace();}}
    }
    配置文件
    <!--配置文件中开启自动代理-->
    <aop:aspectj-autoproxy/>
    <!--开启注解扫描-->
    <context:component-scan base-package="com.qcby" />
    测试类
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = "classpath:applicationContext.xml")
    public class Demo2 {@Autowiredprivate AccountService accountService;@Testpublic void run1(){accountService.save();}
    }
    纯注解形式
    配置类
    @Configuration  // 配置类
    @ComponentScan(value = "com.qcby")  // 扫描包
    @EnableAspectJAutoProxy  // 开启自动代理 == <aop:aspectj-autoproxy/>
    public class SpringConfig {
    }
    切面类
    与半注解形式一样
    测试类
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(classes = SpringConfig.class)
    public class Demo2 {@Autowiredprivate AccountService accountService;@Testpublic void run1(){accountService.save();}
    }
    出现异常时:前置方法,最终方法,异常方法都会执行

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

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

    相关文章

    uniapp打包H5,输入网址空白情况

    由于客户预算有限&#xff0c;最近写了两个uniapp打包成H5的案例&#xff0c;总结下面注意事项 1. 发行–网站-PCWeb或手机H5按钮&#xff0c;输入名称&#xff0c;网址 点击【发行】&#xff0c;生成文件 把这个给后端&#xff0c;就可以了 为什么空白呢 最重要一点&#xf…

    uniapp-商城-63-后台 商品列表(分类展示商品的删除)

    商品列表中的数据需要进行状态管理&#xff0c;如上架、下架、删除和修改等操作。对于存在错误或后期需要重新上传的商品&#xff0c;可以通过删除操作进行处理。 具体到商品删除功能的实现&#xff0c;其基本流程如下&#xff1a;用户在前端页面点击删除按钮后&#xff0c;系统…

    学习设计模式《十》——代理模式

    一、基础概念 代理模式的本质【控制对象访问】&#xff1b; 代理模式的定义&#xff1a;为其他对象提供一种代理以控制对这个对象的访问&#xff1b; 代理模式的功能&#xff1a;代理模式是通过创建一个代理对象&#xff0c;用这个代理对象去代表真实的对象&#xff1b;客户端得…

    阿里云web端直播(前端部分)

    阿里云&#xff1a;Web播放器快速接入_视频点播(VOD)-阿里云帮助中心 import Aliplayer from aliyun-aliplayerimport aliyun-aliplayer/build/skins/default/aliplayer-min.css<div id"J_prismPlayer" style"width: 300px; height: 300px;" />var …

    深入解析OrientDB:多模型数据库的技术优势与实际应用

    OrientDB 是一款开源的多模型 NoSQL 数据库&#xff0c;融合了文档数据库、图数据库和对象数据库的特性。它不仅支持灵活的数据建模&#xff0c;还提供了高性能的查询能力&#xff0c;适用于社交网络、物联网、内容管理等场景。本文详细探讨 OrientDB 的核心特性、应用场景&…

    STM32控制电机

    初始化时钟&#xff1a;在 STM32 的程序中&#xff0c;初始化系统时钟&#xff0c;一般会使用 RCC&#xff08;Reset and Clock Control&#xff09;相关函数来配置时钟。例如&#xff0c;对于 STM32F103 系列&#xff0c;可能会使用 RCC_APB2PeriphClockCmd 函数来使能 GPIO 和…

    (05)数字化转型之生产制造:从通常的离散制造到柔性化生产的全景指南

    当今制造业正经历着前所未有的数字化变革&#xff0c;从传统的离散制造到流程制造&#xff0c;再到新兴的项目制造和柔性制造&#xff0c;各种生产模式都在加速向智能化方向演进。本文将系统性地介绍制造业生产管理的完整体系&#xff0c;为企业数字化转型提供全面的方法论和实…

    龙虎榜——20250520

    上证指数今天缩量向上&#xff0c;个股涨多跌少&#xff0c;大盘股和小盘股总体表现都还可以。 深证同样缩量上涨&#xff0c;向上补缺口的概率增大。 2025年5月20日龙虎榜行业方向分析 宠物经济&#xff08;消费升级政策催化&#xff09; • 代表标的&#xff1a;天元宠物、…

    CVE-2022-22978源码分析与漏洞复现

    漏洞概述 CVE-2022-22978 是 Spring Security 框架中的一个高危认证绕过漏洞&#xff0c;影响版本包括 Spring Security 5.5.x < 5.5.7、5.6.x < 5.6.4 及更早的不受支持版本。攻击者可通过构造包含换行符&#xff08;如 %0a&#xff09;的 URL 路径&#xff0c;绕过正则…

    PostGIS实现栅格数据入库【raster2pgsql】

    raster2pgsql使用与最佳实践 一、工具概述 raster2pgsql是PostGIS提供的命令行工具,用于将GDAL支持的栅格格式(如GeoTIFF、JPEG、PNG等)导入PostgreSQL数据库,支持批量加载、分块切片、创建空间索引及金字塔概览,是栅格数据入库的核心工具。 二、核心功能与典型用法 1…

    Redis企业级开发实战:核心应用场景与最佳实践

    引言 Redis&#xff08;Remote Dictionary Server&#xff09;作为一款高性能的内存数据库&#xff0c;在企业级开发中扮演着至关重要的角色。无论是缓存加速、分布式锁、实时统计&#xff0c;还是消息队列&#xff0c;Redis都能以极低的延迟和极高的吞吐量满足业务需求。本文…

    深入解析Spring Boot与Spring Cloud在微服务架构中的实践

    深入解析Spring Boot与Spring Cloud在微服务架构中的实践 引言 随着云计算和分布式系统的快速发展&#xff0c;微服务架构已成为现代软件开发的主流模式。Spring Boot和Spring Cloud作为Java生态中微服务开发的核心框架&#xff0c;为开发者提供了强大的工具和组件&#xff0…

    AI量化交易是什么?它是如何重塑金融世界的?

    第一章&#xff1a;证券交易的进化之路 1.1 从喊价到代码&#xff1a;交易方式的革命性转变 在电子交易普及之前&#xff0c;证券交易依赖于交易所内的公开喊价系统。交易员通过手势、喊话甚至身体语言传递买卖信息&#xff0c;这种模式虽然直观&#xff0c;但效率低下且容易…

    芯驰科技与安波福联合举办技术研讨会,深化智能汽车领域合作交流

    5月15日&#xff0c;芯驰科技与全球移动出行技术解决方案供应商安波福&#xff08;Aptiv&#xff09;在上海联合举办以“芯智融合&#xff0c;共赢未来”为主题的技术研讨会。会上&#xff0c;双方聚焦智能座舱与智能车控的发展趋势&#xff0c;展开深入交流与探讨&#xff0c;…

    大数据Spark(五十九):Standalone集群部署

    文章目录 Standalone集群部署 一、节点划分 二、搭建Standalone集群 1、将下载好的Spark安装包上传解压 2、配饰spark-env.sh 3、配置workers 4、将配置好的安装包发送到node2、node3节点上 5、启动Standalone集群 三、提交任务测试 Standalone集群部署 Standalone 模…

    Feign异步模式丢失上下文问题

    Feign异步模式丢失上下文问题 问题描述 当我们使用异步对我们代码进行操作优化时&#xff0c;代码中使用了RequestContextHolder去获取上下文的数据&#xff0c;当我们执行原来可以执行的业务时发现报了空指针异常或数据为空&#xff0c;这是为什么呢&#xff1f; 原理解释 …

    JavaScript作用域和作用域链

    在JavaScript中&#xff0c;作用域和作用域链是理解代码执行和变量访问的关键概念。它们决定了变量和函数在代码中的可见性和生命周期。 一、作用域&#xff08;Scope&#xff09; &#xff08;一&#xff09;什么是作用域&#xff1f; 作用域是在运行时代码中的某些特定部分…

    人工智能的“歧视”:“她数据”在算法运行中隐形

    纵观人类的发展史&#xff0c;每一次科技进步都将对性别平等产生深刻影响。尤其是当下&#xff0c;人们对于借助人工智能技术快速发展来弥合性别不平等寄予厚望。 但很多人没想过&#xff0c;人工智能技术本身是客观中立、不存在“算法歧视”“性别偏见的吗&#xff1f; 弗吉…

    设备全生命周期管理:从采购到报废的数字化闭环方案

    在当今数字化时代&#xff0c;企业对设备的管理已不再局限于简单的维护与修理&#xff0c;而是追求从采购到报废的全生命周期数字化闭环管理。易点易动设备管理系统&#xff0c;正是这一趋势下的佼佼者&#xff0c;它为企业提供了一套高效便捷的设备管理解决方案。 采购阶段&a…

    React中useState中更新是同步的还是异步的?

    文章目录 前言一、useState 的基本用法二、useState 的更新机制1. 内部状态管理2. 状态初始化3. 状态更新 三、useState 的更新频率与异步行为1. 异步更新与批量更新2. 为什么需要异步更新&#xff1f; 四、如何正确处理 useState 的更新1. 使用回调函数形式的更新2. 理解异步更…