编程上下文Context及其实现原理

news2024/10/5 14:35:47

编程上下文Context及其实现原理

author:shengfq
date:2024-07-06
title:编程上下文Context及其实现原理
category:编程思想

思维导图

1.编程中的上下文Context是指什么?

在编程和软件工程领域,“上下文”(Context)是一个多义词,其含义可以根据不同的技术和框架有所变化,但总体上,上下文是指程序执行的环境或状态,它包含了影响程序行为的各种因素。下面是一些编程上下文的主要概念和应用场景:

  1. 线程上下文(Thread Context)
    在多线程编程中,上下文通常指一个线程的执行环境,包括CPU寄存器的值、堆栈状态、线程本地存储(TLS,Thread Local Storage)等。当操作系统或运行时环境在多个线程之间切换时,会保存当前线程的上下文,并恢复下一个线程的上下文。
  2. 函数调用上下文
    当一个函数被调用时,会创建一个调用上下文,其中包含函数的参数、局部变量和函数体。这个上下文在函数执行期间保持有效,直到函数返回,上下文被销毁。
  3. 作用域上下文
    作用域上下文定义了变量的可见性和生命周期。在不同的编程语言中,作用域规则可能有所不同,但通常包括全局作用域、局部作用域、类作用域等。
  4. 安全上下文(Security Context)
    在安全相关的编程中,上下文可能包含用户认证信息、权限和角色等。例如,在Spring Security中,SecurityContextHolder用于管理当前线程的安全上下文。
  5. 网络请求上下文
    在网络编程中,上下文可能包含请求和响应的详细信息,如HTTP头部、请求体、状态码等。
  6. 配置上下文
    应用程序运行所需的配置参数,如数据库连接字符串、API密钥、环境变量等,共同构成了配置上下文。
  7. 事务上下文
    在数据库编程中,事务上下文包含了事务的状态、隔离级别、回滚点等信息,它对于确保数据的一致性和完整性至关重要。
  8. 微服务上下文
    在微服务架构中,上下文可能包含服务间通信的追踪ID、请求的元数据等,用于调试和监控。
  9. 上下文切换(Context Switching)
    上下文切换是指操作系统在不同进程或线程之间切换执行环境的过程。这通常涉及到保存和恢复CPU寄存器、堆栈和其他状态,是影响系统性能的关键因素之一。
  10. 函数式编程上下文
    在函数式编程中,上下文可能指的是闭包(Closure)的概念,即函数可以访问并记住其定义时存在的外部变量。
  11. 框架和库提供的上下文
    许多框架和库提供了自己的上下文概念,如Spring框架的ApplicationContext,它管理着bean的生命周期和依赖注入。

总的来说,编程上下文是理解程序行为的关键,它帮助开发者追踪和控制程序执行的不同方面。掌握上下文的概念对于编写健壮、可维护的代码至关重要。

2.编程实践中常见的Context分类,主要作用?

例如spring框架的ApplicationContext,spring WEB框架的SecurityContext,用户自定义的需要获取会话环境数据的应用场景,如:HTTP请求的会话管理,数据库连接池的事务管理,用户登录访问服务授权管理,这些场景基本都是独立线程隔离级别的会话数据,每个线程都拥有独立的变量副本,不会干扰.

3.案例SecurityContext是怎么应用的?

使用SecurityContextHolder获取当前用户信息
在SecurityContextHolder中保存的是当前访问者的信息。Spring Security使用一个Authentication对象来表示这个信息。一般情况下,我们都不需要创建这个对象,在登录过程中,Spring Security已经创建了该对象并帮我们放到了SecurityContextHolder中。从SecurityContextHolder中获取这个对象也是很简单的。比如,获取当前登录用户的用户名,可以这

类结构:
    SecurityContextHolder //SecurityContext bean工厂
        SecurityContext //上下文实例
            Authentication //认证信息
                UserDetails //用户身份
                
  SecurityContextHolderStrategy  getContext() //接口 获取上下文对象            
    ThreadLocalSecurityContextHolderStrategy //实现类 提供存储在ThreadLocal中的SecurityContext
    InheritableThreadLocalSecurityContextHolderStrategy //提供子线程可继承访问的存储在ThreadLocal中的SecurityContext
    
// 获取安全上下文对象SecurityContext,就是那个保存在 ThreadLocal 里面的安全上下文对象,通过对

// 总是不为null(如果不存在,则创建一个authentication属性为null的empty安全上下文对象)
SecurityContext securityContext = SecurityContextHolder.getContext();

// 获取当前认证了的 principal(当事人),或者 request token (令牌)
// 如果没有认证,会是 null,该例子是认证之后的情况
Authentication authentication = securityContext.getAuthentication()

