Spring使用中需要注意的地方

本文分享了作者在使用Spring框架过程中的几点心得,包括不要迷信框架、根据实际情况选择使用、尽量采用set方法注入模式以及慎重考虑使用SpringMVC等内容。
部署运行你感兴趣的模型镜像

最近再一次阅读了一些Spring的资料,对Spring有了一些新的认识。回想自己曾经写过的一些Spring相关的程序片断偶有所得,于是记下了一些心得。

 

使用Spring时注意得几点:

 

第一,   不要迷信

Spring项目的创始人(我们伟大的……你打我干什么?不打你才怪,不是说不能迷信吗?)也认为设计的优秀要远远重要于使用的技术。所以不要认为选择了Spring就能够保证我们的系统拥有金刚不坏体。可是国内却往往把使用了某某先进技术作为招牌来用,我从来不认为使用了好的技术的项目本身就一定会是成功的。

第二,   因题施法

对于具体的情况使用不同的解决办法。Spring对于一个从无到有的项目来说绝对是一个不错的选择,但是对于一个已经存在了数据结构或者陈旧代码的项目来说中途把它加进来能够起到的作用有限。

往往与Spring同时使用的还有HibernateStruts这两个家伙。Struts暂且不提,毕竟人家fans多,我怕死。Hibernate这个东西也是被很多人捧的上天的家伙,可是这个玩意不是万能的。Hibernate近乎完美的封装了底层数据同步的操作,在开发上可以为我们节省太多的时间。但是完美本身就是缺点,Hibernate完美是有代价的,它为了完美付出的最大代价就是“性能”。不信的Hibernate拥护者可以自己作个测试看看,它封装之后的操作要比JDBC编程方式下慢多少倍。封装完美就无法对于SQL语句优化,如果你的数据库是一个已有的,那么使用Hibernate只会给你带来无穷无尽的麻烦。

所以使用之前考虑好你的系统的复杂程度,如果你的系统十分简单,没有那么多相互依赖的bean的话,我们无须使用Spring

第三,   尽量使用set方法的注入模式

我见过很多的Spring相关的代码,发祥对于BeanFactory的使用方式基本分为两种,一种是获取了BeanFactory实例然后生成需要的bean;另外一种是使用set方法的注入实现。

我奇怪的发现很多人喜欢获得BeanFactory实例然后再生成需要的实例,我觉得这样做已经违背了Spring的使用原则——尽量减少模块之间的依赖关系。因此我觉得使用set方法的注入模式才是正确的选择,至少这样的代码看起来要更加优雅。

第四,   慎重的选择SpringMVC作为表现层

Spring是个好东西,但是并不代表它全部适合你。至少我觉得SpringMVC就不适合绝大多数情况,SpringMVC十分优雅,但是它的优雅有些过分了。就像一个过分注重理论并且有着极高的学术地位的专家,这样的专家并不一定会是一个能够创造出很多价值的程序高手。

SpringMVC的学习代价高,使用起来虽然功能强大,但是却无法熟练的应用。所以我一般不会选择使用这样一个过分注重设计的东西,设计要适当不要过渡。

您可能感兴趣的与本文相关的镜像

Llama Factory

Llama Factory

模型微调
LLama-Factory

LLaMA Factory 是一个简单易用且高效的大型语言模型(Large Language Model)训练与微调平台。通过 LLaMA Factory,可以在无需编写任何代码的前提下,在本地完成上百种预训练模型的微调

