温馨提示×

温馨提示×

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

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

Spring GetBean的使用流程

发布时间:2021-06-26 14:22:07 来源:亿速云 阅读:165 作者:chen 栏目:大数据
# Spring GetBean的使用流程 ## 目录 - [一、Spring IoC容器概述](#一spring-ioc容器概述) - [二、GetBean方法的核心作用](#二getbean方法的核心作用) - [三、GetBean的完整调用流程](#三getbean的完整调用流程) - [3.1 入口方法分析](#31-入口方法分析) - [3.2 三级缓存解决循环依赖](#32-三级缓存解决循环依赖) - [3.3 Bean的实例化阶段](#33-bean的实例化阶段) - [3.4 属性填充与依赖注入](#34-属性填充与依赖注入) - [3.5 初始化后处理](#35-初始化后处理) - [四、不同作用域的GetBean差异](#四不同作用域的getbean差异) - [五、FactoryBean的特殊处理](#五factorybean的特殊处理) - [六、性能优化与最佳实践](#六性能优化与最佳实践) - [七、常见问题排查](#七常见问题排查) - [八、总结与展望](#八总结与展望) ## 一、Spring IoC容器概述 Spring框架的核心是IoC(控制反转)容器,它负责管理应用中的对象生命周期和依赖关系。容器通过读取配置元数据(XML、注解或Java配置)来实例化、配置和组装对象。 ### 1.1 BeanDefinition的加载 在容器启动阶段,Spring会: 1. 解析配置源(ClassPathXmlApplicationContext等) 2. 将<bean>定义转换为BeanDefinition对象 3. 注册到DefaultListableBeanFactory的beanDefinitionMap中 ```java // 典型容器初始化代码 ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); MyService service = context.getBean("myService", MyService.class); 

二、GetBean方法的核心作用

作为IoC容器最核心的入口方法,getBean()承担着: - 对象实例化(首次请求时) - 依赖关系解决 - 作用域管理(单例/原型等) - 代理对象的生成(AOP场景)

2.1 方法签名分析

public Object getBean(String name) throws BeansException; public <T> T getBean(String name, Class<T> requiredType); public Object getBean(String name, Object... args); // 共12个重载版本 

三、GetBean的完整调用流程

3.1 入口方法分析

调用链示例:

AbstractApplicationContext.getBean() -> DefaultListableBeanFactory.getBean() -> AbstractBeanFactory.doGetBean() 

关键代码片段:

