-
Spring 是 Java 应用最广的一个开源框架,为了解决企业应用开发的复杂性而创建的,但现在已经不止应用于企业应用
-
是一个轻量级的控制反转
(IOC)和面向切面(AOP)的容器框架 -
它是当前 Java 语言开发应用程序的最重要的软件基础设施
Spring官网:http://spring.io/
Spring 由众多设计精良模块组成,这些模块能够帮助我们快速开发高质量的程序,以下是 Spring框架的特性概述:
-
核心特性:IoC 容器(IoC Container)、面向切面编程(AOP)、Spring 事件(Events)、资源管理(Resources)、国际化(i18n)、校验(Validation)、数据绑定(Data Binding)、类型装换(Type Conversion)、Spring 表达式(Spring Express Language)
-
数据存储: JDBC、事务抽象(Transactions)、DAO支持(DAO Support)、O/R 映射(O/R Mapping)、XML 编列(XML Marshalling)
-
Web 技术: Web Servlet 技术栈(Spring MVC、WebSocket、SockJS)、Web Reactive 技术栈(Spring WebFlux、WebClient、WebSocket)
-
技术整合: 远程调用(Remoting)、Java 消息服务(JMS)、Java 连接架构(JCA)、Java 管理扩展(JMX)、Java 邮件客户端(Email)、本地任务(Tasks)、本地调度(Scheduling)、缓存抽象(Caching)、Spring 测试 (Testing)
-
测试: 模拟对象(Mock Objects)、TestContext 框架(TextContext Framework)、Spring MVC 测试(Spring MVC Test)、Web 测试客户端(Web Test Client)
-
spring-core: Spring 基础API 模块,如资源管理,泛型处理
-
spring-beans: SpringBean 相关,如依赖查找,依赖注入
-
spring-aop : SpringAOP 处理,如动态代理,AOP 字节码提升
-
spring-context : 事件驱动、注解驱动,模块驱动等
-
spring-expression: Spring 表达式语言模块
- IoC—Inversion of Control,即“控制反转”: 不是具体的技术,而是一种设计思想。在 Java 开发中,IoC 意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。如何理解好 IoC 呢?理解好 IoC 的关键是要明确“谁控制谁,控制什么,为何是反转(有反转就应该有正转了),哪些方面反转了”,那我们来深入分析一下:
- 谁控制谁,控制什么: 传统 Java SE 程序设计,我们直接在对象内部通过 new 进行创建对象,是程序主动去创建依赖对象;而 IoC 是有专门一个容器来创建这些对象,即由 IoC 容器来控制对象的创建;谁控制谁?当然是 IoC 容器控制了对象;控制什么?那就是主要控制了外部资源获取(不只是对象包括比如文件等)。
- 为何是反转,哪些方面反转了: 有反转就有正转,传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象,也就是正转;而反转则是由容器来帮忙创建及注入依赖对象;为何是反转?因为由容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以是反转;哪些方面反转了?依赖对象的获取被反转了。
总结:所谓 IoC,就是由 Spring IoC 容器来负责对象的生命周期和对象之间的关系
-
依赖处理
-
生命周期管理
- 容器
- 托管的资源(Java Beans 或其他资源)
-
配置
- 容器
- 外部化配置
- 托管的资源(Java Beans 或其他资源)
-
BeanFactory 和 ApplicationContext 是 Spring 的两大核心接口,而其中 ApplicationContext 是 BeanFactory 的超集。它们都可以当做 Spring 的容器,Spring 容器是生成 Bean 实例的工厂,并管理容器中的 Bean。在基于 Spring 的 Java EE 应用中,所有的组件都被当成 Bean 处理,包括数据源,Hibernate 的 SessionFactory、事务管理器等。
-
两者在功能设计上的区别
-
BeanFactory 是 Spring 里面最低层的接口,提供了最简单的容器的功能,只提供了实例化对象和拿对象的功能;
-
ApplicationContext 应用上下文,继承 BeanFactory 接口,它是 Spring 的一个更高级的容器,提供了更多的有用的功能;
-
面向切面 (AOP)
-
资源管理(Resources)
-
配置元信息(Configuration Metadata)
-
事件、响应机制(Events、ApplicationEventPublisher)
-
国际化(i18n)
-
注解(Annotations)
-
Environment 抽象
-
-
-
两者在装载 bean 时候的区别
- BeanFactory 在启动的时候不会去实例化 Bean,从容器中拿 Bean 的时候才会去实例化;
- ApplicationContext 在启动的时候就把所有的单例 Bean 全部实例化了。它还可以为 Bean 配置 lazy-init=true 来让 Bean 延迟实例化;
注意:BeanFactory 是 IoC 的底层容器,而 FactoryBean 是创建 Bean 的一种方式,帮助实现复杂的初始化逻辑。
- BeanFactory 示例(通过 xml 配置)
public static void main(String[] args) {
// 创建 BeanFactory 容器
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
// XML 配置文件 ClassPath 路径
String location = "classpath:/META-INF/dependency-lookup-context.xml";
// 加载配置
int beanDefinitionsCount = reader.loadBeanDefinitions(location);
System.out.println("Bean 定义加载的数量:" + beanDefinitionsCount);
// 依赖查找集合对象
lookupCollectionByType(beanFactory);
}
private static void lookupCollectionByType(BeanFactory beanFactory) {
if (beanFactory instanceof ListableBeanFactory) {
ListableBeanFactory listableBeanFactory = (ListableBeanFactory) beanFactory;
Map<String, User> users = listableBeanFactory.getBeansOfType(User.class);
System.out.println("查找到的所有的 User 集合对象:" + users);
}
}- ApplicationContext 示例(通过注解配置的方式)
public static void main(String[] args) {
// 创建 BeanFactory 容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
// 将当前类 作为配置类(Configuration Class)
applicationContext.register(AnnotationApplicationContextAsIoCContainerDemo.class);
// 启动应用上下文
applicationContext.refresh();
// 依赖查找集合对象
lookupCollectionByType(applicationContext);
// 关闭应用上下文
applicationContext.close();
}
/**
* 通过 Java 注解的方式,定义了一个 Bean
*/
@Bean
public User user() {
User user = new User();
user.setId(1L);
user.setName("小马哥");
return user;
}
private static void lookupCollectionByType(BeanFactory beanFactory) {
if (beanFactory instanceof ListableBeanFactory) {
ListableBeanFactory listableBeanFactory = (ListableBeanFactory) beanFactory;
Map<String, User> users = listableBeanFactory.getBeansOfType(User.class);
System.out.println("查找到的所有的 User 集合对象:" + users);
}
}-
根据 Bean 名称查找
- 实时查找
private static void lookupInRealTime(BeanFactory beanFactory) { User user = (User) beanFactory.getBean("user"); System.out.println("实时查找:" + user); }
- 延迟查找
需要先在配置文件中定义 ObjectFactory 对象 <bean id="objectFactory" class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean"> <property name="targetBeanName" value="user"/> </bean>
private static void lookupInLazy(BeanFactory beanFactory) { ObjectFactory<User> objectFactory = (ObjectFactory<User>) beanFactory.getBean("objectFactory"); User user = objectFactory.getObject(); System.out.println("延迟查找:" + user); }
-
根据 Bean 类型查找
- 单个 Bean 对象
private static void lookupByType(BeanFactory beanFactory) { //如果 User 类型的对象不止一个会抛出异常 User user = beanFactory.getBean(User.class); System.out.println("实时查找:" + user); }
- 集合 Bean 对象
private static void lookupCollectionByType(BeanFactory beanFactory) { if (beanFactory instanceof ListableBeanFactory) { ListableBeanFactory listableBeanFactory = (ListableBeanFactory) beanFactory; Map<String, User> users = listableBeanFactory.getBeansOfType(User.class); System.out.println("查找到的所有的 User 集合对象:" + users); } }
-
根据 Java 注解查找
- 集合 Bean 对象
private static void lookupByAnnotationType(BeanFactory beanFactory) { if (beanFactory instanceof ListableBeanFactory) { ListableBeanFactory listableBeanFactory = (ListableBeanFactory) beanFactory; Map<String, User> users = (Map) listableBeanFactory.getBeansWithAnnotation(Super.class); System.out.println("查找标注 @Super 所有的 User 集合对象:" + users); } }
- 根据Bean 名称查找
- getBean(String)
- Spring 2.5 覆盖默认参数:getBean(String,Object...)
- 根据Bean 类型查找
- Bean 实时查找
- Spring 3.0 getBean(Class)
- Spring 4.1 覆盖默认参数:getBean(Class,Object...)
- Spring 5.1 Bean 延迟查找
- getBeanProvider(Class)
- getBeanProvider(ResolvableType)
- Bean 实时查找
- 根据Bean 名称+ 类型查找:getBean(String,Class)
集合类型依赖查找接口-ListableBeanFactory
- 根据Bean 类型查找
- 获取同类型Bean 名称列表
- getBeanNamesForType(Class)
- Spring 4.2 getBeanNamesForType(ResolvableType)
- 获取同类型Bean 实例列表
- getBeansOfType(Class) 以及重载方法
- 获取同类型Bean 名称列表
- 通过注解类型查找
- Spring 3.0 获取标注类型Bean 名称列表
- getBeanNamesForAnnotation(Class<? extends Annotation>)
- Spring 3.0 获取标注类型Bean 实例列表
- getBeansWithAnnotation(Class<? extends Annotation>)
- Spring 3.0 获取指定名称+ 标注类型Bean 实例
- findAnnotationOnBean(String,Class<? extends Annotation>)
- Spring 3.0 获取标注类型Bean 名称列表
层次性依赖查找接口-HierarchicalBeanFactory
- 双亲BeanFactory:getParentBeanFactory()
- 层次性查找
- 根据Bean 名称查找
- 基于containsLocalBean 方法实现
- 根据Bean 类型查找实例列表
- 单一类型:BeanFactoryUtils#beanOfType
- 集合类型:BeanFactoryUtils#beansOfTypeIncludingAncestors
- 根据Java 注解查找名称列
- BeanFactoryUtils#beanNamesForTypeIncludingAncestors
- 根据Bean 名称查找
Bean 延迟依赖查找接口
-
org.springframework.beans.factory.ObjectFactory
-
org.springframework.beans.factory.ObjectProvider
-
Spring 5 对 Java 8 特性扩展
- getIfAvailable(Supplier)
private static void lookupIfAvailable(AnnotationConfigApplicationContext applicationContext) { ObjectProvider<User> userObjectProvider = applicationContext.getBeanProvider(User.class); // 如果当前对象不存在,则创建一个,属于兜底的方案 User user = userObjectProvider.getIfAvailable(User::createUser); System.out.println("当前 User 对象:" + user); }
-
ifAvailable(Consumer)
-
Stream 扩展-stream()
private static void lookupByStreamOps(AnnotationConfigApplicationContext applicationContext) { ObjectProvider<String> objectProvider = applicationContext.getBeanProvider(String.class); // Stream -> Method reference objectProvider.stream().forEach(System.out::println); }
-
依赖查找安全性对比
| 依赖查找类型 | 代表实现 | 是否安全 |
|---|---|---|
| 单一类型查找 | BeanFactory#getBean | ==否== |
| ObjectFactory#getObject | ==否== | |
| ObjectProvider#getIfAvailable | 是 | |
| 集合类型查找 | ListableBeanFactory#getBeansOfType | 是 |
| ObjectProvider#stream | 是 |
注意:层次性依赖查找的安全性取决于其扩展的单一或集合类型的 BeanFactory 接口
- AbstractApplicationContext 内建可查找的依赖
- 注解驱动 Spring 应用上下文内建可查找的依赖(内建 bean)(部分)
| Bean 名称 | Bean 实例 | 使用场景 |
|---|---|---|
| org.springframework.contex t.annotation.internalConfigu rationAnnotationProcessor | ConfigurationClassPostProcesso r 对象 | 处理 Spring 配置类 |
| org.springframework.contex t.annotation.internalAutowir edAnnotationProcessor | AutowiredAnnotationBeanPostP rocessor 对象 | 处理 @Autowired 以及 @Value 注解 |
| org.springframework.contex t.annotation.internalCommo nAnnotationProcessor | CommonAnnotationBeanPostPr ocessor 对象 | (条件激活)处理JSR-250 注解, 如@PostConstruct 等 |
| org.springframework.contex t.event.internalEventListener Processor | EventListenerMethodProcessor 对象 | 处理标注@EventListener 的 Spring 事件监听方法 |
| org.springframework.contex t.event.internalEventListener Factory | DefaultEventListenerFactory 对 象 | @EventListener 事件监听方法适配为ApplicationListener |
| org.springframework.contex t.annotation.internalPersiste nceAnnotationProcessor | PersistenceAnnotationBeanPost Processor 对象 | (条件激活)处理JPA 注解场景 |
- 根据 Bean 名称注入
<bean id="userRepository"
class="org.xxx.UserRepository">
<!-- 单个属性配置 -->
<property name="car" ref="Ferrari">
<!-- 集合属性配置 -->
<property name="users">
<util:list>
<ref bean="superUser"/>
<ref bean="user"/>
</util:list>
</property>
</bean>- 根据 Bean 类型注入
<bean id="userRepository"
class="org.xxx.UserRepository" autowire="byType">
<!-- Auto-Wiring 自动装配 -->
</bean>- 注入容器内建非 Bean 对象
1. 先在实体类中定义 BeanFactory
class UserRepository {
private BeanFactory beanFactory; // 內建非 Bean 对象(依赖)
//省略getter和setter方法
}
2. 使用 autowire 自动注入这个依赖对象
<bean id="userRepository"
class="org.xxx.UserRepository" autowire="byType">
</bean>
3. 获取内建非 Bean 对象(依赖)
// 依赖来源一:自定义 Bean
UserRepository userRepository = ac.getBean("userRepository", UserRepository.class);
System.out.println(userRepository.getUsers());
System.out.println(userRepository.getBeanFactory());
// 依赖来源二:依赖注入(內建依赖)
System.out.println(userRepository.getBeanFactory());
4. 使用 applicationContext 查找会抛异常(因为不是定义的普通 bean)
// 依赖查找(错误)
System.out.println(ac.getBean(BeanFactory.class));- 注入容器内建 Bean 对象
// 依赖来源三:容器內建 Bean
Environment environment = ac.getBean(Environment.class);
System.out.println("获取 Environment 类型的 Bean:" + environment);-
Spring BeanDefinition(自定义的 Bean)
配置元数据
@Bean public User user(){}
BeanDefinitionBuilder
-
单例对象
API 配置
通过 SingletonBeanRegistry#registerSingleton(String beanName, Object singletonObject) 实现
- Spring 内建 BeanDefinition
Bean 实例,在 AnnotationConfigUtils 类中可以找到这些类的 Bean 名称
ConfigurationClassPostProcessor 处理 Spring 配置类
AutowiredAnnotationBeanPostProcessor 处理 @Autowired 以及 @Value 注解
CommonAnnotationBeanPostProcesser (条件激活)处理 JSR-250 注解如@PostConstruct 等
EventListenerMethodProcessr 处理标注 @EventListener 的 Spring 事件监听方法
DefaultEventListenerFactory @EventListener 事件监听方法适配为 ApplicationListener
PersistenceAnnotationBeanPostProcessor (条件激活)处理 JPA 注解场景
在依赖查找来源的基础上增加了
-
ResolvableDependency (非 Spring 容器管理的对象)、
BeanFactory
ResourceLoader
ApplicationEventPublisher
ApplicationContext
其中后面三个的类的实例指向同一个对象,就是 Spring 应用上下文实例
注册:ConfigurableListableBeanFactory#registerResolvableDependency
-
@Value 标注的外部化配置
@Value("${usr.name}") private String name;
- 元数据:BeanDefinition
- 注册:BeanDefinitionRegistry#registryBeanDefinition
- 类型:延迟和非延迟
- 顺序:Bean 生命周期顺序按照注册顺序
来源:外部普通 Java 对象(不一定是 POJO)
注册:SingletonBeanRegistry#registrySingleton
限制:
无生命周期管理
无法实现延迟初始化 Bean
注册:ConfigurableListableBeanFactory#registryResolvableDependency
限制:
无生命周期管理
无实现延迟初始化 Bean
无法通过依赖查找
类型:非常规 Spring 对象依赖来源
限制:
无生命周期管理
无实现延迟初始化 Bean
无法通过依赖查找
- Spring Bean 配置元信息-BeanDefinition
- Spring Bean 属性元信息-PropertyValues
- Spring 容器配置元信息
- Spring 外部化配置元信息-PropertySource
- Spring Profile 元信息-@Profile
什么是 BeanDefinition ?
BeanDefinition 是 Spring 框架中定义 Bean 的配置元信息接口,包含:
- Bean 的类名
- Bean 行为配置元素,如作用域、自动绑定的模式,生命周期回调等
- 其他 Bean 引用,又可称作合作者或者依赖
- 配置设置,比如 Bean 属性(properties)
BeanDefinition 的元信息如图:
BeanDefinition 的构建
- 通过 BeanDefinitionBuilder
// 1.通过 BeanDefinitionBuilder 构建
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(User.class);
// 通过属性设置
builder.addPropertyValue("id", 1)
.addPropertyValue("name", "小马哥");
// 获取 BeanDefinition 实例
BeanDefinition beanDefinition = builder.getBeanDefinition();
// BeanDefinition 并非 Bean 终态,可以自定义修改- 通过 AbstractBeanDefinition 以及它的派生类
// 2. 通过 AbstractBeanDefinition 以及派生类
GenericBeanDefinition generic = new GenericBeanDefinition();
// 设置 Bean 类型
generic.setBeanClass(User.class);
// 通过 MutablePropertyValues 批量操作属性
MutablePropertyValues property = new MutablePropertyValues();
property.add("id", 1)
.add("name", "小马哥");
// 通过 set MutablePropertyValues 批量操作属性
generic.setPropertyValues(property);-
每个 Bean 拥有一个或多个标识符,这些标识符在 Bean 所在的容器必须是唯一的(在整个应用中可以不唯一),同时,还可以为 Bean 设置别名(Alias)。
-
在基于 XML 的配置元信息中,可用 id 或者 name 属性来规定 Bean 的标识符,如果想要引入别名的话,可在 name 属性使用半角逗号或分号来间隔。
-
Bean 的 id 或 name 属性并非必须制定,如果留空的话,容器会为 Bean 自动生成一个唯一的名称。
-
Bean 名称生成器(BeanNameGenerator 接口)有两个实现,一个是默认通用的 DefaultBeanNameGenerator,一个是基于注解扫描的 AnnotationBeanNameGenerator
Bean 别名配置:
<!-- 将 Spring 容器中 "user" Bean 关联/建立别名 - "xiaomage-user" -->
<alias name="user" alias="xiaomage-user" />使用别名依赖查找对应的 Bean:
// 通过别名 xiaomage-user 获取曾用名 user 的 bean
User user = beanFactory.getBean("user", User.class);
User xiaomageUser = beanFactory.getBean("xiaomage-user", User.class);
System.out.println(user == xiaomageUser); //trueBeanDefinition 注册
- xml 配置元信息
- <bean name =“…" />
- Java 注解配置元信息
- @Bean
- @Component
- @Import
- Java API 配置元信息
- 命名方式:BeanDefinitionRegistry#registerBeanDefinition(String,BeanDefinition)
- 非命名:BeanDefinitionReaderUtils#registerWithGeneratedName(AbstractBeanDefinition,Be anDefinitionRegistry)
public static void registerUserBeanDefinition(BeanDefinitionRegistry registry, String beanName) {
BeanDefinitionBuilder beanDefinitionBuilder = genericBeanDefinition(User.class);
beanDefinitionBuilder
.addPropertyValue("id", 1L)
.addPropertyValue("name", "小马哥");
// 判断如果 beanName 参数存在时
if (StringUtils.hasText(beanName)) {
// 注册 BeanDefinition
registry.registerBeanDefinition(beanName, beanDefinitionBuilder.getBeanDefinition());
} else {
// 非命名 Bean 注册方法
BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinitionBuilder.getBeanDefinition(), registry);
}
}
public static void registerUserBeanDefinition(BeanDefinitionRegistry registry) {
registerUserBeanDefinition(registry, null);
}-
配置类方式:AnnotatedBeanDefinitionReader#register(Class...)
-
外部单例对象注册
- SingletonBeanRegistry#registerSingleton
// 创建一个外部 UserFactory 对象 UserFactory userFactory = new DefaultUserFactory(); SingletonBeanRegistry sing = appContext.getBeanFactory(); // 注册外部单例对象 sing.registerSingleton("userFactory", userFactory); // 启动 Spring 应用上下文 appContext.refresh(); // 通过依赖查找的方式来获取 UserFactory UserFactory user2 = appContext.getBean("userFactory", UserFactory.class); System.out.println(userFactory == user2);
- 通过构造器
<bean id="user-by-constructor" class="org.xxx.User">
<constructor-arg value="20"/>
<constructor-arg value="zhangsan"/>
</bean>- 通过静态工厂方法
<!-- 静态方法实例化 Bean -->
<bean id="user-by-static-method" class="org.xxx.User"
factory-method="createUser" />
<!-- User 类中的静态方法 -->
public static User createUser() {
User user = new User();
user.setId(1L);
user.setName("小马哥");
return user;
}- 通过 Bean 工厂方法
<!-- 实例(Bean)方法实例化 Bean -->
<bean id="userFactory" class="org.xxx.DefaultUserFactory"/>
<bean id="user-by-instance-method" factory-bean="userFactory" factory-method="createUser"/>
public class DefaultUserFactory {
@Override
public User createUser() {
return User.createUser();
}
}- 通过 FactoryBean
<!-- FactoryBean实例化 Bean -->
<bean id="user-by-factory-bean" class="org.xxx.UserFactoryBean" />
public class UserFactoryBean implements FactoryBean {
@Override
public Object getObject() throws Exception {
return User.createUser();
}
@Override
public Class<?> getObjectType() {
return User.class;
}
}- 通过 ServiceLoaderFactoryBean
<!-- 配置 ServiceLoaderFactoryBean -->
<bean id="userFactoryServiceLoader"class="x.ServiceLoaderFactoryBean">
<property name="serviceType" value="org.xx.UserFactory" />
</bean>
ServiceLoader<UserFactory> serviceLoader = beanFactory.getBean("userFactoryServiceLoader", ServiceLoader.class);
Iterator<UserFactory> iterator = serviceLoader.iterator();
while (iterator.hasNext()) {
UserFactory userFactory = iterator.next();
System.out.println(userFactory.createUser());
}- 通过 AutowireCapableBeanFactory#createBean(Class,int,boolean)
// 通过 ApplicationContext 获取 AutowireCapableBeanFactory
AutowireCapableBeanFactory beanFactory = applicationContext.getAutowireCapableBeanFactory();
// 创建 UserFactory 对象,通过 AutowireCapableBeanFactory
UserFactory factory = beanFactory.createBean(DefaultUserFactory.class);
System.out.println(factory.createUser());- 通过 BeanDefinitionRegistry#registerBeanDefinition(String,BeanDefinition)
- @PostConstruct 标注方法
// 1. 基于 @PostConstruct 注解
@PostConstruct
public void init() {
System.out.println("@PostConstruct : UserFactory 初始化中...");
}- 实现 InitializingBean 接口的 afterPropertiesSet() 方法
public class DefaultUserFactory implements UserFactory, InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("InitializingBean#afterPropertiesSet() : UserFactory 初始化中...");
}
}- 自定义初始化方法
- Java 注解:@Bean(initMethod=”init”)
- XML 配置:<bean init-method=”init” ... />
- Java API:AbstractBeanDefinition#setInitMethodName(String)
@Bean(initMethod = "initUserFactory")
public UserFactory userFactory() {
return new DefaultUserFactory();
}
public void initUserFactory() {
System.out.println("自定义初始化方法 initUserFactory() : UserFactory 初始化中...");
}注意:初始化方法执行顺序:@PostConstruct 》 afterPropertiesSet() 》自定义初始化方法
-
XML 配置:<bean lazy-init=”true” ... />
-
Java 注解:@Lazy
@Lazy
public UserFactory userFactory() {
return new DefaultUserFactory();
}总结:延迟初始化是在容器需要这个 Bean 的时候才去初始化
- @PreDestroy 标注方法
@PreDestroy
public void preDestroy() {
System.out.println("@PreDestroy : UserFactory 销毁中...");
}- 实现 DisposableBean 接口的 destroy() 方法
public class DefaultUserFactory implements UserFactory, DisposableBean {
@Override
public void destroy() throws Exception {
System.out.println("DisposableBean#destroy() : UserFactory 销毁中...");
}
}- 自定义销毁方法
- XML 配置:<bean destroy=”destroy” ... />
- Java 注解:@Bean(destroy=”destroy”)
- Java API:AbstractBeanDefinition#setDestroyMethodName(String)
@Bean(destroyMethod = "doDestroy")
public UserFactory userFactory() {
return new DefaultUserFactory();
}
public void doDestroy() {
System.out.println("自定义销毁方法 doDestroy() : UserFactory 销毁中...");
}注意:销毁方法执行顺序:@PreDestroy 》 destroy() 》自定义销毁方法
Bean 垃圾回收
- 关闭 Spring 容器(应用上下文)
- 执行 GC
- Spring Bean 覆盖的 finalize() 方法被回调(可能)
- 对于 Singleton Bean,Spring IoC容器中只会存在一个共享的 bean 实例。
- Singleton Bean 无论依赖查找还是依赖注入,均为同一个对象。
- Spring 容器管理着 Singleton Bean 的完整生命周期。
- Prototype Bean 无论依赖查找还是依赖注入,均为新生成的对象。
- 如果依赖注入集合类型的对象,Singleton Bean 和 Prototype Bean 均会存在一个, Prototype Bean 有别于其他地方的依赖注入的 Prototype Bean。
- Spring 容器没有办法管理 Prototype Bean 的完整生命周期,也没有办法记录实例的存在。销毁回调方法将不会执行,可以利用 BeanPostProcessor 进行清扫工作。
- Prototype 是原型类型,它在我们创建容器的时候并没有实例化,而是当我们获取 bean 的时候才会去创建一个对象,而且我们每次获取到的对象都不是同一个对象。
- 有状态的 bean 应该使用 prototype 作用域,无状态的 bean 则应该使用 singleton 作用域。
- Request 作用域针对的是每次的 Http 请求,Spring容器会根据相关的Bean的定义来创建一个全新的 Bean 实例。而且该 Bean 只在当前 request 内是有效的。
配置:
- XML <bean class="..."scope = "request"/>
- Java 注解 -@RequestScope 或 @Scope(WebApplicationContext.SCOPE_REQUEST)
实现:
- API - RequestScope
- 在每个 Session 的生命周期内,Spring 容器会根据 id 为 userPreferences 的 bean 定义创建一个 UserPreferences bean 的新实例。 也就是说,userPreferences bean 的作用域限于Session 范围。和请求作用域 request-scoped bean 类似, 因为每个会话域 session-scoped bean 的范围限于特定的 HTTP Session 内部,所以一个 Session 内的 userPreferences bean也是可以被随意修改, 而不会影响到其他 Session 中的 userPreferences bean。当一个 HTTP Session 最终用完被 JVM 回收时,相关的会话域 session-scoped bean 也被一起回收。
配置:
- XML <bean class="..."scope = "session"/>
- Java 注解 -@SessionScope 或 @Scope(WebApplicationContext.SCOPE_SESSION)
实现:
- API - SessionScope
配置:
- XML <bean class="..."scope = "application "/>
- Java 注解 -@ApplicationScope 或 @Scope(WebApplicationContext.SCOPE_APPLICATION)
实现:
- API - SessionScope
-
实现 Scope
- org.springframework.beans.factory.config.Scope
-
注册 Scope
- API - ConfigurableBeanFactory#registerScope
- 配置
<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer"> <property name="scopes"> <map> <entry key="..."> </entry> </map> </property> </bean>
BeanDefinition 配置
- 面向资源
- XML 配置
- Properties 资源配置
- 面向注解
- 面向 API
- 面向资源 BeanDefinition 解析
- BeanDefinitionReader
- XML 解析器 - BeanDefinitionParser
- 面向注解 BeanDefinition 解析
- AnnotatedBeanDefinitionReader (没有继承 BeanDefinitionReader)
-
BeanDefinitionRegistry 接口的 registerBeanDefinition(beanName, beanDefinition) 方法
它的最重要的实现类是 DefaultListableBeanFactory,AnnotationConfigApplicationContext 最终也是引用它来实现。
在 Spring 中每一个 Bean 基本上都会对应有一个 BeanDefinition,对于它们的实例化和初始化的过程 BeanDefinition 也起着关键性作用,BeanDefinition 存在父 bd(BeanDefinition),子 bd 可以继承它的父 bd 的属性,所以我们在实例化和初始化 Bean 的时候必须考虑父 bd。
在 Bean 的初始化流程中很多地方都出现了与合并 bd 相关的操作,特别是合并 bd 更是多次调用,为什么要这么做呢?
- 很多地方我们需要拿到完整的 bd,不能只是一个子 bd,只要会有缺失,很多判断会有问题,所以每次拿到 bd 都需要合并 bd。
- 因为我们可以在很多地方将 bd 中的属性改变,所以我们不能只是在一个地方去合并 bd,所以在很多地方需要合并 bd。比如我们在 BeanDefinitionRegistryPostProcessor 或者 BeanFactoryPostProcessor 可以很简单的拿到 bd 甚至注册 bd,所以我们可通过这种方式更改 bd 中的属性或者添加父 bd,这个时候之前合并的 bd 就不准确了,所以需要多次合并 bd。
合并 BeanDefinition 的方法定义在 ConfigurableBeanFactory 接口中,AbstractBeanFactory 抽象类实现了这个接口的 getMergedBeanDefinition() 方法。
合并流程:
- 找到父 bd,如果没有找到就直接将自身当作父 bd,找到的话就看看父 bd 有没有父 bd,并且通过 getMergedBeanDefinition() 方法得到父 bd 合并之后的 bd。
- 合并 bd,通过父 bd 创建出一个 RootBeanDefinition 对象,然后子 bd 覆盖父 bd 创建出来的对象(覆盖属性之类的)。
- 将合并后的 bd 放入一个 mergedBeanDefinitions 集合中,最后将合并后的 bd 返回。
- Spring 框架同时提供了一个机会给框架其他部分,或者开发人员用于在 bean 创建过程中,MergedBeanDefinition (mbd) 生成之后,bean 属性填充之前,对该 bean 和该MergedBeanDefinition 做一次回调,相应的回调接口是MergedBeanDefinitionPostProcessor。
- ClassLoader 类加载
- Java Security 安全控制
- ConfigurableBeanFactory 临时 ClassLoader
InstantiationAwareBeanPostProcessor 继承自 BeanPostProcessor,是 Spring 非常重要的拓展接口,代表着 bean 的一段生命周期:实例化(Instantiation)。 接口方法说明:
- postProcessBeforeInstantiation 调用时机为 bean 实例化(Instantiation)之前如果返回了bean 实例, 则会替代原来正常通过 target bean 生成的 bean 的流程。此时 bean 的执行流程将会缩短, 只会执行 BeanPostProcessor#postProcessAfterInitialization 接口完成初始化。
- postProcessAfterInstantiation 调用时机为 bean 实例化(Instantiation)之后和任何初始化(Initialization)之前。
- postProcessProperties 调用时机为 postProcessAfterInstantiation 执行之后并返回 true, 返回的 PropertyValues 将作用于给定 bean 属性赋值。
- postProcessPropertyValues 已经被标注@Deprecated,后续将会被 postProcessProperties 取代。
InstantiationAwareBeanPostProcessor 与 BeanPostProcessor 对比:
- BeanPostProcessor 执行时机为 bean 初始化(Initialization)阶段,日常可以拓展该接口对 bean 初始化进行定制化处理。
- InstantiationAwareBeanPostProcessor 执行时机 bean 实例化(Instantiation)阶段,典型用于替换 bean 默认创建方式,例如 aop 通过拓展接口生成代理对应,主要用于基础框架层面。如果日常业务中需要拓展该,Spring 推荐使用缺省适配器类InstantiationAwareBeanPostProcessorAdapter。
- 所有 bean 创建都会进行回调。
InstantiationAwareBeanPostProcessor 的触发点
-
从 AbstractAutowireCapableBeanFactory#createBean 开始
-
跟进 AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation 会触发 postProcessorsBeforeInstantiation 执行,返回 bean 非 null 则直接执行beanPostProcessorsAfterInitialization 进行初始化后置处理,返回的 bean 直接返回容器,生命周期缩短。
-
跟进 AbstractAutowireCapableBeanFactory#doCreateBean#populateBean 先会触发 postProcessAfterInstantiation 执行,紧接着执行 IoC 依赖注入,然后优先触发 postProcessProperties 执行,如没覆盖则触发 postProcessPropertyValues。
- Bean 实例化前阶段
- InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation
- 实例化方式
- 传统实例化方式
- 实例化策略-InstantiationStrategy
- 构造器依赖注入
- 传统实例化方式
-
Bean 属性赋值(Populate)判断
-
InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation
这个方法的默认返回值为 true,如果返回 false,将防止对此 bean 实例调用任何后续 InstantiationAwareBeanPostProcessor 操作。
-
- Bean 属性值元信息
- PropertyValues
- Bean 属性赋值前回调
- Spring 1.2 -5.0:InstantiationAwareBeanPostProcessor#postProcessPropertyValues
- Spring 5.1:InstantiationAwareBeanPostProcessor#postProcessProperties
Aware 是已感知的,意识到的意思。所以这些接口应该是能感知到所有 Aware 前面的含义的。它的目的是为了让 bean 获取 Spring 容器的服务。
- Spring Aware 接口(以下也是回调执行顺序)
- BeanFactory 生命周期
- BeanNameAware
- BeanClassLoaderAware
- BeanFactoryAware
- ApplicationContext 生命周期
- EnvironmentAware
- EmbeddedValueResolverAware
- ResourceLoaderAware
- ApplicationEventPublisherAware
- MessageSourceAware
- ApplicationContextAware
- BeanFactory 生命周期
- 已完成
- Bean 实例化
- Bean 属性赋值
- Bean Aware 接口回调
- 方法回调
- BeanPostProcessor#postProcessBeforeInitialization
- Bean 初始化(Initialization)
- @PostConstruct 标注方法(依赖于注解驱动,在 BeanFactory 中可以使用 CommonAnnotationBeanPostProcessor 触发)
- 实现 InitializingBean 接口的 afterPropertiesSet() 方法
- 自定义初始化方法
- 方法回调
- BeanPostProcessor#postProcessAfterInitialization
- 方法回调
- Spring 4.1 +:SmartInitializingSingleton#afterSingletonsInstantiated
- 方法回调
- DestructionAwareBeanPostProcessor#postProcessBeforeDestruction
- Bean 销毁(Destroy)
- @PreDestroy 标注方法
- 实现 DisposableBean 接口的 destroy() 方法
- 自定义销毁方法
- Bean 垃圾回收(GC)
- 关闭 Spring 容器(应用上下文)
- 执行 GC
- Spring Bean 覆盖的 finalize() 方法被回调
BeanPostProcessor 提供 Spring Bean 初始化前和初始化后的生命周期回调,分别对应postProcessBeforeInitialization 以及 postProcessAfterInitialization 方法,允许对关心的 Bean 进行扩展 ,甚至是替换。其中,ApplicationContext 相关的 Aware 回调也是基于 BeanPostProcessor 实现,即 ApplicationContextAwareProcessor。
BeanFactoryPostProcessor 是 Spring BeanFactory(实际为 ConfigurableListableBeanFactory)的后置处理器,用于扩展 BeanFactory,或通过 BeanFactory 进行依赖查找和依赖注入。 BeanFactoryPostProcessor 必须有 Spring ApplicationContext 执行,BeanFactory 无法与其直接交互。 而 BeanPostProcessor 则直接与 BeanFactory 关联,属于 N 对 1 的关系。
BeanFactory 的默认实现为 DefaultListableBeanFactory,其中 Bean 生命周期与方法映射如下:
- BeanDefinition 注册阶段-registerBeanDefinition
- BeanDefinition 合并阶段-getMergedBeanDefinition
- Bean 实例化前阶段-resolveBeforeInstantiation
- Bean 实例化阶段-createBeanInstance
- Bean 实例化后阶段-populateBean
- Bean 属性赋值前阶段-populateBean
- Bean 属性赋值阶段-populateBean
- Bean Aware 接口回调阶段-initializeBean
- Bean 初始化前阶段-initializeBean
- Bean 初始化阶段-initializeBean
- Bean 初始化后阶段-initializeBean
- Bean 初始化完成阶段-preInstantiateSingletons
- Bean 销毁前阶段-destroyBean
- Bean 销毁阶段-destroyBean