// 获取当事人信息对象,返回结果是 Object 类型,但实际上可以是应用程序自定义的带有更多应用相关信息的某个类型。
// 很多情况下,该对象是 Spring Security 核心接口 UserDetails 的一个实现类,你可以把 UserDetails 想像
// 成我们数据库中保存的一个用户信息到 SecurityContextHolder 中 Spring Security 需要的用户信息格式的
// 一个适配器。
Object principal = authentication.getPrincipal();
if (principal instanceof UserDetails) {
	String username = ((UserDetails)principal).getUsername();
} else {
	String username = principal.toString();
}

每个线程都有一个独立的Security Context,作为环境变量保存到当前线程.

认证与授权

Authentication对象会被填充并放置到SecurityContextHolder中

访问和修改

Authentication =SecurityContextHolder.getContext().getAuthentication()
SecurityContextHolder.getContext().setAuthentication(Authentication)

清理上下文

SecurityContextHolder.clearContext()
    ThreadLocal<SecurityContext>.remove()

4.SecurityContext实现原理ThreadLocal详解?

ThreadLocal 是 Java 中的一个类,用于在多线程环境下为每个线程提供独立的变量副本。它可以解决多线程并发访问共享变量时的线程安全问题。

在多线程应用程序中,多个线程可能同时访问同一个变量,如果没有适当的同步机制,就会导致数据的不一致性和竞态条件。ThreadLocal 提供了一种线程级别的变量隔离机制,使得每个线程都拥有自己独立的变量副本,互不干扰。

ThreadLocal 类提供了以下常用方法

get():获取当前线程的 ThreadLocal 变量的值。如果变量尚未被当前线程设置,则返回 null。

set(T value):设置当前线程的 ThreadLocal 变量的值为指定的值。

remove():移除当前线程的 ThreadLocal 变量。清除后,下次调用 get() 方法将返回 null。

initialValue():返回 ThreadLocal 的初始值。可以通过继承 ThreadLocal 并覆盖该方法来自定义初始值。

withInitial(Supplier<? extends T> supplier):使用指定的 Supplier 函数式接口提供的初始值创建一个 ThreadLocal 实例。

ThreadLocal 的这些方法提供了对线程局部变量的管理和访问。你可以使用 get() 和 set() 方法在当前线程中存储和获取变量的值,使用 remove() 方法清除变量,使用 initialValue() 方法自定义初始值,以及使用 withInitial() 方法创建具有自定义初始值的 ThreadLocal 实例。

ThreadLocal 使用案例

//线程安全的计数器
public class ThreadSafeCounter {
    private static ThreadLocal<Integer> counter = ThreadLocal.withInitial(() -> 0);

    public static void increment() {
        counter.set(counter.get() + 1);
    }

    public static int getCount() {
        return counter.get();
    }
}

线程上下文传递

public class UserContext {
    private static ThreadLocal<User> userThreadLocal = new ThreadLocal<>();

    public static void setUser(User user) {
        userThreadLocal.set(user);
    }

    public static User getUser() {
        return userThreadLocal.get();
    }
}

数据库连接管理

public class DBConnectionManager {
    private static ThreadLocal<Connection> connectionThreadLocal = new ThreadLocal<>();

    public static void openConnection() {
        // 获取数据库连接并设置到 ThreadLocal
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/db", "user", "password");
        connectionThreadLocal.set(connection);
    }

    public static Connection getConnection() {
        return connectionThreadLocal.get();
    }

    public static void closeConnection() {
        // 关闭数据库连接
        Connection connection = connectionThreadLocal.get();
        if (connection != null) {
            try {
                connection.close();
            } catch (SQLException e) {
                // 异常处理
            }
        }
        // 清理 ThreadLocal 变量
        connectionThreadLocal.remove();
    }
}

ThreadLocal 内存泄漏

ThreadLocal 是 Java 中的一个类,它提供了一个线程局部变量。这些变量不同于普通的变量,因为每个线程都有它自己的副本,而且它们之间互不影响。ThreadLocal 的目的是提供一个方便的方式来保存那些每个线程需要独立访问的数据。

内存泄漏通常指的是程序在释放了某个对象后,后续代码仍然可以访问这个对象。在使用 ThreadLocal 时,如果没有正确地移除对应的线程局部变量,可能会导致内存泄漏。因为一旦 ThreadLocal 的线程被回收,其关联的线程局部变量如果没有手动移除,那么下次当这个线程再次使用 ThreadLocal 时,它将持有一个过期的引用。

解决方法:
在使用完 ThreadLocal 后,手动调用 remove() 方法来清除线程局部变量。
如果使用的是 Java 8 或更高版本,可以利用 ThreadLocal 的新特性(目前是 preview 功能),即在 get 或 set 方法后自动清除线程局部变量。
如果是在 web 应用中,可以在请求处理完毕后的 Filter 中清理 ThreadLocal。
使用 ThreadLocal 的包装类,它们在每次 get 后自动清除 ThreadLocal 中的值。
如果使用了第三方库,检查是否有相关的工具类或注解来自动管理 ThreadLocal 的生命周期。

