Spring Boot 学习第八天:AOP代理机制对性能的影响

1 概述

        在讨论动态代理机制时,一个不可避免的话题是性能。无论采用JDK动态代理还是CGLIB动态代理,本质上都是在原有目标对象上进行了封装和转换,这个过程需要消耗资源和性能。而JDK和CGLIB动态代理的内部实现过程本身也存在很大差异。下面将讨论两种动态代理机制对系统运行性能所带来的影响。

2 测试案例设计

        为了量化不同动态代理对性能的影响程度,将设计一个案例,在该案例中同样使用前面介绍的AccountService接口以及它的实现类AccountServiceImpl。将通过创建一定数量的AccountServiceImpl实例并调用它的doAccountTransaction()方法,触发动态代理机制。

        为了能够基于不同的代理机制来创建对象,需要引入Spring中一个非常有用的注解,即@Scope。这个注解可以用来设置Bean的作用域,还可以用来指定代理模式ScopedProxyMode,在Spring中,ScopedProxyMode是一个枚举,代码如下:

public enum ScopedProxyMode {
    DEFAULT,
    NO,
    INTERFACES,
    TARGET_CLASS;

    private ScopedProxyMode() {
    }
}

        这里的INTERFACES代表的就是JDK动态代理,而TARGET_CLASS使用的则是CGLIB动态代理。现在,创建两个配置类JDKProxyConfig和CGLIBProxyConfig,分别针对AccountServiceImpl指定两种不同的代理机制。JDKProxyConfig代码如下:

@Configuration
@EnableAspectJAutoProxy
public class JDKProxyConfig {
    @Bean
    @Scope(proxyMode = ScopedProxyMode.INTERFACES)
    public AccountService accountService(){
        return new AccountServiceImpl();
    }
}

        CGLIBProxyConfig代码如下:

@EnableAspectJAutoProxy
@Configuration
public class CGLIBProxyConfig {

    @Bean
    @Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
    public AccountService accountService(){
        return new AccountServiceImpl();
    }
}

        借助于这两个配置类,就可以通过AnnotationConfigApplicationContext这个基于注解配置的应用上下文对象来获取添加了不同代理机制的AccountServiceImpl对象。准备工作已经完成,编写一个测试用例来对不同代理机制的性能进行量化。代码如下:

public class ProxyTest {
    private static final Logger LOGGER = Logger.getLogger(ProxyTest.class);

    @Test
    public void testAopProxyPerformance() throws MinimumAccountException {
        int countObjects = 5000;
        AccountServiceImpl[] unproxiedClasses = new AccountServiceImpl[countObjects];
        for (int i = 0; i < countObjects; i++) {
            unproxiedClasses[i] = new AccountServiceImpl();
        }
        AccountService[] cglibProxyClasses = new AccountService[countObjects];
        AccountService accountService = null;
        for (int i = 0; i < countObjects; i++) {
            accountService = new AnnotationConfigApplicationContext(CGLIBProxyConfig.class).getBean(AccountService.class);
            cglibProxyClasses[i] = accountService;
        }
        AccountService[] jdkProxyClasses = new AccountService[countObjects];
        for (int i = 0; i < countObjects; i++) {
            accountService = new AnnotationConfigApplicationContext(JDKProxyConfig.class).getBean(AccountService.class);
            jdkProxyClasses[i] = accountService;
        }

        long noProxy = invokeTargetObjects(countObjects, unproxiedClasses);
        displayResults("NOProxy",noProxy);
        long jdkProxy = invokeTargetObjects(countObjects, jdkProxyClasses);
        displayResults("JDKProxy",jdkProxy);
        long cglibProxy = invokeTargetObjects(countObjects, cglibProxyClasses);
        displayResults("cglibProxy",cglibProxy);

    }
    private void displayResults(String label, long timeTook) {
        LOGGER.info(label + ": " + timeTook + "(ns) " + (timeTook / 1000000) + "(ms)");
    }
    private long invokeTargetObjects(int countObjects,AccountService[] classes) throws MinimumAccountException {
        long start = System.nanoTime();
        Account source = new Account(101,"Account1");
        Account dest = new Account(102,"Account2");
        for (int i = 0; i < countObjects; i++) {
            classes[i].doAccountTransaction(source, dest, 100);
        }
        long end = System.nanoTime();
        return end - start;
    }
}

        运行结果:

        可以看到,分别针对不使用代理、使用JDK代理和CGLIB代理的场景,创建了5000个AccountServiceImpl对象实例,并记录它们的创建时间。以上量化结果取决于不同的机器配置,但不影响得出结论。从结果中不难看出,JDK动态代理在性能上优于CGLIB动态代理,但相差并不大。 

  其他类的代码如下:

