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

编程上下文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中的SecurityContextInheritableThreadLocalSecurityContextHolderStrategy //提供子线程可继承访问的存储在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() {// 获取数据库连接并设置到 ThreadLocalConnection 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.mzph.cn/pingmian/42111.shtml

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

相关文章

1.Python学习笔记

一、环境配置 1.Python解释器 把程序员用编程语言编写的程序&#xff0c;翻译成计算机可以执行的机器语言 安装&#xff1a; 双击Python3.7.0-选择自定义安装【Customize installation】-勾选配置环境变量 如果没有勾选配置环境变量&#xff0c;输入python就会提示找不到命令…

Idea新增Module报错:sdk ‘1.8‘ type ‘JavaSDK‘ is not registered in ProjectJdkTable

文章目录 一&#xff0c;创建Module报错二&#xff0c;原因分析三&#xff0c;解决方案1&#xff0c;点击上图的加号&#xff0c;把JDK8添加进来即可2&#xff0c;点击左侧[Project]&#xff0c;直接设置SDK为JDK8 四&#xff0c;配置检查与验证 一&#xff0c;创建Module报错 …

创维汽车开展年中总结会:创新创造·勇开拓 智慧经营·攀高峰

2024年7月3日&#xff0c;回顾上半年的工作成果&#xff0c;总结经验教训&#xff0c;明确下半年的发展方向和重点任务&#xff0c;创维汽车于山西省晋中市榆次区山西联合创维体验中心开展年中总结会。 创维集团、创维汽车创始人黄宏生&#xff1b;开沃集团联合创始人、首席执…

【C++干货基地】C++模板深度解析:进阶技巧与高级特性掌握(按需实例化、全特化与偏特化)文末送书

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 引入 哈喽各位铁汁们好啊&#xff0c;我是博主鸽芷咕《C干货基地》是由我的襄阳家乡零食基地有感而发&#xff0c;不知道各位的…

动态路由--RIP配置(思科cisco)

一、简介 RIP协议&#xff08;Routing Information Protocol&#xff0c;路由信息协议&#xff09;是一种基于距离矢量的动态路由选择协议。 在RIP协议中&#xff0c;如果路由器A和网络B直接相连&#xff0c;那么路由器A到网络B的距离被定义为1跳。若从路由器A出发到达网络B需要…

Vben:表格的表头和表格的内容对不齐,以及解决方法

文章目录 一、问题描述二、解决方法 一、问题描述 基于Vue-Vbne-admin框架进行前端开发的时候&#xff0c;调用表格useTable函数实现表格之后&#xff0c;发现表格的表头和表格的内容对不齐。如下图所示。针对这种情况&#xff0c;本文记录了解决方法。 调用的模块如下&#x…

带你一步步搭建Web自动化测试框架

测试框架的设计有两种思路&#xff0c;一种是自底向上&#xff0c;从脚本逐步演变完善成框架&#xff0c;这种适合新手了解框架的演变过程。另一种则是自顶向下&#xff0c;直接设计框架结构和选取各种问题的解决方案&#xff0c;这种适合有较多框架事件经验的人。本章和下一张…

优化LabVIEW代码以提高软件性能

优化LabVIEW代码对于提高软件性能、减少执行时间和资源消耗至关重要。以下是一些具体的策略和方法&#xff0c;可以帮助LabVIEW程序员优化代码&#xff1a; 1. 代码结构和模块化 使用子VI&#xff1a;将重复使用的代码段封装成子VI&#xff0c;提高代码的可读性和可维护性。 避…

使用Vue CLI方式创建Vue3.0应用程序

Vue CLI 是一个基于 Vue.js 进行快速开发的完整系统。新版本的 Vue CLI 的包名由原来的 vue-cli 改成了 vue/cli。 在开发大型项目时&#xff0c;需要考虑项目的组织结构、项目构建和部署等问题。如果手动完成这些配置工作&#xff0c;工作效率会非常低。为此&#xff0c;Vue.…

刷题之买股票的最佳时机(leetcode)