5.如何确定什么场景适合使用ThreadLocal实现的Context,并正确的使用

在生产实践中,我们要判断是否适合使用Context及ThreadLocal,主要判断依据有:

1.他是以空间换时间的方式实现,在高并发、高性能要求的场景下,频繁的同步操作会导致性能下降。使用 ThreadLocal 可以减少锁的使用,提高程序的并发性能。

2.每个线程都有一个独立的变量副本,需要快捷方便的从上下文中获取变量数据.可考虑使用.

那么,应用开发中,一些场景如:日志追踪,方法间共享信息,事务管理,会话信息,授权信息都可以采用上下文机制实现.

参考文档

ThreadLocal 线程局部变量
Spring Security 的基本组件 SecurityContextHolder

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

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

相关文章

产品经理-​合作的6类干系人(8)

在一个项目中&#xff0c;产品经理并不是一个人在战斗&#xff0c;而是在很多同事的配合下共同完成项目。那产品经理到底要和哪些角色配合&#xff0c;一起完成项目呢 中间的产品经理是一个项目的驱动者。而产品经理的前方是“Boss/Leader”&#xff0c;也就是创业团队中公司的…

地级市数字经济指数、互联网用户数、数字金融普惠指数

2000-2022年地级市数字经济指数&#xff08;含控制变量&#xff09; 目录 数字经济如何改善环境污染 一、引言 二、文献综述 三、实证模型 四、数据来源 五、程序代码 六、运行结果 数字经济如何改善环境污染 摘要&#xff1a; 本论文旨在探讨数字经济对环境污染的改善作…

三级_网络技术_04_中小型网络系统总体规划与设计

1.下列关于路由器技术特征的描述中&#xff0c;正确的是()。 吞吐量是指路由器的路由表容量 背板能力决定了路由器的吞吐量 语音、视频业务对延时抖动要求较低 突发处理能力是以最小帧间隔值来衡量的 2.下列关于路由器技术特征的描述中&#xff0c;正确的是()。 路由器的…

Matlab中collectPlaneWave函数的应用

查看文档如下&#xff1a; 可以看出最多5个参数&#xff0c;分别是阵列对象&#xff0c;信号幅度&#xff0c;入射角度&#xff0c;信号频率&#xff0c;光速。 在下面的代码中&#xff0c;我们先创建一个3阵元的阵列&#xff0c;位置为&#xff1a;&#xff08;-1,0,0&#x…

JavaWeb----JSPJSTL

目录 JSP显隐注释在JSP中写java程序JSP的指令标签JSP中的四大域对象简易版用户登录EL表达式 JSTL条件动作标签if标签 choose\when\otherwise标签迭代标签格式化动作标签 用户登录实例查看是否安装了mysql用户登录界面后台实现 JSP JSP全名是Java Server Pages&#xff0c;它是建…

【后端面试题】【中间件】【NoSQL】MongoDB查询优化3(拆分、嵌入文档,操作系统)

拆分大文档 很常见的一种优化手段&#xff0c;在一些特定的业务场景中&#xff0c;会有一些很大的文档&#xff0c;这些文档有很多字段&#xff0c;而且有一些特定的字段还特别的大。可以考虑拆分这些文档 大文档对MongoDB的性能影响还是很大的&#xff0c;就我个人经验而言&…

常见算法和Lambda

常见算法和Lambda 文章目录 常见算法和Lambda常见算法查找算法基本查找&#xff08;顺序查找&#xff09;二分查找/折半查找插值查找斐波那契查找分块查找扩展的分块查找&#xff08;无规律的数据&#xff09; 常见排序算法冒泡排序选择排序插入排序快速排序递归快速排序 Array…

在Apache HTTP服务器上配置 TLS加密

安装mod_ssl软件包 [rootlocalhost conf.d]# dnf install mod_ssl -y此时查看监听端口多了一个443端口 自己构造证书 [rootlocalhost conf.d]# cd /etc/pki/tls/certs/ [rootlocalhost certs]# openssl genrsa > jiami.key [rootlocalhost certs]# openssl req -utf8 -n…

Pycharm远程连接GPU(内容:下载安装Pycharm、GPU租借、配置SSH、将代码同步到镜像、命令行操控远程镜像、配置远程GPU解释器)

目录 windows下载安装pycharmGPU租借网站AutoDlfeaturize好易智算 GPU租借GPU选择选择镜像充值 然后创建镜像创建成功 复制SSH登录信息 远程进入镜像 在Pycharm中进行ssh连接新建SFTP配置SSH复制ssh根据复制的信息填写ssh配置测试连接 将代码同步到远程镜像上设置mappings将本地…