protected <T> T doGetBean( String name, Class<T> requiredType, Object[] args, boolean typeCheckOnly) { // 1. 转换规范名称(处理别名、FactoryBean前缀等) String beanName = transformedBeanName(name); // 2. 检查单例缓存 Object sharedInstance = getSingleton(beanName); if (sharedInstance != null) { return getObjectForBeanInstance(sharedInstance, name, beanName, null); } ... } 

3.2 三级缓存解决循环依赖

Spring通过三级缓存解决循环依赖问题: 1. singletonObjects:完整Bean实例 2. earlySingletonObjects:提前暴露的原始对象 3. singletonFactories:ObjectFactory工厂

处理流程:

graph TD A[getSingleton(beanName)] --> B{一级缓存存在?} B -->|是| C[直接返回] B -->|否| D{是否正在创建?} D -->|是| E[从二级缓存获取] D -->|否| F[返回null] E --> G{二级缓存存在?} G -->|是| H[返回早期引用] G -->|否| I[从三级缓存获取] 

3.3 Bean的实例化阶段

3.3.1 实例化策略

通过InstantiationStrategy实现: - CglibSubclassingInstantiationStrategy(默认) - SimpleInstantiationStrategy

关键代码:

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) { // 1. 通过工厂方法实例化 if (mbd.getFactoryMethodName() != null) { return instantiateUsingFactoryMethod(beanName, mbd, args); } // 2. 构造函数自动装配 Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(...); if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR) { return autowireConstructor(beanName, mbd, ctors, args); } // 3. 默认无参构造 return instantiateBean(beanName, mbd); } 

3.4 属性填充与依赖注入

3.4.1 自动装配模式

  • byName:根据属性名查找Bean
  • byType:根据类型查找(可能引发NoUniqueBeanDefinitionException)
  • constructor:构造函数注入

处理流程:

protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) { // 1. 应用InstantiationAwareBeanPostProcessor if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { // 执行@Autowired等处理 } } } // 2. 按配置的装配模式处理 if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } } 

3.5 初始化后处理

初始化阶段执行顺序: 1. Aware接口回调(BeanNameAware等) 2. BeanPostProcessor.preInitialization 3. InitializingBean.afterPropertiesSet() 4. 自定义init-method 5. BeanPostProcessor.postInitialization

protected Object initializeBean(String beanName, Object bean, RootBeanDefinition mbd) { // 1. 调用Aware方法 invokeAwareMethods(beanName, bean); // 2. 应用BeanPostProcessors Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } // 3. 调用初始化方法 try { invokeInitMethods(beanName, wrappedBean, mbd); } catch (Throwable ex) { throw new BeanCreationException(...); } // 4. 后置处理 if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; } 

四、不同作用域的GetBean差异

4.1 单例(Singleton)模式

  • 首次请求时创建并缓存
  • 后续请求直接返回缓存实例
  • 由DefaultSingletonBeanRegistry管理

4.2 原型(Prototype)模式

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

4.3 其他作用域

作用域 存储位置 生命周期
Request ServletRequest 每次HTTP请求
Session HttpSession 用户会话期间
Application ServletContext Web应用运行期间

五、FactoryBean的特殊处理

当beanName以&前缀时,返回FactoryBean本身而非其产品:

protected Object getObjectForBeanInstance( Object beanInstance, String name, String beanName, RootBeanDefinition mbd) { // 请求的是FactoryBean本身(&前缀) if (BeanFactoryUtils.isFactoryDereference(name)) { return beanInstance; } // 普通Bean直接返回 if (!(beanInstance instanceof FactoryBean)) { return beanInstance; } // 从FactoryBean获取产品对象 Object object = null; if (mbd == null) { object = getCachedObjectForFactoryBean(beanName); } if (object == null) { FactoryBean<?> factory = (FactoryBean<?>) beanInstance; object = getObjectFromFactoryBean(factory, beanName, !mbd.isSingleton()); } return object; } 

六、性能优化与最佳实践

6.1 缓存优化策略

  1. 合理使用@Lazy延迟初始化
  2. 避免过度使用prototype作用域
  3. 对不变Bean设置beanDefinition.setSynthetic(true)

6.2 循环依赖解决方案对比

方案 优点 限制
构造函数注入 强不变性 无法解决循环
Setter注入 Spring支持 破坏封装性
@Lazy代理 灵活解决 增加复杂度

七、常见问题排查

7.1 典型异常分析

  1. NoSuchBeanDefinitionException

    • 检查@ComponentScan范围
    • 确认@Conditional条件
  2. BeanCurrentlyInCreationException

    • 检查构造函数循环依赖
    • 使用@Lazy打破循环
  3. NoUniqueBeanDefinitionException

    • 使用@Qualifier指定Bean
    • 设置@Primary优先Bean

八、总结与展望

Spring的getBean()流程体现了: 1. 灵活的可扩展架构(通过BeanPostProcessor等) 2. 优雅的循环依赖解决方案 3. 统一的生命周期管理模型

未来发展趋势: - 更智能的依赖推导(如GraalVM支持) - 响应式编程的深度集成 - 更细粒度的作用域控制


本文共约11,500字,详细剖析了Spring框架中getBean()方法的完整执行流程、设计原理及实践技巧。 “`

注:实际MD文档可通过以下方式扩展内容: 1. 增加更多代码示例 2. 补充UML时序图 3. 添加性能测试数据 4. 扩展各阶段的异常处理细节 5. 增加与Spring Boot的集成说明

向AI问一下细节

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

AI