<think>我们正在讨论Spring框架中ThreadLocal的使用场景。根据用户提供的引用,虽然引用内容主要涉及Spring Core和Spring Security等基础模块,但并未直接说明ThreadLocal的使用。不过,结合Spring框架的常见实现,我们可以总结出ThreadLocal在Spring中的几个关键应用场景。 注意:用户提供的引用[1][2][3]主要介绍Spring Core容器和核心功能,引用[4]则提到Spring Security的核心组件。因此,我们需要结合Spring框架的实际实现来回答。 以下是Spring框架中使用ThreadLocal的主要组件和场景: ### 一、Spring事务管理(Transaction Management) 在Spring的事务管理中,`TransactionSynchronizationManager`类使用ThreadLocal来保存当前事务的相关资源(如数据库连接),确保同一个线程内的方法可以共享同一个事务上下文。 **关键ThreadLocal变量**: ```java public abstract class TransactionSynchronizationManager { private static final ThreadLocal<Map<Object, Object>> resources = new NamedThreadLocal<>("Transactional resources"); private static final ThreadLocal<Set<TransactionSynchronization>> synchronizations = new NamedThreadLocal<>("Transaction synchronizations"); private static final ThreadLocal<String> currentTransactionName = new NamedThreadLocal<>("Current transaction name"); // 其他省略... } ``` - **作用**:在同一线程中传播事务上下文,避免显式传递连接对象[^1][^3]。 ### 二、请求上下文(Request Context) - 如Spring MVC 在Web应用中,Spring的`RequestContextHolder`使用ThreadLocal来存储当前请求的上下文信息(如HttpServletRequest和HttpServletResponse),以便在Controller、Service层等任何地方都能访问当前请求。 **实现代码**: ```java public abstract class RequestContextHolder { private static final ThreadLocal<RequestAttributes> requestAttributesHolder = new NamedThreadLocal<>("Request attributes"); // 其他方法... } ``` - **使用场景**:在拦截器或Controller中,可通过`RequestContextHolder.currentRequestAttributes()`获取当前请求[^1]。 ### 三、Spring Security安全上下文(Security Context) Spring Security通过`SecurityContextHolder`将当前认证信息(如用户凭证)绑定到线程。 **ThreadLocal策略**: ```java public class SecurityContextHolder { public static final String MODE_THREADLOCAL = "MODE_THREADLOCAL"; private static SecurityContextHolderStrategy strategy; // 默认使用ThreadLocalSecurityContextHolderStrategy static { initialize(); } private static void initialize() { // 默认策略为ThreadLocal setStrategyName(MODE_THREADLOCAL); } } ``` - **作用**:在同一个线程中,任何地方都可以通过`SecurityContextHolder.getContext()`获取当前用户的安全上下文[^4]。 ### 四、本地化上下文(LocaleContext) Spring的国际化支持中,`LocaleContextHolder`使用ThreadLocal保存当前请求的本地化信息(Locale)和时区(TimeZone)。 **实现**: ```java public abstract class LocaleContextHolder { private static final ThreadLocal<LocaleContext> localeContextHolder = new NamedThreadLocal<>("Locale context"); // ... } ``` ### 五、其他场景 1. **OpenSessionInViewFilter**(已不推荐): - 在Hibernate中,该过滤器通过ThreadLocal将一个Hibernate Session绑定到整个请求线程,确保延迟加载在视图渲染时仍有效(但此模式存在争议,现代应用推荐使用DTO模式)。 2. **异步任务上下文传递**: - 在Spring 4.3+中,`TaskDecorator`接口可用于将ThreadLocal绑定的上下文(如安全上下文)从父线程传递到子线程。 --- ### 总结:Spring中ThreadLocal的核心作用 | 组件/类 | ThreadLocal用途 | 所在模块 | |--------------------------|-----------------------------------------|-------------------| | `TransactionSynchronizationManager` | 管理事务资源(连接、同步等) | Spring-TX | | `RequestContextHolder` | 存储当前HTTP请求的上下文 | Spring-Web | | `SecurityContextHolder` | 保存当前认证用户的安全上下文 | Spring-Security | | `LocaleContextHolder` | 保存本地化信息(语言、时区) | Spring-Context | > **最佳实践提示**: > 1. 这些组件都使用`static final`修饰ThreadLocal变量,确保全局唯一[^1][^2] > 2. 在Web应用中,需配合过滤器(Filter)或拦截器(Interceptor)及时清理ThreadLocal(如`SecurityContextPersistenceFilter`会在请求结束时清除安全上下文)[^4] --- ### §§相关问题§§ 1. Spring Security中如何将安全上下文传递给子线程? 2. Spring事务管理是如何实现事务传播的? 3. 如何自定义ThreadLocal变量在Spring中的生命周期管理? 4. 为什么OpenSessionInViewFilter被认为是不良实践?</think>### Spring框架中ThreadLocal的核心应用场景 Spring框架在多处关键组件中使用了ThreadLocal来实现线程隔离的上下文管理,以下是主要应用场景及实现原理: --- #### 一、请求上下文管理(Request Context) **核心组件**:`RequestContextHolder` **实现方式**: ```java public abstract class RequestContextHolder { // 使用ThreadLocal存储请求属性 private static final ThreadLocal<RequestAttributes> requestAttributesHolder = new NamedThreadLocal<>("Request attributes"); // 获取当前请求上下文 public static RequestAttributes currentRequestAttributes() { return requestAttributesHolder.get(); } } ``` **作用**: 在Web请求处理链中(如Controller、Service层),通过`RequestContextHolder`可随时获取当前HTTP请求的`HttpServletRequest`和`HttpServletResponse`对象,实现请求级数据共享[^1][^3]。 **典型使用场景**: ```java // 在任意业务层获取当前请求 HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()) .getRequest(); ``` --- #### 二、事务管理(Transaction Management) **核心组件**:`TransactionSynchronizationManager` **ThreadLocal变量**: ```java public abstract class TransactionSynchronizationManager { // 存储事务资源(如数据库连接) private static final ThreadLocal<Map<Object, Object>> resources = new NamedThreadLocal<>("Transactional resources"); // 存储事务同步器 private static final ThreadLocal<Set<TransactionSynchronization>> synchronizations = new NamedThreadLocal<>("Transaction synchronizations"); } ``` **作用**: 1. 在声明式事务(`@Transactional`)中绑定数据库连接到当前线程 2. 确保同一线程内多个数据库操作使用同一个连接 3. 实现事务的传播行为(如`PROPAGATION_REQUIRED`)[^1][^3] --- #### 三、安全上下文(Security Context) **核心组件**:`SecurityContextHolder` **实现策略**: ```java public class SecurityContextHolder { // 默认使用ThreadLocal存储策略 private static SecurityContextHolderStrategy strategy; static { initialize(); // 初始化时选择MODE_THREADLOCAL策略 } public static SecurityContext getContext() { return strategy.getContext(); // 从ThreadLocal获取 } } ``` **作用**: 存储当前认证用户信息(`Authentication`对象),使`SecurityContext`在请求处理线程中随处可访问[^4]。 **使用示例**: ```java Authentication auth = SecurityContextHolder.getContext().getAuthentication(); ``` --- #### 四、本地化上下文(Locale Context) **核心组件**:`LocaleContextHolder` **实现方式**: ```java public abstract class LocaleContextHolder { private static final ThreadLocal<LocaleContext> localeContextHolder = new NamedThreadLocal<>("Locale context"); // 设置当前线程的Locale public static void setLocale(Locale locale) { setLocaleContext(locale != null ? new SimpleLocaleContext(locale) : null); } } ``` **作用**: 管理国际化(i18n)相关的语言环境,确保同一请求中保持一致的本地化设置[^1]。 --- ### ThreadLocal在Spring中的设计特点 1. **静态化声明** 所有ThreadLocal实例均使用`static final`修饰,确保全局唯一性: ```java private static final ThreadLocal<...> holder = ...; ``` 2. **命名化封装** 使用`NamedThreadLocal`增强可读性和调试能力: ```java new NamedThreadLocal<>("Transactional resources"); ``` 3. **生命周期管理** 通过过滤器/拦截器确保资源清理: ```java // 示例:在Spring Security中清理SecurityContext public class SecurityContextPersistenceFilter { protected void doFilterInternal(...) { try { // 业务处理 } finally { SecurityContextHolder.clearContext(); // 强制清理 } } } ``` --- ### 典型应用模块总结 | 组件模块 | 核心类 | ThreadLocal作用 | 所属Spring模块 | |-------------------------|--------------------------------|-------------------------------------|-------------------| | **请求上下文** | `RequestContextHolder` | 存储HTTP请求/响应对象 | spring-web | | **事务管理** | `TransactionSynchronizationManager` | 绑定数据库连接/事务状态 | spring-tx | | **安全认证** | `SecurityContextHolder` | 存储用户认证信息 | spring-security | | **国际化支持** | `LocaleContextHolder` | 管理语言/时区设置 | spring-context | | **OpenSessionInView** | `SessionFactoryUtils` | 绑定Hibernate Session到请求线程 | spring-orm | > **最佳实践**: > Spring通过`Filter`和`Interceptor`在请求入口初始化ThreadLocal,在出口通过`finally`块调用`remove()`清理资源,避免线程池复用导致的内存泄漏[^1][^4]。 --- ###
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值