DAY04_Spring—Aop案例引入代理机制

目录

  • 1 AOP
    • 1.1 AOP案例引入
      • 1.1.1 数据库事务说明
    • 1.2 Spring实现事务控制
      • 1.2.1 代码结构如下
      • 1.2.2 编辑User
      • 1.2.3 编辑UserMapper/UserMapperImpl
      • 1.2.4 编辑UserService/UserServiceImpl
      • 1.2.5 编辑配置类
      • 1.2.6 编辑测试类
    • 1.3 代码问题分析
    • 1.4 代理模式
      • 1.4.1 生活中代理案例
      • 1.4.2 代理模式
    • 1.5 静态代理
      • 1.5.1 通过代理模式实现事务控制
      • 1.5.2 修改目标对象名称
      • 1.5.3 编辑代理类
      • 1.5.4 编辑测试类
    • 1.5 静态代理弊端
    • 1.6 动态代理机制
      • 1.6.1 动态代理分类
      • 1.6.2 编辑JDK动态代理
      • 1.6.3 JDK动态代理执行过程
    • 1.7 动态代理优势
      • 1.7.1 编辑DeptService/DeptServiceImpl
      • 1.7.2 编辑测试类
    • 1.8 动态代理实现Demo2
      • 1.8.1 业务需求
      • 1.8.2 编辑UserService/UserServiceImpl
      • 1.8.3 编辑代理工厂
      • 1.8.4 编辑测试案例

1 AOP

1.1 AOP案例引入

1.1.1 数据库事务说明

  • 案例分析:
    • userMapper.insert(User对象)
    • deptMapper.insert(dept对象)
      • 由于业务需求 要求方法要么同时入库,要么同时回滚.所以必须通过事务进行控制.

1.2 Spring实现事务控制

1.2.1 代码结构如下

在这里插入图片描述

1.2.2 编辑User

public class User {private Integer id;private String name;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "User{" +"id=" + id +", name='" + name + '\'' +'}';}
}

1.2.3 编辑UserMapper/UserMapperImpl

  • 编辑UserMapper
import com.jt.pojo.User;public interface UserMapper {void addUser(User user);
}
  • 编辑UserMapperImpl
import com.jt.pojo.User;
import org.springframework.stereotype.Repository;@Repository
public class UserMapperImpl implements UserMapper {//??事务控制应该在哪一层完成!!dao/mapper service@Overridepublic void addUser(User user) {System.out.println("用户入库"+user);}
}

1.2.4 编辑UserService/UserServiceImpl

  • 编辑UserService
import com.jt.pojo.User;public interface UserService {void addUser(User user);
}
  • 编辑UserServiceImpl
import com.jt.mapper.UserMapper;
import com.jt.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class UserServiceImpl implements UserService{@Autowiredprivate UserMapper userMapper;//事务控制应该放在Service层中控制@Overridepublic void addUser(User user) {try {System.out.println("事务开始");userMapper.addUser(user);System.out.println("事务结束");} catch (Exception e) {e.printStackTrace();System.out.println("事务回滚");}}
}

1.2.5 编辑配置类

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;@Configuration//标识我是一个配置类
@ComponentScan("com.jt")
public class SpringConfig {
}

1.2.6 编辑测试类

import com.jt.config.SpringConfig;
import com.jt.pojo.User;
import com.jt.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class TestUser {//Controller-Service-Mapper(Dao)//Spring中规定://  如果传入的是接口的类型 则自动查找/注入 该接口的实现类//  该接口只有一个实现类@Testpublic void testTx(){ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);//写接口的类型/实现类的类型?UserService userService = context.getBean(UserService.class);
//        UserService userService = (UserService) context.getBean("userServiceImpl");User user = new User();user.setId(101);user.setName("SpringAop测试入门案例");userService.addUser(user);}
}

1.3 代码问题分析

  • Service层应该写代码业务,但是现在与事务控制紧紧的耦合在一起
  • 代码冗余不便于大批量开发

在这里插入图片描述

  • 解决方案:
    • 采用代理模式进行编辑.

