温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Spring Ioc中各个scope的Bean是怎么创建的

发布时间:2021-06-23 14:16:05 来源:亿速云 阅读:118 作者:chen 栏目:大数据
# Spring IoC中各个scope的Bean是怎么创建的 ## 目录 1. [引言](#引言) 2. [Spring Bean Scope概述](#spring-bean-scope概述) 3. [Singleton Scope的创建机制](#singleton-scope的创建机制) 4. [Prototype Scope的创建机制](#prototype-scope的创建机制) 5. [Request Scope的创建机制](#request-scope的创建机制) 6. [Session Scope的创建机制](#session-scope的创建机制) 7. [Application Scope的创建机制](#application-scope的创建机制) 8. [WebSocket Scope的创建机制](#websocket-scope的创建机制) 9. [自定义Scope的实现原理](#自定义scope的实现原理) 10. [Scope代理模式详解](#scope代理模式详解) 11. [生命周期回调与Scope的关系](#生命周期回调与scope的关系) 12. [常见问题与解决方案](#常见问题与解决方案) 13. [总结](#总结) ## 引言 Spring框架的核心特性之一就是控制反转(IoC)容器,它负责管理应用中各个组件(Bean)的生命周期。理解不同scope下Bean的创建机制对于构建健壮的Spring应用至关重要。本文将深入剖析Spring IoC容器中各种scope Bean的创建过程,揭示其底层实现原理。 ## Spring Bean Scope概述 Spring提供了多种Bean作用域(Scope),每种scope定义了Bean实例的生命周期和可见范围: ```java public interface Scope { Object get(String name, ObjectFactory<?> objectFactory); Object remove(String name); void registerDestructionCallback(String name, Runnable callback); Object resolveContextualObject(String key); String getConversationId(); } 

标准scope包括: - singleton(默认) - prototype - request - session - application - websocket

Singleton Scope的创建机制

核心特点

  • 每个Spring IoC容器中仅存在一个实例
  • 默认作用域
  • 在容器启动时预初始化(可通过lazy-init延迟)

创建流程

  1. 实例化阶段

    // AbstractAutowireCapableBeanFactory.java protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) { BeanWrapper instanceWrapper = createBeanInstance(beanName, mbd, args); // ... } 
  2. 依赖注入

    populateBean(beanName, mbd, instanceWrapper); 
  3. 初始化

    exposedObject = initializeBean(beanName, exposedObject, mbd); 
  4. 缓存到单例池

    // DefaultSingletonBeanRegistry.java public void registerSingleton(String beanName, Object singletonObject) { synchronized (this.singletonObjects) { this.singletonObjects.put(beanName, singletonObject); // ... } } 

关键实现

  • 使用ConcurrentHashMap实现单例缓存:
     private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256); 

Prototype Scope的创建机制

核心特点

  • 每次请求都创建新实例
  • 不参与生命周期完整管理
  • 需要手动清理资源

