文章目录
- Bean
-
- 一、核心定义与体系边界
-
- [1.1 Bean的本质定义](#1.1 Bean的本质定义)
- [1.2 核心体系分支与边界划分](#1.2 核心体系分支与边界划分)
- [1.3 相关JSR标准规范](#1.3 相关JSR标准规范)
- 二、Java原生Bean(JavaBean)规范体系
-
- [2.1 核心规范约束](#2.1 核心规范约束)
- [2.2 核心API与组件](#2.2 核心API与组件)
- [2.3 分类与应用场景](#2.3 分类与应用场景)
- [三、Spring Bean 核心体系(行业主流)](#三、Spring Bean 核心体系(行业主流))
-
- [3.1 与JavaBean的核心异同](#3.1 与JavaBean的核心异同)
- [3.2 Bean的核心元数据:BeanDefinition](#3.2 Bean的核心元数据:BeanDefinition)
-
- [3.2.1 核心属性](#3.2.1 核心属性)
- [3.2.2 核心实现类](#3.2.2 核心实现类)
- [3.3 Bean的定义与注册方式](#3.3 Bean的定义与注册方式)
- [3.4 Bean的作用域(Scope)](#3.4 Bean的作用域(Scope))
-
- [3.4.1 Spring Core 内置作用域](#3.4.1 Spring Core 内置作用域)
- [3.4.2 Web环境专属作用域(Spring Web)](#3.4.2 Web环境专属作用域(Spring Web))
- [3.4.3 自定义作用域](#3.4.3 自定义作用域)
- [3.5 Bean的完整生命周期与扩展点体系](#3.5 Bean的完整生命周期与扩展点体系)
-
- 阶段1:Bean实例化(Instantiation)
- [阶段2:属性赋值(Populate)- 依赖注入DI核心阶段](#阶段2:属性赋值(Populate)- 依赖注入DI核心阶段)
- 阶段3:Bean初始化(Initialization)
- [阶段4:就绪使用(Ready to Use)](#阶段4:就绪使用(Ready to Use))
- 阶段5:Bean销毁(Destruction)
- 核心扩展点体系总览
- [3.6 依赖注入(DI)核心机制](#3.6 依赖注入(DI)核心机制)
-
- [3.6.1 核心注入方式](#3.6.1 核心注入方式)
- [3.6.2 自动装配模式](#3.6.2 自动装配模式)
- [3.6.3 依赖冲突解决方案](#3.6.3 依赖冲突解决方案)
- [3.7 核心高级特性](#3.7 核心高级特性)
- [3.8 循环依赖解决方案](#3.8 循环依赖解决方案)
-
- [3.8.1 核心解决方案:三级缓存](#3.8.1 核心解决方案:三级缓存)
- [3.8.2 执行流程(A依赖B,B依赖A)](#3.8.2 执行流程(A依赖B,B依赖A))
- [3.8.3 无法解决的循环依赖场景](#3.8.3 无法解决的循环依赖场景)
- [四、Spring Boot 对Bean体系的增强](#四、Spring Boot 对Bean体系的增强)
- 五、其他生态中的Bean体系
- 六、常见问题与避坑指南
- 七、行业最佳实践与编码规范
-
- [7.1 编码规范](#7.1 编码规范)
- [7.2 配置规范](#7.2 配置规范)
- [7.3 性能与可维护性规范](#7.3 性能与可维护性规范)
Bean
本文以Java生态为核心,从基础规范、核心实现、高级特性、工程实践四大维度,完整构建Bean的知识体系,厘清Java原生Bean与Spring Bean的边界,覆盖从入门到原理级的全链路知识点。
一、核心定义与体系边界
1.1 Bean的本质定义
Bean是Java语言中可复用、可组件化、可被容器管理的标准化Java对象 ,是Java面向对象编程中组件化、模块化开发的核心原子单元,核心价值是解耦对象的创建、依赖管理与业务逻辑,实现代码的高内聚、低耦合。
1.2 核心体系分支与边界划分
Bean体系分为三大核心分支,边界清晰,不可混淆:
| 分支类型 | 核心定位 | 管理主体 | 主流应用场景 |
|---|---|---|---|
| JavaBean(原生规范) | Java官方定义的对象标准化规范 | 开发者手动管理 | DTO/VO/Entity数据模型、序列化传输、UI组件 |
| Spring Bean | Spring IoC容器管理的对象核心模型 | Spring IoC容器全生命周期管理 | 企业级Java开发、Spring全家桶应用 |
| 企业级Bean(EJB/Jakarta Bean) | Java EE/Jakarta EE定义的分布式组件规范 | 应用服务器(WebLogic/JBoss等) | 传统分布式Java EE项目(现已基本被Spring替代) |
1.3 相关JSR标准规范
Bean体系的底层遵循Java官方标准化规范,核心包括:
- JSR 54:JavaBeans 1.01规范,JavaBean的原生标准定义
- JSR 250 :Java平台通用注解规范,定义
@PostConstruct/@PreDestroy/@Resource等生命周期与注入注解(Spring 6+/Spring Boot 3+已迁移至jakarta.annotation包) - JSR 330 :Java依赖注入规范,定义
@Inject/@Named/@Singleton等标准化DI注解,Spring原生兼容 - JSR 317/338:JPA规范,定义持久化实体Bean的标准
二、Java原生Bean(JavaBean)规范体系
JavaBean是所有Bean体系的基础,Spring Bean是对其的扩展与重构,而非完全替代。
2.1 核心规范约束
符合JavaBean规范的类,必须满足以下核心规则:
- 必须是
public修饰的顶级类,提供public无参构造方法(默认构造器),支持反射实例化 - 成员属性私有化(
private修饰),对外提供符合命名规范的getter/setter方法:- 普通属性:
getXxx()/setXxx() - 布尔类型属性:支持
isXxx()替代getXxx()
- 普通属性:
- 支持序列化:实现
java.io.Serializable接口(规范推荐,用于持久化与网络传输) - 支持事件机制:可绑定属性变更监听器
PropertyChangeListener,实现事件驱动 - 支持自定义扩展:通过
BeanInfo、PropertyEditor实现属性自定义编辑与元数据描述
2.2 核心API与组件
JavaBean的核心能力由java.beans包提供,核心组件包括:
Introspector:内省器,核心工具类,用于解析JavaBean的属性、方法、事件等元数据BeanInfo:JavaBean的元数据接口,描述Bean的完整信息PropertyDescriptor:属性描述符,封装单个属性的getter/setter方法与元数据PropertyEditor:属性编辑器接口,实现属性类型的自定义转换PropertyChangeSupport:属性变更事件的工具类,简化事件监听的实现
2.3 分类与应用场景
- 简单JavaBean(POJO) :无业务逻辑,仅包含属性与getter/setter,是最常用的类型,典型场景:
- 数据传输:DTO/VO/BO等分层数据模型
- ORM映射:JPA/MyBatis的数据库实体类
- 配置封装:配置文件的属性映射类
- 复杂JavaBean :包含业务逻辑、事件处理、自定义扩展,典型场景:
- Swing/JavaFX的UI组件
- 可视化开发工具的可拖拽组件
- 带状态与事件处理的业务组件
三、Spring Bean 核心体系(行业主流)
Spring Bean是Spring生态的核心基石,是由Spring IoC容器实例化、组装、管理全生命周期的Java对象,不强制遵循JavaBean原生规范,核心解决企业级开发中对象的依赖管理、解耦与扩展问题。
3.1 与JavaBean的核心异同
| 对比维度 | JavaBean | Spring Bean |
|---|---|---|
| 规范约束 | 必须严格遵循JavaBean规范 | 无强制规范,可无getter/setter、可使用有参构造器 |
| 生命周期 | 开发者手动创建与销毁 | 由Spring IoC容器统一管理全生命周期 |
| 实例化 | 手动new/反射实例化 | 容器基于BeanDefinition反射/工厂模式实例化 |
| 依赖管理 | 手动组装依赖 | 容器自动完成依赖注入(DI) |
| 作用域 | 无内置作用域,由开发者控制 | 内置Singleton/Prototype等6种作用域,支持自定义 |
| 扩展能力 | 有限的事件与属性编辑扩展 | 提供数十个生命周期扩展点,支持无限定制 |
3.2 Bean的核心元数据:BeanDefinition
BeanDefinition是Spring Bean的设计图纸,Spring容器基于该元数据完成Bean的创建与管理,是Spring Bean体系的核心底层。
3.2.1 核心属性
| 属性名 | 核心作用 |
|---|---|
beanClass |
Bean的全限定类名,定义实例化的目标类 |
scope |
Bean的作用域,默认Singleton |
lazyInit |
是否懒加载,默认false(容器启动时实例化) |
initMethodName/destroyMethodName |
自定义初始化/销毁回调方法名 |
constructorArgumentValues |
构造器注入的参数值 |
propertyValues |
属性注入的参数值 |
autowireMode |
自动装配模式(no/byName/byType/constructor) |
dependsOn |
Bean的依赖前置,指定先实例化的Bean |
primary |
是否为同类型首选Bean,解决依赖冲突 |
abstract |
是否为抽象Bean,仅作为配置模板,不实例化 |
factoryBeanName/factoryMethodName |
工厂Bean与工厂方法,用于自定义实例化逻辑 |
3.2.2 核心实现类
GenericBeanDefinition:通用BeanDefinition,日常开发中注解/XML配置生成的默认类型AnnotatedGenericBeanDefinition:注解配置的BeanDefinition,承载注解元数据(@Configuration/@Bean)RootBeanDefinition:合并后的BeanDefinition,容器实例化前的最终模板,可作为父Bean模板ChildBeanDefinition:子BeanDefinition,继承父Bean的配置,实现配置复用
3.3 Bean的定义与注册方式
Spring提供了从入门到高级的全场景Bean定义方式,支持灵活的配置与扩展:
-
XML配置方式 (传统方式)
通过<bean>标签在XML文件中定义Bean,配置全量元数据,示例:xml<bean id="userService" class="com.xxx.UserService" scope="singleton" init-method="init" destroy-method="destroy"> <property name="userDao" ref="userDao"/> </bean> -
注解扫描方式 (主流开发方式)
通过类级别注解标记Bean,配合@ComponentScan自动扫描注册,核心注解:- 基础注解:
@Component - 分层衍生注解:
@Controller/@Service/@Repository/@Configuration
- 基础注解:
-
JavaConfig配置类方式 (全注解推荐方式)
通过@Configuration配置类+@Bean方法级注解定义Bean,替代XML,支持复杂配置:java@Configuration public class AppConfig { @Bean(initMethod = "init", destroyMethod = "destroy") public UserService userService(UserDao userDao) { return new UserService(userDao); } } -
条件化注册方式
通过@Conditional系列注解,满足指定条件才注册Bean,是Spring Boot自动配置的核心:- 基础注解:
@Conditional(自定义条件) - Spring Boot扩展:
@ConditionalOnClass/@ConditionalOnMissingBean/@ConditionalOnProperty等
- 基础注解:
-
高级动态注册方式
用于框架开发与底层扩展,在容器启动过程中动态注册Bean:@Import:直接导入配置类/Bean类,实现Bean的批量注册ImportBeanDefinitionRegistrar:手动注册BeanDefinition,实现自定义注册逻辑BeanDefinitionRegistryPostProcessor:容器启动的最早期扩展,修改/新增BeanDefinition
3.4 Bean的作用域(Scope)
Spring为Bean定义了明确的生命周期作用域,控制Bean的实例创建时机与存活范围,核心分为两大类:
3.4.1 Spring Core 内置作用域
- singleton(单例,默认)
- 特性:整个IoC容器中仅创建一个实例,容器启动时完成实例化(非懒加载),全程复用
- 适用场景:无状态的业务组件(
@Service/@Repository),无共享可变状态,线程安全
- prototype(原型)
- 特性:每次依赖注入/调用
getBean()时,创建一个全新的实例 - 关键限制:容器仅负责实例化,不管理销毁生命周期,
destroy-method不会自动执行 - 适用场景:有状态的业务对象,每次使用需要独立状态的组件
- 特性:每次依赖注入/调用
3.4.2 Web环境专属作用域(Spring Web)
需配合WebApplicationContext使用,仅在Web应用中生效:
| 作用域 | 生命周期范围 | 适用场景 |
|---|---|---|
| request | 单次HTTP请求内,请求结束销毁 | 单次请求内的共享数据对象 |
| session | 单个HTTP Session生命周期内,会话过期销毁 | 用户会话级别的数据对象 |
| application | 整个ServletContext生命周期内,与Web应用同生共死 |
应用全局的配置对象 |
| websocket | 单个WebSocket连接生命周期内 | WebSocket会话的专属对象 |
3.4.3 自定义作用域
实现org.springframework.beans.factory.config.Scope接口,注册到容器中,即可自定义作用域,典型案例:Spring Cloud的@RefreshScope(配置刷新作用域)。
3.5 Bean的完整生命周期与扩展点体系
Spring Bean的生命周期是体系的核心重难点,全流程分为5大核心阶段,内置数十个扩展点,支持全流程定制,执行顺序严格固定:
阶段1:Bean实例化(Instantiation)
容器基于BeanDefinition,创建Bean的原生对象(属性未赋值,未初始化)
- 容器启动,解析并合并BeanDefinition,定位Bean的Class
- 执行扩展点:
InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()- 实例化前执行,可直接返回代理对象,短路后续所有实例化流程
- 推断构造方法,通过反射调用构造器,完成Bean的实例化
- 执行扩展点:
InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()- 实例化后执行,返回false会跳过后续属性赋值流程
阶段2:属性赋值(Populate)- 依赖注入DI核心阶段
完成Bean的属性填充与依赖注入,解决Bean之间的依赖关系
- 执行扩展点:
InstantiationAwareBeanPostProcessor.postProcessProperties()- 处理属性值,
@Autowired/@Value/@Resource注解的注入逻辑在此处执行
- 处理属性值,
- 按照BeanDefinition配置,完成依赖注入:构造器注入、setter注入、字段注入
- 执行Aware接口第一组(容器基础信息注入) ,执行顺序固定:
BeanNameAware.setBeanName():注入当前Bean的名称BeanClassLoaderAware.setBeanClassLoader():注入加载Bean的类加载器BeanFactoryAware.setBeanFactory():注入当前BeanFactory容器
阶段3:Bean初始化(Initialization)
完成Bean的初始化配置、代理增强,生成最终可用的Bean对象
- 执行Aware接口第二组(ApplicationContext环境信息注入) ,执行顺序固定:
EnvironmentAware.setEnvironment():注入环境配置对象EmbeddedValueResolverAware.setEmbeddedValueResolver():注入占位符解析器ResourceLoaderAware.setResourceLoader():注入资源加载器ApplicationEventPublisherAware.setApplicationEventPublisher():注入事件发布器MessageSourceAware.setMessageSource():注入国际化组件ApplicationContextAware.setApplicationContext():注入ApplicationContext上下文
- 执行扩展点:
BeanPostProcessor.postProcessBeforeInitialization()- 初始化方法前执行,
@PostConstruct注解的生命周期方法在此处执行
- 初始化方法前执行,
- 执行初始化核心回调 ,执行顺序固定:
- 实现
InitializingBean接口的afterPropertiesSet()方法 - 执行自定义的
init-method方法(XML/@Bean注解配置)
- 实现
- 执行扩展点:
BeanPostProcessor.postProcessAfterInitialization()- 初始化方法后执行,AOP动态代理的核心入口,返回代理对象替换原生Bean
阶段4:就绪使用(Ready to Use)
Bean已完成全流程初始化,成为完整的代理对象,驻留在Spring容器的单例池中,供应用程序调用。
阶段5:Bean销毁(Destruction)
容器关闭时触发,完成Bean的资源释放与销毁
- 容器调用
ApplicationContext.close(),触发销毁流程 - 执行销毁核心回调 ,执行顺序固定:
@PreDestroy注解标注的方法- 实现
DisposableBean接口的destroy()方法 - 执行自定义的
destroy-method方法(XML/@Bean注解配置)
- 完成Bean的销毁,容器关闭
核心扩展点体系总览
Spring的扩展能力核心基于BeanPostProcessor体系,是框架定制的核心入口:
| 扩展接口 | 核心作用 | 执行阶段 |
|---|---|---|
BeanPostProcessor |
顶级扩展接口,初始化前后的全局定制 | 初始化阶段 |
InstantiationAwareBeanPostProcessor |
实例化前后的定制,可干预属性注入 | 实例化+属性赋值阶段 |
MergedBeanDefinitionPostProcessor |
BeanDefinition合并后的定制,解析注解元数据 | 实例化前 |
DestructionAwareBeanPostProcessor |
销毁前的定制,干预销毁流程 | 销毁阶段 |
BeanFactoryPostProcessor |
容器启动早期,修改BeanDefinition配置 | Bean实例化前 |
BeanDefinitionRegistryPostProcessor |
最早期扩展,动态注册/修改BeanDefinition | BeanDefinition加载后,实例化前 |
3.6 依赖注入(DI)核心机制
依赖注入是Spring Bean的核心能力,解决对象之间的依赖耦合问题,核心机制如下:
3.6.1 核心注入方式
| 注入方式 | 实现方式 | 优势 | 劣势 | 推荐等级 |
|---|---|---|---|---|
| 构造器注入 | 构造方法参数注入,Spring 4.3+单构造器可省略@Autowired |
强制依赖不可变、编译期校验、无循环依赖隐患、完全脱离Spring容器可测试 | 依赖过多时构造器臃肿 | ⭐⭐⭐⭐⭐ 官方推荐 |
| setter注入 | setter方法注入,配合@Autowired |
可选依赖灵活、支持循环依赖、可重新注入 | 依赖不可变、可能出现空指针 | ⭐⭐⭐⭐ 可选依赖场景 |
| 字段注入 | 直接在成员字段上加@Autowired/@Resource |
代码简洁、开发便捷 | 强耦合Spring容器、无法单元测试、依赖不可变、隐藏代码复杂度 | ⭐⭐ 不推荐生产使用 |
| 方法注入 | 普通方法上加@Autowired |
批量注入多个依赖、支持动态注入 | 可读性差、使用场景有限 | ⭐⭐ 特殊场景使用 |
3.6.2 自动装配模式
no:默认值,不自动装配,手动通过ref指定依赖byName:按属性名称匹配Bean的名称,自动注入byType:按属性的类型匹配Bean,同类型多个Bean时抛出异常constructor:按构造器参数的类型匹配,用于构造器注入
3.6.3 依赖冲突解决方案
当容器中存在多个同类型的Bean时,会抛出NoUniqueBeanDefinitionException,解决方案:
@Primary:标记首选Bean,同类型匹配时优先注入@Qualifier:按Bean名称精准指定注入的Bean,解决多实例冲突@Priority:按优先级排序,数值越小优先级越高@Conditional:条件化注册Bean,控制同类型Bean的注册逻辑
3.7 核心高级特性
-
FactoryBean 工厂Bean
特殊的Bean,用于创建复杂对象,实现
FactoryBean接口,核心方法:getObject():返回工厂创建的目标对象(容器中默认暴露的Bean)getObjectType():返回目标对象的类型isSingleton():是否为单例
核心区别:BeanFactory是Spring容器的顶级接口,是Bean的工厂;FactoryBean是创建对象的特殊Bean,是对象的工厂。
典型应用:MyBatis的SqlSessionFactoryBean、Feign的FeignClientFactoryBean。
-
懒加载
@Lazy延迟Bean的实例化时机,从容器启动时延迟到第一次使用时才实例化,核心作用:
- 减少容器启动时间,优化启动性能
- 解决循环依赖问题
- 解决启动时的依赖缺失问题
注意:被非懒加载的单例Bean依赖时,懒加载会失效,Bean会提前实例化。
-
Bean的继承与抽象Bean
- 抽象Bean:
abstract="true",仅作为配置模板,不会被实例化,用于提取公共配置 - 子Bean:通过
parent属性继承父Bean的配置,可覆盖属性,减少重复配置
- 抽象Bean:
-
Bean别名机制
为Bean定义多个名称,通过XML的
<alias>标签、@Bean的name属性、@Qualifier注解实现,适用于多模块引用、兼容旧版本、多实例区分场景。 -
事件驱动模型
Bean可实现
ApplicationListener接口,监听容器事件,也可通过@EventListener注解实现事件监听,实现业务解耦。
3.8 循环依赖解决方案
循环依赖指两个或多个Bean之间相互依赖,形成闭环(如A依赖B,B依赖A),是Spring Bean体系的高频重难点。
3.8.1 核心解决方案:三级缓存
Spring通过三级单例缓存解决单例Bean的setter注入循环依赖,三级缓存定义:
| 缓存层级 | 缓存名称 | 存储内容 | 核心作用 |
|---|---|---|---|
| 一级缓存 | singletonObjects |
完全初始化完成的单例Bean | 存放最终可用的Bean,对外暴露 |
| 二级缓存 | earlySingletonObjects |
实例化完成、未初始化的原生Bean | 提前曝光半成品Bean,解决循环依赖 |
| 三级缓存 | singletonFactories |
Bean的ObjectFactory工厂对象 |
生成AOP代理对象,解决代理后的循环依赖 |
3.8.2 执行流程(A依赖B,B依赖A)
- 实例化A,将A的ObjectFactory放入三级缓存,提前曝光
- 为A注入属性B,发现B未实例化,开始实例化B
- 实例化B,将B的ObjectFactory放入三级缓存
- 为B注入属性A,从三级缓存获取A的ObjectFactory,生成A的对象(原生/代理),放入二级缓存,移除三级缓存,注入A到B
- B完成初始化,放入一级缓存,移除二级、三级缓存
- A完成属性注入与初始化,放入一级缓存,移除二级缓存,循环依赖解决
3.8.3 无法解决的循环依赖场景
- 构造器注入形成的循环依赖(无提前曝光的实例)
- prototype作用域的Bean循环依赖(容器不缓存原型Bean)
@Async/@Transactional代理后的循环依赖(代理时机与三级缓存不匹配)- 懒加载失效导致的循环依赖
四、Spring Boot 对Bean体系的增强
Spring Boot在Spring Bean的基础上,做了大量工程化增强,实现Bean的开箱即用,核心特性:
- 自动装配机制
基于SPI机制,通过META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件,自动加载配置类,完成Bean的自动注册,无需手动配置。 - 条件化自动配置
扩展大量@Conditional派生注解,实现Bean的按需注册,是自动配置的核心:@ConditionalOnClass:类路径存在指定类时注册Bean@ConditionalOnMissingBean:容器中无指定Bean时才注册@ConditionalOnProperty:配置文件中指定属性匹配时注册
- 配置属性绑定
通过@ConfigurationProperties+@EnableConfigurationProperties,将配置文件(application.yml)中的属性自动绑定到Bean,实现配置与代码的解耦。 - Starter组件机制
封装Bean的自动配置、依赖管理,实现第三方组件的开箱即用,开发者只需引入Starter,无需手动配置Bean。 - Bean加载顺序控制
提供@Order、@AutoConfigureOrder、@AutoConfigureBefore、@AutoConfigureAfter注解,精准控制配置类与Bean的加载顺序,解决依赖顺序问题。 - Bean的Actuator监控
提供beans端点,可实时查看容器中所有Bean的元数据、依赖关系、作用域,方便问题排查。
五、其他生态中的Bean体系
-
EJB(Enterprise JavaBean)
Java EE官方定义的分布式企业级Bean规范,分为三大类:
- 会话Bean:Stateless(无状态)/Stateful(有状态),处理业务逻辑
- 实体Bean:持久化数据对象,现已被JPA替代
- 消息驱动Bean(MDB):基于JMS的异步消息处理组件
现状:随着Spring生态的崛起,EJB已基本退出主流市场,仅在传统Java EE项目中使用。
-
Jakarta EE Bean
EJB的演进版本,Java EE移交Eclipse基金会后,更名为Jakarta EE,包名从
javax.ejb迁移至jakarta.ejb,适配云原生场景。 -
第三方框架的Bean扩展
- MyBatis:Mapper Bean,通过MapperFactoryBean创建Mapper代理对象,交给Spring容器管理
- Quartz:JobBean,将定时任务Job交给Spring容器管理,支持依赖注入
- Spring Cloud:微服务场景的各类扩展Bean,如
@FeignClient生成的代理Bean、网关过滤器Bean等
六、常见问题与避坑指南
- 注入的Bean为null
高频原因:- 对象通过
new手动创建,未交给Spring容器管理 - 静态字段/静态方法注入,Spring不支持静态成员注入
- Bean加载顺序问题,依赖的Bean未完成初始化
- 循环依赖导致的代理对象提前曝光,注入了未初始化的Bean
- 对象通过
@Transactional/@Async注解失效
核心原因:Bean内部方法调用,未走AOP代理对象,只有外部调用才会触发切面逻辑- Bean生命周期回调不执行
高频原因:- Prototype作用域的Bean,容器不管理销毁生命周期,destroy方法不执行
- 回调方法非public、带参数、静态方法
- Bean未被Spring容器管理,手动new的对象
- Bean重复注册与覆盖
Spring Boot 2.1+默认禁用Bean覆盖,同名称Bean注册会抛出异常,解决方案:- 规范Bean命名,避免名称冲突
- 配置
spring.main.allow-bean-definition-overriding=true开启覆盖
- 单例Bean线程安全问题
单例Bean本身不是线程不安全的,有状态的单例Bean才会有线程安全问题 :- 无状态Bean(无共享可变成员变量):天然线程安全
- 有状态Bean(存在共享可变成员变量):多线程并发修改会出现线程安全问题,需通过锁、ThreadLocal解决
- 懒加载失效
核心原因:懒加载的Bean被非懒加载的单例Bean依赖,容器启动时会提前实例化依赖的Bean,导致懒加载失效。
七、行业最佳实践与编码规范
7.1 编码规范
- 优先使用构造器注入,强制依赖用构造器保证不可变,可选依赖用setter注入,禁止生产环境使用字段注入
- 单例Bean优先设计为无状态,避免共享可变成员变量,天然保证线程安全
- 生命周期回调优先使用JSR-250规范的
@PostConstruct/@PreDestroy,避免耦合Spring的InitializingBean/DisposableBean接口 - POJO类遵循JavaBean规范,提供标准getter/setter,序列化场景实现
Serializable接口,指定serialVersionUID - 合理拆分Bean,遵循单一职责原则,避免单个Bean代码臃肿、职责过多
- 避免循环依赖,通过代码分层、职责拆分、接口隔离从根源解决循环依赖问题
7.2 配置规范
- 优先使用JavaConfig全注解配置,替代XML配置,保证配置的类型安全与可读性
- 使用
@ConfigurationProperties做配置绑定,禁止硬编码配置项,配置与代码解耦 - 合理使用
@Conditional注解,控制Bean的注册条件,避免无效Bean加载 - 明确Bean的作用域,禁止滥用prototype作用域,默认使用singleton单例
- 规范Bean命名,遵循驼峰命名法,见名知意,避免名称冲突
- 复杂Bean的创建逻辑,使用
FactoryBean封装,隔离复杂实例化逻辑
7.3 性能与可维护性规范
- 合理使用懒加载,对非核心路径、启动耗时的Bean开启懒加载,优化应用启动速度
- 避免在Bean的初始化/销毁方法中执行耗时操作,阻塞容器启动与关闭
- 禁止在Bean的构造器中执行复杂业务逻辑,构造器仅用于依赖注入与基础属性赋值
- 扩展Spring时,优先使用BeanPostProcessor体系,避免硬编码修改容器核心逻辑
- 生产环境开启Actuator的Bean监控端点,方便问题排查与容器状态监控