spring中 THreadLocal 的运用地方

本文深入探讨了AOP(面向切面编程)在Spring框架中的实现细节,特别是在创建代理对象过程中如何匹配合适的通知类。文章详细解析了AbstractAdvisorAutoProxyCreator类中findAdvisorsThatCanApply方法的作用,以及在匹配过程中如何利用ThreadLocal保存当前被代理的bean名称,确保正确地为每个bean创建代理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.aop 代理xx 在真正对普通bean作为tartget创建代理proxy对象前,
先是找该类所对应所有的可以适配的 通知类集合时,
在 AbstarctAdvisorAutoProxyCreator 中

protected List<Advisor> findAdvisorsThatCanApply(
			List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {

		ProxyCreationContext.setCurrentProxiedBeanName(beanName);
		try {
			return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
		}
		finally {
			ProxyCreationContext.setCurrentProxiedBeanName(null);
		}
	}

而那个setxxxName 就是
加粗样式

public class ProxyCreationContext {

	/** ThreadLocal holding the current proxied bean name during Advisor matching */
	private static final ThreadLocal<String> currentProxiedBeanName =
			new NamedThreadLocal<>("Name of currently proxied bean");

2.获取requestxxx

### 如何在 Spring 框架中获取和使用 ThreadLocal 变量 #### 创建自定义 ThreadLocal 类 为了更好地管理和访问 `ThreadLocal` 变量,通常会创建一个封装类来处理这些操作。这不仅提高了代码的可读性和维护性,还确保了线程安全。 ```java public class UserContextHolder { private static final ThreadLocal<String> contextHolder = new ThreadLocal<>(); public static void setUserId(String userId) { contextHolder.set(userId); } public static String getUserId() { return contextHolder.get(); } public static void clear() { contextHolder.remove(); } } ``` 此方法允许应用程序通过静态方法设置、获取或清除特定于当前线程的数据[^1]。 #### 将 ThreadLocal 集成到 Spring 中 当希望在整个请求生命周期内保持某些数据不变时(例如用户ID),可以在控制器层捕获所需信息并将其存储在 `ThreadLocal` 中: ```java @RestController @RequestMapping("/api/users") public class UserController { @GetMapping("/{id}") public ResponseEntity<UserDTO> getUserById(@PathVariable Long id) { // 设置当前线程的userId UserContextHolder.setUserId(id.toString()); try { // 调用服务逻辑... return userService.getUserById(id); } finally { // 清除上下文以防止内存泄漏 UserContextHolder.clear(); } } } ``` 这种模式特别适用于跨多个组件传递相同的信息而无需显式地将参数逐级向下传入每一个调用链路中[^2]。 #### 使用 AOP 自动注入 ThreadLocal 数据 对于更复杂的应用程序结构,可以利用面向切面编程(AOP),自动为符合条件的方法执行前后添加 `ThreadLocal` 的存取逻辑。这样做的好处是可以减少样板代码的数量,并使业务逻辑更加清晰简洁。 ```java @Aspect @Component public class UserContextAspect { @Around("@annotation(org.springframework.web.bind.annotation.RequestMapping)") public Object around(ProceedingJoinPoint joinPoint) throws Throwable { HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest(); String userIdFromHeader = request.getHeader("X-User-ID"); if (StringUtils.hasText(userIdFromHeader)) { UserContextHolder.setUserId(userIdFromHeader); try { return joinPoint.proceed(); } finally { UserContextHolder.clear(); } } throw new IllegalArgumentException("Missing X-User-ID header"); } } ``` 上述实现展示了如何拦截带有 `@RequestMapping` 注解的方法,在进入实际业务逻辑之前解析 HTTP 请求头并将找到的用户 ID 存储至 `ThreadLocal` 实例中;之后无论后续流程多么复杂,任何地方都可以方便快捷地获得这个值。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值