03、Spring中的静态代理JDK动态代理CGLB动态代理

news2025/7/30 9:54:42

本文章主要讲解以下几个点:
1、代理模式
2、静态代理
3、JDK的动态代理
4、CGLB动态代理

1、代理模式

1、定义

给某一个对象提供一个代理,并由代理对象控制对原对象的引用。

2、通俗解释

比如:一个人(客户端)需要去租房子,但是找不到房子,就会去找中介(代理对象)租房子,真实的房子主人(真实对象)并不会被客户端知晓。所有的租房子操作都是由中介代理办理。

3、好处

  • 代理模式能够协调调用者和被调用者,在一定程度上降低代码之间的耦合度。
  • 实现了职责分离

2、静态代理

1、定义

在程序运行之前就已经存在代理类的字节码文件,代理对象和真实对象的关系在程序运行之前就确定了。(代理对象需要我们自己去手动创建)

2、类图

在这里插入图片描述

3、 代码演示

1、 新建一个Maven项目导入如下依赖

<dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.0.8.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.0.8.RELEASE</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>

2、提供一个接口

package cn.simplelife._01staticProxy;

/**
 * @ClassName IEmployeeService
 * @Description
 * @Author simplelife
 * @Date 2022/11/22 19:14
 * @Version 1.0
 */

public interface IEmployeeService {
    void save(String name, String password);
}

3、创建实现类实现接口

package cn.simplelife._01staticProxy.impl;

import cn.simplelife._01staticProxy.IEmployeeService;

/**
 * @ClassName IEmployeeServiceImpl
 * @Description
 * @Author simplelife
 * @Date 2022/11/22 19:15
 * @Version 1.0
 */

public class IEmployeeServiceImpl implements IEmployeeService {

    @Override
    public void save(String name, String password) {
        System.out.println("保存" + name);
    }
}

4、创建代理类实现接口

package cn.simplelife._01staticProxy.proxy;

import cn.simplelife._01staticProxy.IEmployeeService;
import cn.simplelife._01staticProxy.tx.MyTransaction;
import org.springframework.stereotype.Component;

/**
 * @ClassName IEmployeeProxy
 * @Description
 * @Author simplelife
 * @Date 2022/11/22 19:24
 * @Version 1.0
 */
@Component
public class IEmployeeProxy implements IEmployeeService {
    private MyTransaction myTransaction; // 事务管理对象
    private IEmployeeService target; // 代理类中的真实类对象

	// 因为使用的是XML配置方式,所以这里必须提供Set方法
    public void setMyTransaction(MyTransaction myTransaction) {
        this.myTransaction = myTransaction;
    }

    public void setTarget(IEmployeeService target) {
        this.target = target;
    }

    @Override
    public void save(String name, String password) {
        try {
            myTransaction.begin();
            // 真实类对象调用真实类的方法保存信息
            target.save(name, password);
            myTransaction.commit();
        } catch (Exception e) {
            myTransaction.rollback();
            e.printStackTrace();
        }
    }
}

5、使用Spring帮我们创建对象

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--创建代理类对象-->
    <bean id="iEmployeeProxy" class="cn.simplelife._01staticProxy.proxy.IEmployeeProxy">
        <!--真实类对象-->
        <property name="target">
            <!--这种配置方式会隐藏真实类,客户端不会拿到真实类对象-->
            <bean class="cn.simplelife._01staticProxy.impl.IEmployeeServiceImpl"/>
        </property>
        <!--事务管理器-->
        <property name="myTransaction" ref="myTransaction"/>
    </bean>
    <!--创建事务管理器对象-->
    <bean id="myTransaction" class="cn.simplelife._01staticProxy.tx.MyTransaction"/>
</beans>

6、编写测试类进行测试

package cn.simplelife._01staticProxy.proxy;

import cn.simplelife._01staticProxy.IEmployeeService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
 * @ClassName IEmployeeProxyTest
 * @Description
 * @Author simplelife
 * @Date 2022/11/22 19:29
 * @Version 1.0
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class IEmployeeProxyTest {

    @Autowired
    private IEmployeeService iEmployeeService;

    @Test
    public void save() {
        System.out.println(iEmployeeService);
        iEmployeeService.save("张胜男","12315");
    }
}

7、测试结果

在这里插入图片描述

3、JDK动态代理

1、相关API简介

1、java.lang.reflect.Proxy

  • Java 动态代理机制生成的所有动态代理类的父类,它提供了一组静态方法来为一组接口动态地生成代理类及其对象。

  • 主要方法

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler hanlder)
  • 方法职责:为指定类加载器、一组接口及调用处理器生成动态代理类实例。

  • 参数:

    • loader:类加载器,一般传递真实对象的类加载器
    • interfaces:代理类所需要实现的接口
    • hanlder:代理执行处理器,代理对象需要做的事情。
  • 返回值:创建的代理对象。