React 省市查询组件完整代码

目录 一、地区文件 二、Antd配合使用 三、实现效果 一、地区文件 下载地址&#xff1a;全国省市区数据_JSON格式_SQL格式 export const chinaArea {0: {1: 北京,2: 天津,3: 河北省,4: 山西省,5: 内蒙古自治区,6: 辽宁省,7: 吉林省,8: 黑龙江省,9: 上海,10: 江苏省,11: 浙…

计算机出现找不到msvcp140.dll无法继续执行代码怎么办?推荐7个有效解决方法

在日常使用电脑过程中会经常遇到各式各样的问题&#xff0c;比如msvcp140.dll丢失或找不到msvcp140.dll文件是最常见的问题之一&#xff0c;那么遇到这个问题要怎么解决呢&#xff1f;msvcp140.dll到底是什么&#xff1f;为什么会出现msvcp140.dll丢失问题&#xff1f;今天给大…

原生事件监听及组件内置事件处理

监听事件 我们可以使用 v-on 指令 (简写为 ) 来监听 DOM 事件&#xff0c;并在事件触发时执行对应的 JavaScript。用法&#xff1a;v-on:click“handler” 或 click“handler”。 事件处理器 (handler) 的值可以是&#xff1a; 内联事件处理器&#xff1a;事件被触发时执行的…

《QT从基础到进阶·四十三》QPlugin插件多线程问题和只有插件dll没有头文件和lib文件时调用插件中的方法

1、插件和多线程问题&#xff1a; 创建插件对象不能放到多线程执行&#xff0c;不然报错&#xff1a;ASSERT failure in QWidget: "Widgets must be created in the GUlthread. //不能放在多线程执行 QPluginLoader pluginLoader(pluginsDir.absoluteFilePath(fileName))…

单选多选提交问卷,代码示例

&#xff45;&#xff4c;&#xff45;&#xff4d;&#xff45;&#xff4e;&#xff54;中 需要对接口返回的数据进行分析。多选问题使用checkbox&#xff0c;单选题使用radio。 多选时可以绑定&#xff4d;&#xff49;&#xff4e;&#xff0f;&#xff4d;&#xff41;&am…

Transformer前置知识:Seq2Seq模型

Seq2Seq model Seq2Seq&#xff08;Sequence to Sequence&#xff09;模型是一类用于将一个序列转换为另一个序列的深度学习模型&#xff0c;广泛应用于自然语言处理&#xff08;NLP&#xff09;任务&#xff0c;如机器翻译、文本摘要、对话生成等。Seq2Seq模型由编码器&#…

搭建互联网医院实战:从源码到在线问诊APP的全流程开发

今天&#xff0c;笔者将讲述在线问诊APP的全流程开发&#xff0c;帮助开发者理解和掌握搭建互联网医院的核心技术和步骤。 一、需求分析与设计 需求分析包括明确目标用户、功能需求、性能需求等。设计阶段则包括系统架构设计、数据库设计和前后端界面设计等。 1.目标用户&…

统计是一门艺术(非参数假设检验)

1.定义 当总体分布未知&#xff0c;那么就需要一种与分布具体数学形式无关的统计推断方法&#xff0c;称为非参数方法 只能利用样本中的一般信息包括位置和次序关系等 稳健性强 2.符号检验 考虑问题&#xff1a; 小样本情况&#xff1a; 以概率为1/2的二项分布是对称的 两…

ASP.NET Core----基础学习01----HelloWorld---创建Blank空项目

文章目录 1. 创建新项目--方式一&#xff1a; blank2. 程序各文件介绍&#xff08;Project name &#xff1a;ASP.Net_Blank&#xff09;&#xff08;1&#xff09;launchSettings.json 启动方式的配置文件&#xff08;2&#xff09;appsettings.json 基础配置file参数的读取&a…

昇思25天学习打卡营第08天 | 模型训练

昇思25天学习打卡营第08天 | 模型训练 文章目录 昇思25天学习打卡营第08天 | 模型训练超参数损失函数优化器优化过程 训练与评估总结打卡 模型训练一般遵循四个步骤&#xff1a; 构建数据集定义神经网络模型定义超参数、损失函数和优化器输入数据集进行训练和评估 构建数据集和…

Git 运用小知识

1.Git添加未完善代码的解决方法 1.1 Git只是提交未推送 把未完善的代码提交到本地仓库 只需点击撤销提交&#xff0c;提交的未完善代码会被撤回 代码显示未提交状态 1.2 Git提交并推送 把未完善的代码提交并推送到远程仓库 点击【未完善提交并推送】的结点选择还原提交&#x…