1.4 代理模式

1.4.1 生活中代理案例

  • 房屋中介代理模式:
    • 房东: 自己手里有房子 需要出租换钱
    • 中介机构 1.本职工作 带客户看房/出租房屋 2.收取中介费(服务费)
    • 租客: 满足自身需求 租房子
  • 代码思维建模:
    • 暴露一个公共的接口(租房子)
    • 客户与中介机构进行沟通,中介看起来和房东功能一致.(代理看起来就是真实的对象)
    • 完成用户额外的操作(收取中介费)

1.4.2 代理模式

  • 组成部分
    • 要求代理者实现与被代理者相同的接口
    • 在代理方法中实现功能的扩展
    • 用户调用代理对象完成功能(用户认为代理就是目标对象)
  • 调用流程

在这里插入图片描述

1.5 静态代理

1.5.1 通过代理模式实现事务控制

  • 角色划分:
    • 目标对象target UserServiceImpl类
    • 目标方法 method addUser()方法
    • 代理: 实现事务控制.
    • 代理对象与目标对象实现相同的接口.

1.5.2 修改目标对象名称

在这里插入图片描述

1.5.3 编辑代理类

import com.jt.pojo.User;
import com.jt.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service("userService")
public class StaticProxy implements UserService {//要求引入目标对象@Autowired //ByType  byName//@Qualifier("target")private UserService target;//目的: 对原有方法进行扩展@Overridepublic void addUser(User user) {try {System.out.println("事务开始");target.addUser(user);System.out.println("事务结束");} catch (Exception e) {e.printStackTrace();System.out.println("事务回滚");}}
}

1.5.4 编辑测试类

@Test
public void testStaticProxy(){ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);UserService userService = (UserService) context.getBean("userService");User user = new User();user.setId(10001);user.setName("测试代理机制");//执行用户调用userService.addUser(user);
}

1.5 静态代理弊端

  • 静态代理只针对于某个接口 不能实现所有接口的代理 实用性较差

在这里插入图片描述

  • 静态代理中所有的方法,都需要手动的添加事务开始/事务提交代码 代码冗余 不够简洁

在这里插入图片描述

1.6 动态代理机制

1.6.1 动态代理分类

  • JDK代理:
    • 要求: 要求目标对象必须实现接口
    • 代理要求: 代理对象也必须实现目标对象的接口
    • 目标对象/代理关系: 目标对象与代理对象兄弟关系.
  • CGlib代理
    • 要求: 不管目标对象是否有接口,都可以为其创建代理对象
    • 代理要求: 要求代理对象必须继承目标对象
    • 目标对象/代理关系: 目标对象与代理对象是父子关系

在这里插入图片描述

1.6.2 编辑JDK动态代理

官网API:

在这里插入图片描述

  • 知识点:
    • 关于匿名内部类用法说明: 匿名内部类引用外部参数 要求参数必须final修饰
    • 该方法标识 当代理对象执行时,"回调"该方法.
       public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {}
    
    • 目标方法执行
    result = method.invoke(target,args);
    
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;//能否利用一个工厂动态为目标对象创建代理
public class JDKProxyFactory {//要求用户传递目标对象//关于匿名内部类用法说明:  匿名内部类引用外部参数 要求参数必须final修饰public static Object getProxy(final Object target) {//1.调用java API实现动态代理/***  参数分析: 3个参数*      1.ClassLoader loader, 类加载器(获取目标对象的Class)*      2.类<?>[] interfaces,  JDK代理要求 必须有接口*                             java中可以多实现*      3.InvocationHandler h  对目标方法进行扩展*///1.获取类加载器ClassLoader classLoader = target.getClass().getClassLoader();//2.获取接口数组Class[] interfaces = target.getClass().getInterfaces();//3.通过动态代理创建对象Object proxy = Proxy.newProxyInstance(classLoader, interfaces, new InvocationHandler() {//invoke方法: 代理对象调用方法时invoke执行,扩展方法的编辑位置@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//proxy: 代理对象本身//method: 用户调用的方法对象//args:   用户调用方法的参数// result 标识目标方法执行的返回值Object result = null;try {//添加事务的控制System.out.println("事务开始");//执行目标方法// target真实的目标对象,method方法对象,args方法参数result = method.invoke(target, args);System.out.println("事务提交");} catch (Exception e) {e.printStackTrace();System.out.println("事务回滚");}return result;}});return proxy;}
}
  • 测试代码