创建流程

  1. 每次请求触发新实例创建

    // AbstractBeanFactory.java if (mbd.isPrototype()) { return createBean(beanName, mbd, args); } 
  2. 不进行缓存

    • 与singleton不同,prototype不会缓存实例
  3. 初始化回调仍会执行

    if (mbd.isPrototype()) { // 每次都执行初始化方法 initializeBean(beanName, object, mbd); } 

资源管理

  • 建议实现DisposableBean接口:
     public class PrototypeBean implements DisposableBean { @Override public void destroy() { // 清理资源 } } 

Request Scope的创建机制

核心特点

  • 每个HTTP请求一个实例
  • 仅适用于Web环境
  • 请求结束时自动销毁

注册过程

  1. 需要注册RequestContextListener
     <listener> <listener-class> org.springframework.web.context.request.RequestContextListener </listener-class> </listener> 

实现原理

  1. 使用RequestScope实现:

    public class RequestScope implements Scope { @Override public Object get(String name, ObjectFactory<?> objectFactory) { ServletRequestAttributes attrs = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes(); // ... } } 
  2. 存储于请求属性中:

    attrs.setAttribute(name, scopedObject, RequestAttributes.SCOPE_REQUEST); 

Session Scope的创建机制

核心特点

  • 每个用户会话一个实例
  • 会话失效时自动销毁
  • 支持分布式会话

实现机制

  1. 基于SessionScope实现:

    public class SessionScope implements Scope { @Override public Object get(String name, ObjectFactory<?> objectFactory) { HttpSession session = RequestContextHolder.currentRequestAttributes().getSession(); // ... } } 
  2. 会话绑定监听:

    session.setAttribute(name, scopedObject); 

Application Scope的创建机制

核心特点

  • 整个Web应用共享一个实例
  • 介于singleton和request之间
  • 存储在ServletContext中

实现方式

public class ServletContextScope implements Scope { @Override public Object get(String name, ObjectFactory<?> objectFactory) { ServletContext sc = getServletContext(); synchronized (sc) { // ... } } } 

WebSocket Scope的创建机制

核心特点

  • 每个WebSocket会话一个实例
  • 需要Spring WebSocket支持
  • 会话结束时销毁

配置示例

@Bean public static ServletWebSocketHandlerRegistry webSocketHandlerRegistry() { return new ServletWebSocketHandlerRegistry(); } 

自定义Scope的实现原理

实现步骤

  1. 实现Scope接口:

    public class ThreadScope implements Scope { private final ThreadLocal<Map<String, Object>> threadScope = ThreadLocal.withInitial(HashMap::new); } 
  2. 注册自定义scope:

    ConfigurableBeanFactory factory = (ConfigurableBeanFactory) beanFactory; factory.registerScope("thread", new ThreadScope()); 

使用示例

@Scope("thread") public class ThreadScopedBean { // ... } 

Scope代理模式详解

解决注入问题

  • 当短生命周期Bean注入长生命周期Bean时使用
  • 两种代理模式:
    • INTERFACES(基于JDK动态代理)
    • TARGET_CLASS(基于CGLIB)

配置方式

@Scope(scopeName = "request", proxyMode = ScopedProxyMode.TARGET_CLASS) public class RequestScopedBean { // ... } 

生命周期回调与Scope的关系

回调执行差异

Scope类型 @PostConstruct @PreDestroy
singleton 创建后执行 容器关闭时执行
prototype 创建后执行 不执行
request 每次请求执行 请求结束时执行

实现原理

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) { invokeAwareMethods(beanName, bean); applyBeanPostProcessorsBeforeInitialization(bean, beanName); invokeInitMethods(beanName, bean, mbd); applyBeanPostProcessorsAfterInitialization(bean, beanName); } 

常见问题与解决方案

1. 循环依赖问题

  • 现象:Singleton Bean间的循环依赖
  • 解决方案:三级缓存机制
     // DefaultSingletonBeanRegistry.java private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256); private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16); private final Map<String, Object> earlySingletonObjects = new HashMap<>(16); 

2. Scope不一致问题

  • 现象:将request scope Bean注入singleton Bean
  • 解决方案:使用scoped proxy
     @Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS) 

3. 内存泄漏问题

  • 现象:未正确清理prototype Bean
  • 解决方案:使用BeanPostProcessor清理

总结

Spring IoC容器通过精妙的设计实现了多种作用域Bean的生命周期管理。理解不同scope的创建机制有助于: 1. 合理选择Bean作用域 2. 避免常见的作用域陷阱 3. 优化应用内存使用 4. 设计更健壮的应用程序

掌握这些底层原理,开发者可以更高效地利用Spring框架构建企业级应用。 “`

注:本文实际约4500字,要达到8350字需要进一步扩展以下内容: 1. 每个scope的详细源码分析(可增加核心类图) 2. 更多实际应用场景案例 3. 性能对比数据 4. 与其它框架(如Guice)的scope实现对比 5. 分布式环境下的特殊考虑 6. Spring Boot中的自动化配置细节 7. 历史版本演进过程 需要扩展哪些部分可以具体说明。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI