java代理模式之JDK动态代理

目录

什么是动态代理?

动态代理的两种方式?

jdk动态代理;

cglib静态代理

为什么需要代理?

1、原有功能增强

2、降低耦合

JDK动态代理代码实例:

实体类:

持久层接口+实现类(使用jdbc进行数据库操作)

业务层接口+实现类(调用持久层,仅书写业务逻辑,不进行其他操作,如添加事物处理等)

代理类:代理的是AccountService接口 获取业务层接口的代理对象,增强后返回

工具类:提供一些工具方法,如建立连接池,创建数据库,进行事物操作的方法等

测试类:直接调用代理类进行操作


什么是动态代理?

动态代理就是,在程序运行期,创建目标对象的代理对象,并对目标对象中的方法进行功能性增强的一种技术。在生成代理对象的过程中,目标对象不变,代理对象中的方法是目标对象方法的增强方法。

可以通过调用代理对象来实现对目标对象的调用。

动态代理的两种方式?

  • jdk动态代理;

  • cglib静态代理

为什么需要代理?

1、原有功能增强

举例来说,当前类的代码只能满足一些基本的功能,而这些功能满足不了新需求,但又不能改动以前的代码,这时就用代理模式。通过代理类,扩展原有类的功能,客户端访问的入口只是从目标对象切换到代理对象而已;

2、降低耦合

使用代理类,可以在不对原来类修改的基础上,进行相关功能的扩展

JDK动态代理代码实例:

实体类:

/*** 实体类* 账户表的实体类* 序列化* 反序列化*/
public class Account implements Serializable{//idprivate Integer id;//名称private String name;//钱 金额private Double money;public Account() {}public Account(Integer id, String name, Double money) {this.id = id;this.name = name;this.money = money;}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;}public Double getMoney() {return money;}public void setMoney(Double money) {this.money = money;}@Overridepublic String toString() {return "Account{" +"id=" + id +", name='" + name + '\'' +", money=" + money +'}';}
}

持久层接口+实现类(使用jdbc进行数据库操作)

/*** 持久层接口* 面向接口开发*/
public interface AccountDao {//保存账户public void saveAll(Account account) throws SQLException;
}
/*** 持久层接口实现类* 面向接口开发*/
public class AccountDaoImpl implements AccountDao{//    @Overridepublic void saveAll(Account account) throws SQLException {//jdbc//使用工具类  减少加载驱动 直接获取连接System.out.println("持久层:保存账户...");// 把数据存储到数据库中// 先获取到连接Connection connection = TxUtils.getConnection();//编写sql// 编写sql语句String sql = "insert into account values (null,?,?)";//获取执行对象stmt  prepareStatement(sql注入)  Statement(不可以防止)PreparedStatement statement = connection.prepareStatement(sql);// 设置值statement.setString(1,account.getName());statement.setDouble(2,account.getMoney());//执行sqlint i = statement.executeUpdate();//关闭资源statement.close();}
}

业务层接口+实现类(调用持久层,仅书写业务逻辑,不进行其他操作,如添加事物处理等)

/*** 账户的接口*/
public interface AccountService {//保存账户public void saveAll(Account account1,Account account2) throws SQLException;
}
/*** 账户业务层实现类* 目的:实现新增账户* 演示事务*/
public class AccountServiceImpl implements  AccountService{private AccountDao accountDao;public void setAccountDao(AccountDao accountDao) {this.accountDao = accountDao;}/*** 实现保存* @param account1* @param account2* @throws SQLException*/
//    @Overridepublic void saveAll(Account account1, Account account2) throws SQLException {accountDao.saveAll(account1);int i=5/0;accountDao.saveAll(account2);}
}

代理类:代理的是AccountService接口 获取业务层接口的代理对象,增强后返回

因为jdk动态代理是面向接口的