2、java.lang.reflect.InvocationHandler

  • 主要方法
public Object invoke(Object proxy, Method method, Object[] args)
  • 方法职责:负责集中处理动态代理类上的所有方法调用,让使用者自定义做什么事情,对原来方法增强。

  • 参数:

    • proxy :生成的代理对象;
    • method:当前调用的真实方法对象;
    • args :当前调用方法的实参。
  • 返回值:真实方法的返回结果。

2、优缺点

1、优点

  • 对比静态代理,我们不需要手动创建代理类。

2、缺点

  • 真实类必须实现接口。
  • 对多个真实对象进行代理的话,若使用 Spring 的话配置太多了,要手动创建代理对象,用起来麻烦。

3、代码演示

1、 新建一个Maven项目导入如下依赖

<dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.0.8.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.0.8.RELEASE</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>

2、提供一个接口

package cn.simplelife._01staticProxy;

/**
 * @ClassName IEmployeeService
 * @Description
 * @Author simplelife
 * @Date 2022/11/22 19:14
 * @Version 1.0
 */

public interface IEmployeeService {
    void save(String name, String password);
}

3、创建实现类实现接口

package cn.simplelife._01staticProxy.impl;

import cn.simplelife._01staticProxy.IEmployeeService;

/**
 * @ClassName IEmployeeServiceImpl
 * @Description
 * @Author simplelife
 * @Date 2022/11/22 19:15
 * @Version 1.0
 */

public class IEmployeeServiceImpl implements IEmployeeService {

    @Override
    public void save(String name, String password) {
        System.out.println("保存" + name);
    }
}

4、编写代理执行处理器类

package cn.simplelife.jdkproxy.handler;

import cn.simplelife.jdkproxy.tx.MyTransactionManger;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @ClassName IEmployeeServiceProxy
 * @Description
 * @Author simplelife
 * @Date 2022/11/22 19:55
 * @Version 1.0
 */

public class TransactionInvocationHandler implements InvocationHandler {
    private MyTransactionManger myTransactionManger; // 事务管理器
    private Object target; // 真实对象

    public void setMyTransactionManger(MyTransactionManger myTransactionManger) {
        this.myTransactionManger = myTransactionManger;
    }

    public void setTarget(Object target) {
        this.target = target;
    }

    public Object getTarget() {
        return target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object invoke = null;
        try {
            myTransactionManger.begin();
            // 真实对象调用方法
            invoke = method.invoke(target, args);
            myTransactionManger.commit();
        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
            myTransactionManger.rock();
            e.printStackTrace();
        }
        return invoke;
    }
}

5、使用Spring帮我们创建对象

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="employeeServiceProxy" class="cn.simplelife.jdkproxy.handler.TransactionInvocationHandler">
        <property name="target">
            <bean class="cn.simplelife.jdkproxy.impl.IEmployeeServiceImpl"/>
        </property>
        <property name="myTransactionManger" ref="myTransactionManger"/>
    </bean>
    <bean id="myTransactionManger" class="cn.simplelife.jdkproxy.tx.MyTransactionManger"/>
</beans>

6、编写测试类进行测试

package cn.simplelife.jdkproxy.handler;

import cn.simplelife.jdkproxy.IEmployeeService;
import cn.simplelife.jdkproxy.impl.IEmployeeServiceImpl;
import cn.simplelife.jdkproxy.tx.MyTransactionManger;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.lang.reflect.Proxy;