public class Account {
    private String accountName;
    private Integer accountNumber;

    public String getAccountName() {
        return accountName;
    }
    public void setAccountName(String accountName) {
        this.accountName = accountName;
    }

    public Integer getAccountNumber() {
        return accountNumber;
    }
    public void setAccountNumber(Integer accountNumber) {
        this.accountNumber = accountNumber;
    }

    public Account(Integer accountNumber, String accountName) {
        this.accountNumber = accountNumber;
        this.accountName = accountName;
    }
}
public interface AccountService {
	
	boolean doAccountTransaction(Account source, Account dest, int amount);
}
public class AccountServiceImpl implements AccountService {
	@Override
	public boolean doAccountTransaction(Account source, Account dest, int amount) {
		
		return true;
	}

}

         

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

VMware vSphere 8.0 Update 3 发布下载 - 企业级工作负载平台

VMware vSphere 8.0 Update 3 发布下载 - 企业级工作负载平台 vSphere 8.0U3 | ESXi 8.0U3 & vCenter Server 8.0U3 请访问原文链接&#xff1a;https://sysin.org/blog/vmware-vsphere-8-u3/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&am…

Java面试八股之JVM内存溢出的原因及解决方案

JVM内存溢出的原因及解决方案 JVM内存溢出&#xff08;Out Of Memory&#xff0c;OOM&#xff09;通常是由于程序运行过程中内存使用不当造成的&#xff0c;常见原因及相应的解决方案如下&#xff1a; 原因及解决方案 内存中加载的数据量过大 原因&#xff1a;一次性从数据…

运维入门技术——监控的三个维度(非常详细)零基础收藏这一篇就够了_监控维度怎么区分

一个好的监控系统最后要做到的形态:实现Metrics、Tracing、Logging的融合。监控的三个维度也就是Metrics、Tracing、Logging。 Metrics Metrics也就是我们常说的指标。 首先它的典型特征就是可聚合(aggregatable).什么是可聚合的呢,简单讲可聚合就是一种基本单位可以在一种维…

Verilog刷题笔记48——FSM1型异步复位

题目: 解题&#xff1a; module top_module(input clk,input areset, // Asynchronous reset to state Binput in,output out);// parameter A0, B1; reg state, next_state;always (*) begin // This is a combinational always block// State transition logiccase(…

加拿大魁北克IT人士的就业分析

魁北克省作为加拿大东部的一个重要省份&#xff0c;近年来在IT行业的就业市场上展现出了强劲的增长势头。随着数字化转型的加速&#xff0c;魁北克对IT专业人士的需求日益增加&#xff0c;特别是在软件开发、网络安全、数据分析和人工智能等领域。 热门职位方面&#xff0c;软…

禹晶、肖创柏、廖庆敏《数字图像处理(面向新工科的电工电子信息基础课程系列教材)》Chapter 9插图

禹晶、肖创柏、廖庆敏《数字图像处理&#xff08;面向新工科的电工电子信息基础课程系列教材&#xff09;》 Chapter 9插图

201.回溯算法:全排列(力扣)