买股票的最佳时机 动态规划入门题。 最简单的模拟式解法&#xff1a; class Solution { public:int maxProfit(vector<int>& prices) {//也可以换一种思路&#xff0c;因为只交易一次&#xff0c;那么找出股票最便宜的时候买入&#xff0c;最贵的时候卖出&#xff…

c与c++的内存管理

给出内存四个分区名字&#xff1a;栈区、堆区、全局区&#xff08;俗话也叫静态变量区&#xff09;、代码区&#xff08;也叫代码段&#xff09;&#xff08;代码段又分很多种&#xff0c;比如常量区&#xff09; 当然也会看到别的定义如&#xff1a; 两者都正确&#xff0c;记…

职升网:中级统计师是否属于中级职称?

中级统计师确实属于中级职称。 在统计专业人员的职称体系中&#xff0c;中级统计师占据了重要的位置&#xff0c;它属于中级职称范畴。这个职称体系包括初级、中级、高级和正高级四个层次&#xff0c;每个层次都对应着不同的专业技术岗位等级。初级职称只设助理级&#xff0c;…

【大数据】—FIFA世界杯探索性分析(EDA)

引言 足球&#xff0c;作为全球最受欢迎的运动之一&#xff0c;拥有庞大的粉丝群体和深远的文化影响。自1930年首届FIFA世界杯举办以来&#xff0c;这项赛事已经成为全球体育盛事&#xff0c;吸引了数十亿观众的目光。世界杯不仅是各国足球技艺的较量&#xff0c;更是国家荣誉…

View->裁剪框View的绘制,手势处理

XML文件 <?xml version"1.0" encoding"utf-8"?> <RelativeLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"match_parent"android…

texStudio使用(小白)

原先使用overleaf在线编译&#xff0c;可能eps格式的图片太大导致需要充钱&#xff0c;所以考虑本地安装 安装教程参考B站视频&#xff1a;B站Latex本地编译器安装&#xff1a;TexLive TextStudio 踩到坑&#xff1a; 1. 编译器位置要选择对 因为BibTex选成了Biber导致出现无…

vb.netcad二开自学笔记1:万里长征第一步Hello CAD!

已入门的朋友请绕行&#xff01; 今天开启自学vb.net 开发autocad&#xff0c;网上相关资料太少了、太老了。花钱买课吧&#xff0c;穷&#xff01;又舍不得&#xff0c;咬牙从小白开始摸索自学吧&#xff0c;虽然注定是踏上了一条艰苦之路&#xff0c;顺便作个自学笔记备忘!积…

海外短剧CPS系统:源码部署与推广分佣全攻略

海外短剧CPS系统&#xff1a;源码部署与推广分佣全攻略 在数字化浪潮下&#xff0c;海外短剧市场日益繁荣&#xff0c;成为众多创业者和投资者的新宠。倾力打造了一款创新的海外短剧CPS分销系统&#xff0c;为广大用户提供了一个全新的赚钱模式。今天&#xff0c;我们就来深入…

Django学习第六天

启动项目命令 python manage.py runserver 取消模态框功能 js实现列表数据删除 第二种实现思路 使用jquery修改模态框标题 编辑页面拿到数据库数据显示默认数据功能实现 想要去数据库中获取数据时&#xff1a;对象/字典 三种不同的数据类型 使用Ajax传入数据实现表单编辑&…

HTML5使用<details>标签:展开/收缩信息

details 标签提供了一种替代 JavaScript 的方法&#xff0c;它主要是提供了一个展开/收缩区域。details 标签中可以使用 summary 标签从属于 details 标签&#xff0c;单击 summary 标签中的内容文字时&#xff0c;details 标签中的其他所有从属元素将会展开或收缩。语法如下&a…

S32DS S32 Design Studio for S32 Platform 3.5 软件安装离线激活

问题描述 重新下载安装 NXP s32系列芯片的集成开发环境&#xff08;IDE&#xff09; S32DS S32 Design Studio&#xff0c;当前版本 S32 Design Studio for S32 Platform 3.5&#xff0c;安装时遇到激活问题 在线激活&#xff0c;激活码哪里来&#xff1f; s32ds 不是免费的&a…