/**
 * @ClassName IEmployeeServiceProxyTest
 * @Description
 * @Author simplelife
 * @Date 2022/11/22 19:58
 * @Version 1.0
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class IEmployeeServiceProxyTest {

    @Autowired
    private TransactionInvocationHandler invocationHandler;

    @Test
    public void testJDKProxy() {
        invocationHandler.setMyTransactionManger(new MyTransactionManger());
        invocationHandler.setTarget(new IEmployeeServiceImpl());
        IEmployeeService proxyInstance = (IEmployeeService) Proxy.newProxyInstance(
                this.getClass().getClassLoader(),
                invocationHandler.getTarget().getClass().getInterfaces(),
                invocationHandler
        );
        proxyInstance.save("李四", "11345");
    }
}

7、测试结果

在这里插入图片描述

8、底层分析图解

在这里插入图片描述

9、调用流程

在这里插入图片描述

4、CGLB动态代理

1、相关API简介

1、org.springframework.cglib.proxy.Enhancer

类似 JDK 中 Proxy,用来生成代理类创建代理对象的。

2、org.springframework.cglib.proxy.InvocationHandler

类似 JDK 中 InvocationHandler,让使用者自定义做什么事情,对原来方法增强。

2、代码演示

1、修改代理执行处理器类

  • 修改其实现接口为 org.springframework.cglib.proxy.InvocationHandler,其他不变。

2、修改单元测试类

package cn.simplelife.cjlbproxy.impl;

import cn.simplelife.cjlbproxy.IEmployeeService;
import cn.simplelife.cjlbproxy.handler.TransactionInvokeHandler;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

/**
 * @ClassName IEmployeeServiceImplTest
 * @Description
 * @Author simplelife
 * @Date 2022/11/22 15:38
 * @Version 1.0
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class IEmployeeServiceImplTest {

    @Autowired
    private TransactionInvokeHandler transactionInvokeHandler;

    @Test
    public void save() {
        Enhancer enhancer = new Enhancer();
        // 生产的代理类是继承真实类的
        enhancer.setSuperclass(transactionInvokeHandler.getTarget().getClass());
        // 生成的代理类对象要做的事情
        enhancer.setCallback(transactionInvokeHandler);
        // 接收生成的代理类
        IEmployeeService iEmployeeService = (IEmployeeService) enhancer.create();

        iEmployeeService.save("yyy", "123");
    }
}

3、测试结果

在这里插入图片描述

4、调用流程

在这里插入图片描述

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

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

相关文章

深度学习 Day 20——优化器对比实验

深度学习 Day 20——优化器对比实验 文章目录深度学习 Day 20——优化器对比实验一、前言二、我的环境三、前期工作1、设置GPU2、导入数据3、配置数据集4、数据可视化三、构建模型四、训练模型五、模型评估1、Accuracy与Loss图2、评估模型六、最后我想说一、前言 &#x1f368;…

分析linux启动内核源码

内核的启动时从main.c这个文件里面的start_kernel函数开始的&#xff0c;这个文件在linux源码里面的init文件夹下面 下面我们来看看这个函数 这个函数很长&#xff0c;可以看个大概过去 asmlinkage __visible void __init start_kernel(void) {char *command_line;char *afte…

MCE | 靶向相分离 小分子药物研发

细胞内的各种组分如何在正确的时间、地点上聚集并执行其相应的功能&#xff0c;是生命科学领域内的一大问题。近些年来&#xff0c;细胞内一些没有细胞膜结构包被的“细胞器” (Membrane-less organelles/condensates)——又称生物分子凝聚体 (Biomolecular condensates) 逐渐引…

Analyzing User-Level Privacy Attack Against Federated Learning

Analyzing User-Level Privacy Attack Against Federated Learning IEEE JSAC CCF-A期刊 宋梦凯&#xff08;武汉大学网络安全实验室&#xff09; Summary 提出了针对FL用户级隐私的基于GAN的攻击&#xff08;mGAN-AI&#xff09;&#xff0c;主要是从每个client的更新中计算…

UniPro助力半导体企业之低代码平台篇:高效协同快速响应

在《UniPro助力半导体企业之特色篇&#xff1a;缺陷管理覆盖全流程》中&#xff0c;我们介绍了UniPro如何帮助半导体企业完成在研发过程中的Bug管理&#xff0c;然而缺陷管理也并非UniPro的全部&#xff0c;除此之外&#xff0c;UniPro有着完整的项目管理体系&#xff0c;涵盖了…

相控阵天线(二):非规则直线阵列天线(稀布阵列、稀疏阵列、平方率分布阵列)

目录非规则线阵概述不均匀递变间距阵列稀布阵列稀疏阵列不均匀相位递变阵列不均匀幅度激励阵列代码示例非规则线阵概述 非规则线阵主要包括以下情况&#xff1a; 1. 不均匀间距阵列&#xff1a; a&#xff09;不均匀间距递变阵列&#xff1a;单元间距按照一定的系数递增&#…

傻白入门芯片设计,IP, MCM, SiP, SoC 和 Chiplet的区别(二)

一、IP&#xff1a; 早期的复制电路都是全定制&#xff0c;比如Intel的4004cpu&#xff0c;这种设计非常耗时。考虑到cpu的很多模块有相似的地方&#xff0c;能不能把这些东西模块化&#xff1f;于是就有了IP核的概念&#xff0c;Intelligent Property&#xff0c;即知识产权核…

智慧运维解决方案-最新全套文件

智慧运维解决方案-最新全套文件一、智能运维的必然性二、建设思路三、建设方案1、IT资产和配置管理2、自动化运维管理3、一体化运维平台四、获取 - 智慧运维全套最新解决方案合集一、智能运维的必然性 运维场景多样化。随着IT业务持续增长&#xff0c;为保证业务连续性&#xf…

相控阵天线(八):圆环阵列天线和球面阵列天线

目录圆环阵圆环阵方向图函数均匀圆环阵示例圆环阵层间距的影响非均匀圆环阵示例球面阵列球面阵方向图函数球面阵示例圆环阵 多个单元分布在一个圆环上的阵列称为圆环阵列。这是一种有实际意义的阵列结构&#xff0c;可应用于无线电测向、导航、地下探测等系统中。 圆环阵方向…

微服务介绍

目录一、系统架构演变单体应用架构垂直应用架构分布式架构SOA架构微服务架构二、微服务架构介绍微服务架构常见问题微服务架构常见概念服务治理服务调用服务网关服务容错链路追踪微服务架构常见问题解决方案ServiceComdServiceCloudServiceCloud AlibabaSpringCloud Alibaba介绍…

[论文评析-CV]MediaPipe: A Framework for Building Perception Pipelines, ArXiv,2019

MediaPipe: A Framework for Building Perception Pipelines文章信息前言框架介绍MediaPipe用于目标检测(1)Detection branch:(2)Tracking branch:MediaPipe框架重要的概念调度其他References文章信息 论文题目&#xff1a;MediaPipe: A Framework for Building Perception Pi…

mysql误删数据后 快速恢复的办法

手抖不小心把表里的数据删除或修改错误怎么办&#xff1f;该如何快速恢复呢&#xff1f;遇到这样的问题怎么办&#xff1f;希望下面这篇文章能够帮助到你&#xff01; 第一步&#xff1a;保证mysql已经开启binlog&#xff0c;查看命令&#xff1a; 查看binklog是否开启 show…

运动耳机品牌排行榜前十名有哪些,2022年六款运动耳机值得入手

近几年来&#xff0c;运动健身潮流一直都非常火热&#xff0c;但一个人运动难免会感到枯燥&#xff0c;这个时候最需要的就是音乐的陪伴了&#xff0c;佩戴着运动耳机听音乐&#xff0c;运动的时间也会过得越来越快&#xff0c;不过在选购运动耳机的过程会比挑选普通蓝牙耳机还…

pycharm社区版不能使用conda

修改成cmd 本质是conda init 问题 专业版的直接在终端改成cmd就行了

(DS90UB3702TRURRQ1) LT8640SHV-2低噪声降压稳压器QFN

LT8640/LT8640-1降压稳压器采用Silent Switcher架构&#xff0c;设计用于最大限度地降低EMI/EMC辐射并在高达3MHz的频率下提供高效率。由于具有2.5μA的超低静态电流&#xff08;当输出处于全面调节状态时&#xff09;&#xff0c;因此适用于要求在非常小负载电流条件下获得极高…

ICP算法加速优化--多线程和GPU

LZ之前的文章ICP算法实现&#xff08;C&#xff09; 用C实现了基础的ICP算法&#xff0c;由于该算法是一种迭代的优化算法&#xff0c;里面含有大量循环操作以及矩阵运算&#xff0c;可以通过使用多线程或者GPU硬件来进行加速&#xff0c;具体分别可以通过OpenMP和CUDA编程实现…

六、【React基础】组件实例三大核心属性之三 refs + 事件处理

文章目录1、字符串形式的ref&#xff08;过时/不推荐&#xff09;2、回调形式的ref&#xff08;推荐&#xff01;&#xff01;&#xff01;&#xff09;● 回调ref中回调次数的问题3、createRef创建ref容器&#xff08;最新最推荐&#xff09;4、事件处理理解&#xff1a;组件内…

Web3D应用开发在线IDE【中文版】

nunuStudio 是一个Web 3D应用程序的集成开发环境&#xff0c;它提供用于在 3D 世界中创建和编辑对象的工具&#xff0c;支持JavaScript和Python对3D场景进行二次开发。nunuStudio中文版 由 BimAnt 提供。 如果你曾经使用过其他类似的框架&#xff08;unity、playcanvas、godot …

Spring Boot 3.0 正式发布了!一个超重要的版本!!

首发于 JavaGuide (「Java学习面试指南」一份涵盖大部分 Java 程序员所需要掌握的核心知识。准备 Java 面试&#xff0c;首选 JavaGuide&#xff01;) 紧跟着 Spring Framework 6.0 的正式发布&#xff0c;就在昨天&#xff0c;Spring Boot 3.0 也正式发布了&#xff01; 这是一…

供应多臂PEG衍生物4-Arm PEG-Azide,4-Arm PEG-N3,四臂-聚乙二醇-叠氮

1、名称 英文&#xff1a;4-Arm PEG-Azide&#xff0c;4-Arm PEG-N3 中文&#xff1a;四臂-聚乙二醇-叠氮 2、CAS编号&#xff1a;N/A 3、所属分类&#xff1a;Azide PEG Multi-arm PEGs 4、分子量&#xff1a;可定制&#xff0c;四臂-PEG 2000-叠氮、4-Arm PEG-N3 20000、…