/*** 测试JDK动态代理*/@Testpublic void testJDKProxy(){ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);//1.获取用户目标对象UserService target = (UserService) context.getBean("target");//2.获取代理对象UserService userService = (UserService) JDKProxyFactory.getProxy(target);//3.打印代理对象的类型System.out.println(userService.getClass());//4.用户完成调用User user = new User();user.setId(10001);user.setName("JDK动态代理完成");//执行用户调用userService.addUser(user);}

在这里插入图片描述

1.6.3 JDK动态代理执行过程

在这里插入图片描述

1.7 动态代理优势

将公共的部分写到动态代理中,之后其他的业务类调用即可

1.7.1 编辑DeptService/DeptServiceImpl

  • 编辑DeptService
public interface DeptService {void addDept();
}
  • 编辑DeptServiceImpl
import org.springframework.stereotype.Service;@Service("deptService")
public class DeptServiceImpl implements DeptService {@Overridepublic void addDept() {//添加事务System.out.println("调用DeptMapper实现入库操作");//提交事务}
}

1.7.2 编辑测试类

@Testpublic void testTx() {//1.获取目标对象ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);DeptService target = (DeptService) context.getBean("deptService");//2.获取代理对象DeptService deptService = (DeptService) JDKProxyFactory.getProxy(target);//通过代理对象 调用方法  扩展了方法!!!!!deptService.addDept();  //invoke}

在这里插入图片描述

1.8 动态代理实现Demo2

1.8.1 业务需求

  • 要求:
    • 对Service层的方法记录其执行的时间
    • service中 有 addUser方法/deleteUser方法.
    • 要求代码结构扩展性好,耦合性低.

1.8.2 编辑UserService/UserServiceImpl

  • 编辑UserService
public interface UserService {void addUser();void deleteUser();
}
  • 编辑UserServiceImpl
@Service("target")
public class UserServiceImpl implements UserService{@Overridepublic void addUser() {System.out.println("新增用户");}@Overridepublic void deleteUser() {System.out.println("删除用户");}
}

1.8.3 编辑代理工厂

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;public class JDKProxyFactory {//编辑静态方法获取代理对象public static Object getProxy(final Object target) {//3个参数  1.类加载器  2.对象的接口ClassLoader classLoader = target.getClass().getClassLoader();Class[] interfaces = target.getClass().getInterfaces();Object proxy = Proxy.newProxyInstance(classLoader, interfaces, new InvocationHandler() {//代理对象执行目标方法时执行@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//让用户执行目标方法Long startTime = System.currentTimeMillis(); //开始时间//执行目标方法 获取返回值 可能为nullObject result = method.invoke(target);Long endTime = System.currentTimeMillis();  //结束时间System.out.println("程序执行:" + (endTime - startTime) + "毫秒");//将返回值传递给调用者return result;}});return proxy;}
}

1.8.4 编辑测试案例

@Testpublic void test01(){ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);//1.获取目标对象UserService target = (UserService) context.getBean("target");//2.获取代理对象UserService proxy = (UserService) JDKProxyFactory.getProxy(target);System.out.println(proxy.getClass());//3.调用业务方法proxy.addUser();proxy.deleteUser();}

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

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

相关文章

vue3 实现简单计数器示例——一个html文件展示vue3的效果

目的&#xff1a;作为一个新手开发&#xff0c;我想使用 Vue 3 将代码封装在 HTML 文件中时&#xff0c;进行界面打开展示。 一、vue计数示例 学了一个简单计数器界面展示&#xff0c;代码如下&#xff1a; <!DOCTYPE html> <html lang"en"><head&…

R语言【paleobioDB】——pbdb_temporal_resolution():展示化石数据的时空分辨率

Package paleobioDB version 0.7.0 paleobioDB 包在2020年已经停止更新&#xff0c;该包依赖PBDB v1 API。 可以选择在Index of /src/contrib/Archive/paleobioDB (r-project.org)下载安装包后&#xff0c;执行本地安装。 Usage pbdb_temporal_resolution (data, do.plotTRUE…

uniapp + node.js 开发问卷调查小程序

前后端效果图 后端&#xff1a;nodejs 12.8 ; mongoDB 4.0 前端&#xff1a;uniapp 开发工具&#xff1a;HBuilderX 3.99 前端首页代码 index.vue <!-- 源码下载地址 https://pan.baidu.com/s/1AVB71AjEX06wpc4wbcV_tQ?pwdl9zp --><template><view class&q…

十二、Qt 操作PDF文件(2)

一、在《十、Qt 操作PDF文件-CSDN博客》中我们用Poppler类库打开了PDF文件&#xff0c;并显示到窗体上&#xff0c;但只能显示一页&#xff0c;功能还没完善&#xff0c;在本章节中&#xff0c;加入了&#xff1a; 通过选择框选择PDF文件并打开&#xff0c;默认打开第一页。通…

Spring Boot 配置文件和日志

目录 配置文件格式 properties配置文件说明 1.properties基本语法 2.读取配置文件 3.properties缺点 yml配置文件说明 1.yml基本语法 2.配置不同数据类型 3.字符串特殊情况 4.配置对象 properties和yml对比 日志 日志的使用 日志级别 日志持久化 Lombok Lombo…

C++大学教程(第九版)5.18进制表

目录 题目 代码 运行截图 题目 &#xff08;进制表&#xff09;编写一个程序要求打印一张表&#xff0c;内容是1~256范围内每个十进制数对应的二进制、八进制和十六进制形式。如果还不熟悉这些计数系统&#xff0c;可先阅读附录 D。提示:可以使用流操纵符dec、oct 和 hex来…

网络部署实战具体学习内容总结

网络部署实战具体学习内容总结 &#x1f4bb;网络部署实战课程通常旨在教授学生如何规划、配置、维护和优化计算机网络。这些课程涵盖了广泛的主题&#xff0c;以确保学生具备网络部署和管理所需的技能。 网络部署实战课程具体学习内容&#x1f447; 1️⃣网络架构设计及网络原…

ARM 1.12

norflash与nandflash的区别&#xff1a; 一、NAND flash和NOR flash的性能比较 1、NOR的读速度比NAND稍快一些。 2、NAND的写入速度比NOR快很多。 3、NAND的4ms擦除速度远比NOR的5s快。 4、大多数写入操作需要先进行擦除操作。 5、NAND的擦除单元更小&#xff0c;相应的擦除电…

yolo9000:Better, Faster, Stronger的目标检测网络

目录 一、回顾yolov1二、yolov2详细讲解2.1 Better部分创新点&#xff08;1&#xff09;Batch Normalization(批量归一化)&#xff08;2&#xff09;High Resolution Classifier---高分辨率分类器&#xff08;3&#xff09;Anchor Boxes---锚框&#xff08;4&#xff09;Dimens…

4D毫米波雷达——原理、对比、优势、行业现状

前言 4D 毫米波雷达是传统毫米波雷达的升级版&#xff0c;4D指的是速度、距离、水平角度、垂直高度四个维度。 相比传统 3D 毫米波雷达&#xff0c;4D 毫米波雷达增加了“高度”的探测&#xff0c;将第四个维度整合到传统毫米波雷达中。 4D毫米波雷达被视为未来车载雷达的一…

Elasticsearch:和 LIamaIndex 的集成

LlamaIndex 是一个数据框架&#xff0c;供 LLM 应用程序摄取、构建和访问私有或特定领域的数据。 LlamaIndex 是开源的&#xff0c;可用于构建各种应用程序。 在 GitHub 上查看该项目。 安装 在 Docker 上设置 Elasticsearch 使用以下 docker 命令启动单节点 Elasticsearch 实…

【Go面试向】rune和byte类型的认识与使用

【Go】rune和byte类型的认识与使用 大家好 我是寸铁&#x1f44a; 总结了一篇rune和byte类型的认识与使用的文章✨ 喜欢的小伙伴可以点点关注 &#x1f49d; byte和rune类型定义 byte,占用1个字节&#xff0c;共8个比特位&#xff0c;所以它实际上和uint8没什么本质区别,它表示…

基于Docker的Nginx的安装与配置

基于Docker的Nginx的安装与配置 1 为Nginx创建一个容器1.1 学习docker run1.2 通过docker run为Nginx创建并启动一个容器 2 配置Nginx2.1 学习docker的bind mount技术2.2 在Nginx容器中找到想修改的文件所在的目录2.2.1 认识nginx.conf文件2.2.2 访问Nginx服务&#xff0c;默认…

【陈老板赠书活动 - 22期】- 人工智能(第三版)

陈老老老板&#x1f9d9;‍♂️ &#x1f46e;‍♂️本文专栏&#xff1a;赠书活动专栏&#xff08;为大家争取的福利&#xff0c;免费送书&#xff09; &#x1f934;本文简述&#xff1a;活就像海洋,只有意志坚强的人,才能到达彼岸。 &#x1f473;‍♂️上一篇文章&#xff…

学习JavaEE的日子 day13 封装 static private this 类加载机制

Day13 1. private – 私有化 理解&#xff1a;private是访问修饰符的一种&#xff0c;访问修饰符规定了访问权限. 作用&#xff1a; ​ 1.private修饰属性&#xff1a;该属性只能在类的内部使用 ​ 2.private修饰方法&#xff1a;该方法只能在类的内部使用 应用场景&#xff1…

【Flutter 问题系列第 80 篇】TextField 输入框组件限制可输入的最大长度后,输入的内容中包含表情符号时,获取输入的内容数还是会超出限制的问题

这是【Flutter 问题系列第 80 篇】&#xff0c;如果觉得有用的话&#xff0c;欢迎关注专栏。 博文当前所用 Flutter SDK&#xff1a;3.10.5、Dart SDK&#xff1a;3.0.5 一&#xff1a;问题描述 在输入用户名称、简介等内容时&#xff0c;一般我们都会限制输入框内最大可输入…

011:vue结合css动画animation实现下雪效果

文章目录 1. 实现效果2. 编写一个下雪效果组件 VabSnow.vue3. 页面使用4. 注意点 1. 实现效果 GIF录屏文件太卡有点卡&#xff0c;实际是很丝滑的 2. 编写一个下雪效果组件 VabSnow.vue 在 src 下新建 components 文件&#xff0c;创建VabSnow.vue组件文件 <template>…

系分备考计算机网络传输介质、通信方式和交换方式

文章目录 1、概述2、传输介质3、网络通信4、网络交换5、总结 1、概述 计算机网路是系统分析师考试的常考知识点&#xff0c;本篇主要记录了知识点&#xff1a;网络传输介质、网络通信和数据交换方式等。 2、传输介质 网络的传输最常见的就是网线&#xff0c;也就是双绞线&…

k8s---ingress对外服务(ingress-controller)

ingress 概念 k8s的对外服务&#xff0c;ingress service作用现在两个方面&#xff1a; 1、集群内部&#xff1a;不断跟踪的变化&#xff0c;更新endpoint中的pod对象&#xff0c;基于pod的ip地址不断变化的一种服务发现机制。 2、集群外部&#xff1a;类似于负载均衡器&a…

球幕影院气膜:未来娱乐的奇妙之旅

球幕影院气膜&#xff1a;未来娱乐的奇妙之旅 在科技日新月异的时代&#xff0c;娱乐体验的创新与演变从未停歇。气膜球幕影院&#xff0c;作为一项领航未来的前沿科技&#xff0c;正以其沉浸感和颠覆性的观影体验&#xff0c;吸引着人们驻足体验。 创新科技的巅峰之作 气膜球幕…