class Solution { public:vector<int> res; // 用于存储当前排列组合vector<vector<int>> result; // 用于存储所有的排列组合void backtracing(vector<int>& nums, vector<bool>& used) {// 如果当前排列组合的长度等于 nums 的长度&am…

用 Rust 实现一个替代 WebSocket 的协议

很久之前我就对websocket颇有微词&#xff0c;它的确满足了很多情境下的需求&#xff0c;但是仍然有不少问题。对我来说&#xff0c;最大的一个问题是websocket的数据是明文传输的&#xff0c;这使得websocket的数据很容易遭到劫持和攻击。同时&#xff0c;WebSocket继承自HTTP…

【操作系统】操作系统发展简史

目录 1.前言 2.第一代&#xff08;1945~1955&#xff09;&#xff1a;真空管和穿孔卡片 3.第二代&#xff08;1955~1965&#xff09;&#xff1a;晶体管和批处理系统 4.第三代&#xff08;1965~1980&#xff09;&#xff1a;集成电路和多道程序设计 5.第四代&#xff08;1…

关于VMware遇到的一些问题

问题一&#xff1a;打不开磁盘…或它所依赖的某个快照磁盘&#xff0c;开启模块DiskEarly的操作失败&#xff0c;未能启动虚拟机 解决方法&#xff1a; 首先将centos 7关机&#xff0c;然后把快照1删掉 然后打开虚拟机所在目录&#xff0c;把提示的000001.vmdk全部删除&…

本地读取classNames txt文件

通过本地读取classNames,来减少程序修改代码,提高了程序的拓展性和自定义化。 步骤: 1、输入本地路径,分割字符串。 2、将className按顺序放入vector容器中。 3、将vector赋值给classNmaes;获取classNames.size(),赋值给CLASSES;这样,类别个数和类别都已经赋值完成。…

大厂面试官问我:Redis内存淘汰,LRU维护整个队列吗?【后端八股文四:Redis内存淘汰策略八股文合集】

往期内容&#xff1a; 大厂面试官问我&#xff1a;Redis处理点赞&#xff0c;如果瞬时涌入大量用户点赞&#xff08;千万级&#xff09;&#xff0c;应当如何进行处理&#xff1f;【后端八股文一&#xff1a;Redis点赞八股文合集】-CSDN博客 大厂面试官问我&#xff1a;布隆过滤…

vue3 Cesium 离线地图

1、vite-plugin-cesium 是一个专门为 Vite 构建工具定制的插件&#xff0c;用于在 Vite 项目中轻松使用 Cesium 库。它简化了在 Vite 项目中集成 Cesium 的过程。 npm i cesium vite-plugin-cesium vite -D 2、配置vite.config.js import cesium from vite-plugin-cesiumexp…

监测与管理:钢筋计在工程项目中的应用

在现代工程建设中&#xff0c;特别是大型长期工程项目&#xff0c;对结构安全性的监测与管理至关重要。钢筋计作为一种重要的监测工具&#xff0c;在工程项目中发挥着不可替代的作用。本文将探讨钢筋计在长期工程项目中的应用&#xff0c;包括安装方法、数据监测与分析以及实际…

“基于下垂的多电源分布式控制系统设计”,高分资源,匠心制作,查重5%,下载可用。强烈推荐!!!

“基于下垂的多电源分布式控制系统设计”&#xff0c;高分资源&#xff0c;匠心制作&#xff0c;查重5%&#xff0c;下载可用。强烈推荐&#xff01;&#xff01;&#xff01; 摘要 社会的进步与发展&#xff0c;人们对于能源的需求和依赖越来越大。与此同时&#xff0c;国家…

通达信擒牛亮剑出击抄底主升浪指标公式源码

通达信擒牛亮剑出击抄底主升浪指标公式源码&#xff1a; ABC1:(CLOSE-REF(CLOSE,1))/REF(CLOSE,1)*100; ABC2:IF(CLOSE>OPEN,CLOSE,OPEN); ABC3:IF(CLOSE>OPEN,OPEN,CLOSE); ABC4:LLV(ABC2,4); ABC5:HHV(ABC3,4); ABC6:ABC2>ABC4 AND ABC3<ABC4 AND ABC2>ABC5 …

【unity实战】制作unity数据保存和加载系统——大型游戏存储的最优解

最终效果 文章目录 最终效果前言存储位置信息存储更多数据存储场景信息持久化存储数据 前言 前面写过小型游戏存储功能&#xff1a; 【unity实战】制作unity数据保存和加载系统——小型游戏存储的最优解&#xff08;包含数据安全处理方案的加密解密&#xff09; 这次做一个针…

spire.Pdf 将pdf转成image

一、nuget安装 <ItemGroup><PackageReference Include"Spire.PDF" Version"10.6.7" /></ItemGroup> 二、直接上代码 using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using System; using System.IO;namespace …

spring 中自动代理生成器的实现

为什么需要自动代理生成器 在 spring 中&#xff0c;提供了 org.springframework.aop.framework.ProxyFactoryBean 来实现对目标 bean 的增强&#xff0c;但此工具类存在以下缺点&#xff1a; 目标 bean 被增强后&#xff0c;获取实例对象时&#xff0c;使用的是配置的代理 b…

PostgreSQL使用教程

安装 PostgreSQL 您可以从 PostgreSQL 官方网站下载适合您操作系统的安装程序&#xff0c;并按照安装向导进行安装。 启动数据库服务器 安装完成后&#xff0c;根据您的操作系统&#xff0c;通过相应的方式启动数据库服务器。 连接到数据库 可以使用命令行工具&#xff08;如 p…