《Spring实战 第四版》Bean
本文最后更新于 2025年9月13日 下午
在讲Spring Bean之前,我们先来讲讲简单的JavaBean
JavaBean
JavaBean简单来说就是一种符合特定规范的普通Java类:
1 | |
其中的核心特征有:
- 有无参构造器
- 字段都是私有的
- 提供public的属性:getter/setter
- 只有getter的属性称为只读属性
- 只有setter的属性称为只写属性(For what?!)
- 遵循命名规范
- 可序列化(可选)
对于boolean字段,其读方法一般被命名为isXyz()。这里可以引出一个很经典的面试问题:
为什么boolean字段的命名通常不允许以is开头?
- 对程序自动生成的属性来说,如果一个boolean字段以is开头,便会出现一些非常奇怪的命名
isIsXyz() - 许多序列化的框架(Jackson, Gson等)都依赖JavaBean规范
- 对于某些框架来说(Spring, Hibernate),使用反射访问字段时容易出现问题。
JavaBean的主要目的是为了设立一种规范以自动化地完成一系列任务。比如:
- 数据传输,更方便序列化
- 便于分析以自动生成属性代码
- 轻松的图形可视化设计
在了解了JavaBean后,我们可以介绍一下Spring Bean了。
Spring Bean
Spring Bean是否Spring IoC容器创建,组装和管理的对象。也就是说,当你定义一个类时在上面加了与Spring Bean相关的注解,这个对象就会被视为是一个Spring Bean。
1 | |
这个UserService便是一个Spring Bean,因为其被@Component注解修饰了。
当一个类成为Spring Bean,它有了如下特性:
- 由IoC容器(Spring 容器)管理生命周期
- 支持依赖注入
- 支持AOP编程
- 支持各种作用域(singleton, prototype等)
Spring容器(IoC容器)
Spring容器(IoC容器,往后我就叫IoC容器了,大伙听这个听得比较多)是Spring框架的核心。它用于创建,管理相互协作的组件之间的关联。
Spring中有多个IoC容器的实现:
- bean工厂(
org.springframework.beans.factory.beanFactory接口定义) - 应用上下文(
org.springframework.context.ApplicationContext接口定义)
如今更多的是使用应用上下文来实现容器,但实际上,我们只要去简单地翻翻源码,便能够看见ApplicationContext是基于BeanFactory实现的。
1 | |
书中表示由于应用上下文更受欢迎,因此并没有对原始的BeanFactory做过多赘述,因此接下来将直接讲应用上下文的内容。
应用上下文 ApplicationContext
Spring中虽然有很多种应用上下文,但是最常遇到的是如下几个:
AnnotationConfigApplicationContext:从一个或多个基于 Java 的配置类中加载 Spring 应用上下文。AnnotationConfigWebApplicationContext:从一个或多个基于 Java 的配置类中加载 Spring Web 应用上下文。ClassPathXmlApplicationContext:从类路径下的一个或多个 XML 配置文件中加载上下文定义,把应用上下文的定义文件作为类资源。ApplicationContext ctx = new ClassPathXmlApplicationContext("agent.xml")
FileSystemXmlapplicationcontext:从文件系统下的一 个或多个 XML 配置文件中加载上下文定义。ApplicationContext ctx = new FileSystemXmlApplicationContext("c://agent.xml")
XmlWebApplicationContext:从 Web 应用下的一个或多个 XML 配置文件中加载上下文定义。
bean的生命周期
传统的JavaBean是单纯的使用new来实例化bean以进行使用。当bean不再被使用时,则由Java自动进行垃圾回收。而Spring Bean则比这个复杂多了。
这里展示一下书中给的流程图:

- Spring 对 bean 进行实例化;
- Spring 将值和 bean 的引用注入到 bean 对应的属性中;
- 如果 bean 实现了 BeanNameAware 接口,Spring 将 bean 的 ID 传递给 setBeanName()方法;
- 如果 bean 实现了 BeanFactoryAware 接口,Spring 将调用 setBeanFactory() 方法,将 BeanFactory 容器实例传入;
- 如果 bean 实现了 ApplicationContextAware 接口,Spring 将调用 setApplicationContext() 方法,将 bean 所在的应用上下文的引用传入进来;
- 如果 bean 实现了 BeanPostProcessor 接口,Spring 将调用它们的 postProcessBefore-Initialization() 方法;
- 如果 bean 实现了 InitializingBean 接口,Spring 将调用它们的 afterPropertiesSet() 方法。类似地,如果 bean 使用 initmethod 声明了初始化方法,该方法也会被调用;
- 如果 bean 实现了 BeanPostProcessor 接口,Spring 将调用它们的 postProcessAfter-Initialization() 方法;
- 此时,bean 已经准备就绪,可以被应用程序使用了,它们将一直驻留在应用上下文中,直到该应用上下文被销毁;
- 如果 bean 实现了 DisposableBean 接口,Spring 将调用它的 destroy() 接口方法。
总的来说,Bean的生命周期可由以下五个步骤概括:
graph TD
1[实例化 Instantiation] --> 2[属性赋值 Populate] --> 3[初始化 Initialization] --> 4[使用 In Use] --> 5[销毁 Destruction]
Spring会基于该bean实现的接口和bean中使用的注解来决定是否执行额外的操作:
@PostConstruct:如果Bean的方法上有该注解,则会在bean初始化阶段被调用- 自定义
init-method:如果在Bean定义中指定了初始化方法,该方法也会被执行 @PreDestroy:如果Bean的方法上有该注解,则会在bean被销毁前调用- 自定义
destroy-method:如果在Bean定义中指定了销毁方法,则该方法也会被执行。
我猜测这只是一小部分,实际上Spring对Bean的操作十分精密,功能繁多。一个个讲属实讲不完。
看到这里,我发现书中给的内容属实是需要结合Spring官方文档和网上大佬写的博客一起看,顺便本地还要开一个Spring项目测试下来看看到底是个什么行为。此外,Spring所蕴含的东西实在是太多了,如果跟随者教程或书籍立马写出总结的话,总会在后面再看书的时候发现自己前面写的根本就是欠妥当的,或者甚至根本就是错的。因此,接下来的章节中,我只会将在测试过程中发现的问题和具体操作过程写下来。知道真正确定自己了解了之后,才会做最终的总结。