/*** 代理类* 使用动态代理JDK   面向接口* 传入目标对象,生成该对象的代理对象,返回。对目标对象的方法进行增强* Proxy java 反射*/
public class JdkProxy {/*** 获取代理对象并返回,增强目标对象的方法* @param accountService* @return*/public static Object getProxy(final AccountService accountService){//通过java反射包里提供的Proxy的类的api方法newProxyInstance,按要求(根据三个参数)返回一个代理对象proxyObject proxy=Proxy.newProxyInstance(JdkProxy.class.getClassLoader(), accountService.getClass().getInterfaces(), new InvocationHandler() {/*** 调用代理对象AccountServiceImpl的方法,invoke方法就会去执行*/
//            @Overridepublic 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;}
}

工具类:提供一些工具方法,如建立连接池,创建数据库,进行事物操作的方法等

*** 事务的工具类  数据库连接的工具类*/
public class TxUtils {//类属性 连接池对象private static DruidDataSource ds = null;// 使用ThreadLocal存储当前线程中的Connection对象private static ThreadLocal<Connection> threadLocal = new ThreadLocal<Connection>();// 在静态代码块中创建数据库连接池static {try {// 通过代码创建druid数据库连接池ds = new DruidDataSource();ds.setDriverClassName("com.mysql.jdbc.Driver");ds.setUrl("jdbc:mysql:///spring_db?useUnicode=true&characterEncoding=utf8");ds.setUsername("root");ds.setPassword("root");} catch (Exception e) {throw new ExceptionInInitializerError(e);}}/*** @Method: getConnection* @Description: 从数据源中获取数据库连接* @Anthor:* @return Connection* @throws SQLException*/public static Connection getConnection() throws SQLException {// 从当前线程中获取ConnectionConnection conn = threadLocal.get();if (conn == null) {// 从数据源中获取数据库连接conn = getDataSource().getConnection();// 将conn绑定到当前线程threadLocal.set(conn);}return conn;}/*** @Method: startTransaction* @Description: 开启事务* @Anthor:**/public static void startTransaction() {try {Connection conn = threadLocal.get();if (conn == null) {conn = getConnection();// 把 conn绑定到当前线程上threadLocal.set(conn);}// 开启事务conn.setAutoCommit(false);} catch (Exception e) {throw new RuntimeException(e);}}/*** @Method: rollback* @Description:回滚事务* @Anthor:*/public static void rollback() {try {// 从当前线程中获取ConnectionConnection conn = threadLocal.get();if (conn != null) {// 回滚事务conn.rollback();}} catch (Exception e) {throw new RuntimeException(e);}}/*** @Method: commit* @Description:提交事务* @Anthor:*/public static void commit() {try {// 从当前线程中获取ConnectionConnection conn = threadLocal.get();if (conn != null) {// 提交事务conn.commit();}} catch (Exception e) {throw new RuntimeException(e);}}/*** @Method: close* @Description:关闭数据库连接(注意,并不是真的关闭,而是把连接还给数据库连接池)* @Anthor:**/public static void close() {try {// 从当前线程中获取ConnectionConnection conn = threadLocal.get();if (conn != null) {conn.close();// 解除当前线程上绑定connthreadLocal.remove();}} catch (Exception e) {throw new RuntimeException(e);}}/*** @Method: getDataSource* @Description: 获取数据源* @Anthor:* @return DataSource*/public static DataSource getDataSource() {// 从数据源中获取数据库连接return ds;}}

测试类:直接调用代理类进行操作

public class TestDemo {@Testpublic void run() throws SQLException {ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");AccountService service = (AccountService) ac.getBean("service");AccountService proxy = (AccountService) JdkProxy.getProxy(service);Account account1=new Account();account1.setName("张三0716");account1.setMoney(5000.00);Account account2=new Account();account2.setName("李四0716");account2.setMoney(9000.00);proxy.saveAll(account1,account2);}
}

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

【2024】VsCode + Latex + Linux(Ubuntu) + wsl环境下配置教程 | 包含 中文配置,和 格式化处理

前言 本篇教程是针对WSL下的Ubuntu操作系统的配置教程&#xff0c;它和一般的Linux环境下的配置有所不同&#xff0c;并且和Windows环境下的也有所不同。 本篇博客编写参考了 官方文档&#xff08;Tex&#xff09; 和 插件官方&#xff08;Texlive Workshop&#xff09; 文档…

动手学RAG:Part1 什么是RAG?

1、大模型的幻觉问题、时效性问题、数据安全问题 2、大模型的结构和参数数量导致对其修改、微调和重新训练变得很困难 3、基于知识的问答&#xff0c;依赖于信息抽取

Logback日志异步打印接入指南,输出自定义业务数据

背景 随着应用的请求量上升&#xff0c;日志输出量也会成线性比例的上升&#xff0c;给磁盘IO带来压力与性能瓶颈。应用也遇到了线程池满&#xff0c;是因为大量线程卡在输出日志。为了缓解日志同步打印&#xff0c;会采取异步打印日志。这样会引起日志中的追踪id丢失&#xf…

2024 HNCTF PWN(close ezpwn idea what beauty)

文章目录 closeezpwn代码利用exp idea代码exp whatexp beauty libc 2.35IDA中文乱码解决代码思路exp close int __fastcall main(int argc, const char **argv, const char **envp) {puts("**********************************");puts("* Welcome to the H…

kubernetes k8s Deployment 控制器配置管理 k8s 红蓝部署 金丝雀发布

目录 1、Deployment控制器&#xff1a;概念、原理解读 1.1 Deployment概述 1.2 Deployment工作原理&#xff1a;如何管理rs和Pod&#xff1f; 2、Deployment资源清单文件编写技巧 3、Deployment使用案例&#xff1a;创建一个web站点 4、Deployment管理pod&#xff1a;扩…

数字化装备场革新:智能装备采集设备问世!

数字化装备场建设是一项跨学科的综合工程&#xff0c;它不仅涵盖了网络布线的整合、系统框架的构建&#xff0c;还包含了各类硬件设备的配置等丰富多样的内容。该工程的关键环节主要包括对装备场所的出入口进行现代化升级、完善车库车辆定位与管理体系&#xff0c;以及部署一体…

Maven学习——Maven的下载、安装与配置(详细攻略!)

目录 前言 1.下载与安装 2.配置Maven的环境变量 3.配置Maven的本地仓库 4. 配置Maven的镜像远程仓库 前言 我在之前写了一篇博客&#xff0c;是介绍Maven的基本概念和下载安装&#xff0c;但是由于篇幅过长&#xff0c;Maven的下载与安装写的并不详细&#x1f436;&#x…

kaggle 量化交易 比赛

作者: Raoul Malm 描述: 本笔记本演示了如何使用 TensorFlow 中的循环神经网络预测不同股票的未来价格。实现了带有基本单元、LSTM 或 GRU 单元的循环神经网络。 大纲: [库和设置][分析数据][操作数据][建模和验证数据][预测]参考: https://www.kaggle.com/benjibb/lstm-st…

图片压缩python

linux粘贴文本格式错乱&#xff1a; vi/vim :set paste然后再 insert &#xff0c;粘贴 centos安装pillow图像处理库&#xff1a; 引用&#xff1a;https://blog.csdn.net/newbieLCQ/article/details/125345335 linux赋予执行权限&#xff1a; # 创建文件 touch comperss.p…

C++解决:书本信息储存

书本信息储存 暂无标签 时间限制&#xff1a;C/C 1000MS&#xff0c;其他语言 2000MS 内存限制&#xff1a;C/C 256MB&#xff0c;其他语言 512MB 难度&#xff1a;简单 描述 创建一个储存书本信息的结构体&#xff0c;包括书号&#xff0c;名称&#xff0c;作者&#xff0…

日本IT-SE职位一览与未来职业发展路径规划

日本IT-SE 工作内容特点&#xff1a; 1. 软件开发&#xff1a;SE的主要任务是编写、测试和维护&#xff0c;以满足客户需求。他们需要使用多种编程语言和开发工具来完成任务。 2. 需求分析&#xff1a;SE负责与客户沟通&#xff0c;理解他们的需求&#xff0c;并将其转化为可…

给你的博客添加数据统计功能

20.数据统计 我们可以给博客添加统计功能&#xff0c;这里以百度统计和谷歌统计为例。 ‍ 百度统计 ‍ 添加网站 登陆百度统计后台&#xff1a;百度统计——一站式智能数据分析与应用平台&#xff0c;并登录&#xff0c;然后进入产品&#xff1a; ‍ 在使用设置–网站列…

Windows命令行(CMD)中,tasklist | findstr(搜索并显示包含特定字符串的进程信息)

文章目录 示例注意事项示例&#xff1a;使用 /FI 选项过滤进程 在Windows命令行&#xff08;CMD&#xff09;中&#xff0c; tasklist 命令用于显示当前运行的进程列表&#xff0c;而 findstr 命令则用于搜索字符串。当你将 tasklist 命令的输出通过管道&#xff08; |&…

单片机设计_自行车码表(AT89C51, LCD1602, DS1302,霍尔传感器)

想要更多项目私wo!!! 一、电路设计 系统采用51单片机LCD1602液晶DS1302时钟模块霍尔传感器电机按键模块蜂鸣器报警模块设计而成。 产品自带单片机上电复位电路、手动复位电路&#xff08;复位按键&#xff09;、晶振电路&#xff08;给单片机提供时钟周期&#xff09;。 …

OpenCV下的无标定校正(stereoRectifyUncalibrated)

OpenCV下的无标定校正(stereoRectifyUncalibrated) 文章目录 1. 杂话2. 无标定校正2.1 先看代码2.2 一点解释2.3 findFundamentalMat参数2.4 stereoRectifyUncalibrated参数 3. 矫正结果 1. 杂话 咱们在之前的帖子里面讲了一些比较常规的标定和校正OpenCV下的单目标定&#xff…

紫外测熔融实验结果温度和abs作折线图和求一阶导最大值

import numpy as np import pandas as pd from pyecharts.charts import Line from pyecharts import options as opts from matplotlib import pyplot as plt import xlrd # 读取 csv 文件 data pd.read_excel(F:/LJX/lc8.xls)# 假设 csv 文件中有两列数据&#xff1a;x 和 y…

iOS——编译链接

编译连接的过程 预处理编译汇编链接 预处理 clang -E main.m -o main.i“#define"删除并展开对应宏定义。处理所有的条件预编译指令。如#if/#ifdef/#else/#endif。”#include/#import"包含的文件递归插入到此处。删除所有的注释"//或/**/"。添加行号和文…

SpringCloud网关的实现原理与使用指南

Spring Cloud网关是一个基于Spring Cloud的微服务网关&#xff0c;它是一个独立的项目&#xff0c;可以对外提供API接口服务&#xff0c;负责请求的转发和路由。本文将介绍Spring Cloud网关的实现原理和使用指南。 一、Spring Cloud网关的实现原理 Spring Cloud网关基于Spring…

在 Windows 上开发.NET MAUI 应用_2.生成你的第一个应用

先决条件 Visual Studio 2022 17.8 或更高版本&#xff0c;并安装了 .NET Multi-platform App UI 工作负载。 可参考上一篇文章&#xff1a;http://t.csdnimg.cn/n38Yy 创建应用 1.启动 Visual Studio 2022。 在开始窗口中&#xff0c;单击“创建新项目”以创建新项目&#…

时间管理计划表怎么做 待办计划时间管理工具

每当夜深人静&#xff0c;我总会坐在书桌前&#xff0c;思考着如何更好地规划明天的时间。那一张张密密麻麻的时间管理计划表&#xff0c;就像是我生活的地图&#xff0c;指引着我前行。我知道&#xff0c;对于每一个在都市丛林中奔波的打工人来说&#xff0c;时间都是最宝贵的…