目录
[三、HierarchicalBeanFactory(分层 Bean 工厂)](#三、HierarchicalBeanFactory(分层 Bean 工厂))
[四、ListableBeanFactory(可列表的 Bean 工厂)](#四、ListableBeanFactory(可列表的 Bean 工厂))
五、AutowireCapableBeanFactory(可自动装配)
[六、ConfigurableBeanFactory(可配置的 Bean 工厂)](#六、ConfigurableBeanFactory(可配置的 Bean 工厂))
一、理解BeanFactory
(一)功能性理解
BeanFactory 是 Spring 框架中的一个核心接口,用于管理应用程序中的对象(也称为 bean)。它提供了一种将应用程序组件(如服务、数据源、控制器等)解耦并配置到应用程序中的方式。对 BeanFactory 的初步理解可以简单从以下几个方面来说说:
-
IoC 容器: BeanFactory 是 Spring 的 IoC 容器之一,IoC(Inverse of Control,控制反转)是一种设计模式,它将对象的创建和管理控制权从代码中转移到了容器中。BeanFactory 作为 IoC 容器的顶层抽象,负责创建、组装、配置和管理 bean 对象。
-
Bean 定义管理: BeanFactory 负责管理应用程序中的所有 bean 定义。这些 bean 定义通常是通过XML 文件、注解或 Java 代码进行配置的。BeanFactory 负责解析这些配置信息,并在需要时实例化相应的 bean 对象。
-
延迟加载: BeanFactory 支持延迟加载机制,即只有在请求时才会实例化 bean 对象,这样可以提高应用程序的性能和资源利用率。在大型应用程序中,延迟加载可以避免在启动时加载大量的对象,从而加快应用程序的启动速度。
-
依赖注入: BeanFactory 实现了依赖注入(DI)机制,它负责解决 bean 之间的依赖关系。通过依赖注入,BeanFactory 可以在创建 bean 对象时自动将其依赖的其他 bean 对象注入到其中,从而实现了对象之间的解耦。
-
Bean 的作用域管理: BeanFactory 支持不同的 bean 作用域,如 singleton、prototype、request、session 等。通过配置不同的作用域,可以控制 bean 对象的生命周期,并确保在不同的作用域下能够正确地管理 bean 对象的创建和销毁。
总的来说,可以初步理解BeanFactory 为 Spring 框架中负责管理 bean 对象的核心组件,它通过 IoC 容器、延迟加载、依赖注入和作用域管理等机制,实现了对象之间的解耦和灵活配置,从而提高了应用程序的可维护性、可测试性和可扩展性。
(二)BeanFactory和它的子接口
BeanFactory(Bean 工厂):
- BeanFactory 是 Spring 框架的核心接口之一,负责管理和装配 bean 对象。
- Spring IoC 容器的基础,负责创建、查找、注册和管理 bean 对象。
HierarchicalBeanFactory(分层 Bean 工厂):
- HierarchicalBeanFactory 继承自 BeanFactory 接口,支持创建多级的 bean 工厂层次结构。
- 层次结构适用父子容器概念,更灵活地管理 bean 对象的生命周期和依赖关系。
ListableBeanFactory(可列表的 Bean 工厂):
- ListableBeanFactory 继承自 BeanFactory 接口,扩展了对 bean 列表的操作。
- 允许查询容器中的所有 bean,支持按条件查找和过滤。
AutowireCapableBeanFactory(可自动装配的 Bean 工厂):
- AutowireCapableBeanFactory 继承自 BeanFactory 接口,增强了自动装配功能。
- 支持自动装配 bean 的依赖关系,使得我们不需要显式地配置所有的 bean 依赖。
ApplicationContext(应用上下文):
- ApplicationContext 是 BeanFactory 的一个扩展,提供了更多的应用级功能。
- 它包括了 BeanFactory 的所有功能,并且提供了国际化、事件发布、资源加载等功能。
ConfigurableBeanFactory(可配置的 Bean 工厂):
- ConfigurableBeanFactory 继承自 BeanFactory 接口,增强了对 BeanFactory 的配置能力。
- 允许我们配置 BeanFactory 的各种属性和行为,以满足不同应用场景的需求。
ConfigurableApplicationContext(可配置的应用上下文):
- ConfigurableApplicationContext 是 ApplicationContext 的扩展,提供了更多的配置选项。
- 包括了 ApplicationContext 的所有功能,并且支持对 ApplicationContext 进行配置。
ConfigurableListableBeanFactory(可配置且可列表的 Bean 工厂):
- ConfigurableListableBeanFactory 继承自 ConfigurableBeanFactory 和 ListableBeanFactory 接口,结合了两者的功能。
- 不仅支持对 BeanFactory 进行配置,还提供了对 bean 列表的操作。
(三)BeanFactory的实现类
BeanFactory的结构体系非常庞大,在 Spring 中,BeanFactory 的实现类是容器的实际执行者,负责解析 bean 的定义、创建 bean 实例以及管理 bean 的生命周期。今天主要针对
二、BeanFactory根接口
BeanFactory 是 Spring 框架中的一个核心接口,用于管理应用程序中的对象(也称为 bean)。它提供了一种将应用程序组件(如服务、数据源、控制器等)解耦并配置到应用程序中的方式。BeanFactory 负责创建、组装、配置和管理 bean 对象。这些 bean 可以通过 XML 文件、注解或 Java 代码进行配置。BeanFactory 还支持延迟加载、依赖注入和作用域管理等功能,以提高应用程序的性能、可维护性和可扩展性。
(一)源码展示和理解
java
package org.springframework.beans.factory;
import org.springframework.beans.BeansException;
/**
* 根接口,用于定义访问 Spring bean 容器的基本功能。
* 这是 Spring IoC 容器的基础接口。
*/
public interface BeanFactory {
/**
* 根据给定的名称获取一个 bean 实例。
* @param name 要获取的 bean 的名称
* @return bean 实例
* @throws BeansException 如果找不到 bean 或 bean 创建过程中发生异常,则抛出 BeansException 异常
*/
Object getBean(String name) throws BeansException;
/**
* 检查容器中是否包含具有给定名称的 bean。
* @param name 要检查的 bean 的名称
* @return 如果容器中包含具有给定名称的 bean,则返回 true;否则返回 false
*/
boolean containsBean(String name);
/**
* 检查具有给定名称的 bean 是否为 singleton。
* @param name 要检查的 bean 的名称
* @return 如果该 bean 是 singleton,则返回 true;否则返回 false
* @throws NoSuchBeanDefinitionException 如果找不到具有给定名称的 bean,则抛出 NoSuchBeanDefinitionException 异常
*/
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
/**
* 检查具有给定名称的 bean 是否为 prototype。
* @param name 要检查的 bean 的名称
* @return 如果该 bean 是 prototype,则返回 true;否则返回 false
* @throws NoSuchBeanDefinitionException 如果找不到具有给定名称的 bean,则抛出 NoSuchBeanDefinitionException 异常
*/
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
/**
* 获取具有给定名称的 bean 的类型。
* @param name 要获取类型的 bean 的名称
* @return bean 的类型
* @throws NoSuchBeanDefinitionException 如果找不到具有给定名称的 bean,则抛出 NoSuchBeanDefinitionException 异常
*/
Class<?> getType(String name) throws NoSuchBeanDefinitionException;
/**
* 获取具有给定名称的 bean 的别名。
* @param name 要获取别名的 bean 的名称
* @return bean 的别名数组(如果存在),否则返回空数组
* @throws NoSuchBeanDefinitionException 如果找不到具有给定名称的 bean,则抛出 NoSuchBeanDefinitionException 异常
*/
String[] getAliases(String name) throws NoSuchBeanDefinitionException;
}
方法 | 描述 |
---|---|
getBean(String name) | 从容器中获取指定名称(或 ID)的 bean 实例。根据名称查找相应的 bean 定义,并根据需要实例化和初始化 bean 对象。 |
containsBean(String name) | 检查容器是否包含具有给定名称的 bean。在内部查找 bean 定义的注册表,并返回相应的结果。 |
isSingleton(String name) | 检查具有给定名称的 bean 是否为 singleton。返回 true 表示单例,false 表示非单例。根据定义中的作用域信息确定 bean 是否为 singleton。 |
isPrototype(String name) | 检查具有给定名称的 bean 是否为 prototype(原型)。返回 true 表示原型,false 表示非原型。根据定义中的作用域信息确定 bean 是否为 prototype。 |
getType(String name) | 获取具有给定名称的 bean 的类型。查找 bean 的定义,并返回相应的 bean 类型信息。 |
getAliases(String name) | 获取具有给定名称的 bean 的别名(如果存在)。别名是指在容器中注册的其他名称,可以用来引用相同的 bean 实例。查找 bean 的定义,并返回相应的别名列表。 |
(二)基础特性总结
特性 | 描述 |
---|---|
Bean 实例管理 | 管理应用程序中的各种 bean 实例。提供获取、检查和操作 bean 实例的方法。 |
Bean 实例化和初始化 | 根据配置信息实例化和初始化 bean。根据配置信息找到相应的 bean 定义,并进行实例化和初始化。 |
支持不同的作用域 | 支持 singleton(单例)和 prototype(原型)等不同作用域。提供方法检查指定 bean 的作用域,并根据需要获取相应作用域的 bean 实例。 |
类型信息获取 | 提供方法获取 bean 的类型信息。允许获取指定名称的 bean 的类型。 |
别名管理 | 支持别名管理,允许为 bean 定义设置多个别名。提供方法获取指定 bean 的所有别名列表。 |
三、HierarchicalBeanFactory(分层 Bean 工厂)
(一)源码展示
HierarchicalBeanFactory
接口是 BeanFactory
接口的子接口之一,定义了一种层次化的 BeanFactory 结构,可以用于实现 bean 定义的继承和覆盖。以下是 接口的部分源码展示:
java
public interface HierarchicalBeanFactory extends BeanFactory {
// 获取该 BeanFactory 的父级 BeanFactory
@Nullable
BeanFactory getParentBeanFactory();
// 判断该 BeanFactory 是否包含给定名称的本地 bean 定义
boolean containsLocalBean(@NonNull String name);
}
(二)理解设计
HierarchicalBeanFactory
接口设计的核心理念在于提供一种层次化的 bean 定义管理机制,允许在多个 BeanFactory 之间建立父子关系,实现 bean 定义的继承和覆盖。
-
继承与重用:通过允许多个 BeanFactory 之间建立父子关系,子 BeanFactory 可以继承父 BeanFactory 中定义的 bean,从而实现 bean 定义的重用,有利于提高代码的可重用性和可维护性,因为可以将通用的 bean 定义定义在父 BeanFactory 中,而在子 BeanFactory 中只需定义特定的、与父 BeanFactory 不同的 bean。
-
覆盖与定制:除了继承外,子 BeanFactory 还可以覆盖父 BeanFactory 中的 bean 定义,以满足特定的业务需求或定制化需求,使得在不同的环境下可以灵活地覆盖和定制 bean 定义,从而实现更高级别的定制化和灵活性。
-
解耦与模块化 :
HierarchicalBeanFactory
的设计有助于实现组件之间的解耦和模块化。通过将不同的 bean 定义放置在不同的 BeanFactory 中,可以将不同的组件划分为独立的模块,从而降低组件之间的耦合度,提高代码的可维护性和可扩展性。 -
配置灵活性 :
HierarchicalBeanFactory
提供了一种灵活的配置机制,允许在不同层次的 BeanFactory 中进行不同程度的配置。这使得可以根据实际需求灵活地配置不同层次的 BeanFactory,从而满足不同环境下的配置需求,提高了应用程序的适应性和灵活性。 -
集成与扩展 :
HierarchicalBeanFactory
设计的灵活性使得可以轻松地集成和扩展现有的 BeanFactory 结构。通过建立新的子 BeanFactory 或者替换现有的父 BeanFactory,可以方便地扩展和定制 BeanFactory 的结构,以满足不同的业务需求或者技术需求。
HierarchicalBeanFactory
的设计充分体现了 Spring 框架的核心理念:依赖注入、松耦合、模块化和可扩展性。通过提供一种层次化的 bean 定义管理机制,使得可以更加灵活地管理和配置 bean,从而实现更加健壮和灵活的应用程序。
(三)实际操作分析
假设我们有一个 Web 应用程序,其中有两个配置文件 applicationContext.xml
和 webApplicationContext.xml
,分别定义了应用程序的核心组件和 Web 相关的组件。
applicationContext.xml
包含了应用程序的核心组件,如数据访问对象、服务、消息处理器等;webApplicationContext.xml
包含了与 Web 相关的组件,如控制器、视图解析器、拦截器等。
在这种情况下,我们可以使用 HierarchicalBeanFactory
来管理这两个配置文件中的 bean 定义。具体实现如下:
java
public class MainApplicationContext implements HierarchicalBeanFactory {
private DefaultListableBeanFactory coreBeanFactory;
private DefaultListableBeanFactory webBeanFactory;
public MainApplicationContext() {
// 初始化核心 BeanFactory
coreBeanFactory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader coreReader = new XmlBeanDefinitionReader(coreBeanFactory);
coreReader.loadBeanDefinitions("classpath:applicationContext.xml");
// 初始化 Web BeanFactory,设置核心 BeanFactory 为父级
webBeanFactory = new DefaultListableBeanFactory(coreBeanFactory);
XmlBeanDefinitionReader webReader = new XmlBeanDefinitionReader(webBeanFactory);
webReader.loadBeanDefinitions("classpath:webApplicationContext.xml");
}
@Override
public BeanFactory getParentBeanFactory() {
return coreBeanFactory;
}
@Override
public boolean containsLocalBean(String name) {
return coreBeanFactory.containsBeanDefinition(name) || webBeanFactory.containsBeanDefinition(name);
}
@Override
public Object getBean(String name) throws BeansException {
try {
return webBeanFactory.getBean(name);
} catch (NoSuchBeanDefinitionException e) {
return coreBeanFactory.getBean(name);
}
}
}
具体验证可以按实际写测试用例来打印自己相关的配置类。
四、ListableBeanFactory(可列表的 Bean 工厂)
ListableBeanFactory
是 Spring 框架中的另一个重要接口,它是 BeanFactory
接口的子接口之一。与 BeanFactory
不同的是,ListableBeanFactory
不仅可以获取单个的 bean 实例,还可以获取 bean 的列表,并提供了更丰富的检索功能。
(一)源码展示
ListableBeanFactory
接口通过源码中这些方法提供了一种便捷的方式来获取 bean 实例列表,使得应用程序可以更加灵活地管理和操作 bean 实例。通过调用这些方法,可以快速地获取符合条件的 bean 实例,从而方便地进行批量操作、批量注册等操作。
java
public interface ListableBeanFactory extends BeanFactory {
// 根据类型获取所有匹配的 bean 实例
<T> Map<String, T> getBeansOfType(@Nullable Class<T> type) throws BeansException;
// 获取所有 bean 的名称
String[] getBeanDefinitionNames();
// 根据类型获取所有 bean 的名称
String[] getBeanNamesForType(@Nullable Class<?> type);
// 根据类型和包含的父级 BeanFactory 获取所有 bean 的名称
String[] getBeanNamesForType(@Nullable Class<?> type, boolean includeNonSingletons, boolean allowEagerInit);
}
(二)设计选择性列举的目的
设计选择性列举的目的是为了突出重点,集中于最具代表性或最为关键的设计方面,以便更清晰地说明问题或理解设计。通过有选择地列举设计特性,可以避免混淆或过于复杂的描述,使得能够更快速地理解和掌握关键信息。实际应用中可能相对使用的较少,一般我只在不理解有些bean没有生效的时候才会使用下,但是对于其目的而言,不同看源码的人有不同的理解,这里不做区别!
(三)案例举例
简单定义一个服务接口 UserService
, AdminUserService
和RegularUserService是其对应的
两个实现类。通过 ListableBeanFactory
来验证 Spring 容器中的 bean 实例是否符合预期。
定义 UserService
接口及其两个实现类:
java
public interface UserService {
String getUserType();
}
@Component
public class AdminUserService implements UserService {
@Override
public String getUserType() {
return "Admin";
}
}
@Component
public class RegularUserService implements UserService {
@Override
public String getUserType() {
return "Regular";
}
}
创建一个测试类来验证容器中的 bean 实例:
java
@SpringBootTest
public class UserServiceTest {
@Autowired
private ListableBeanFactory beanFactory;
@Test
public void testBeanDefinitionNames() {
// 获取容器中所有的 bean 名称
String[] beanNames = beanFactory.getBeanDefinitionNames();
// 验证容器中是否包含了我们定义的两个 bean 实例的名称
assertTrue(Arrays.asList(beanNames).contains("adminUserService"));
assertTrue(Arrays.asList(beanNames).contains("regularUserService"));
}
@Test
public void testGetBeansOfType() {
// 根据类型获取容器中所有的 UserService 实例
Map<String, UserService> userServiceMap =
beanFactory.getBeansOfType(UserService.class);
// 验证容器中是否包含了我们定义的两个 UserService 实例
assertEquals(2, userServiceMap.size());
assertTrue(userServiceMap.containsKey("adminUserService"));
assertTrue(userServiceMap.containsKey("regularUserService"));
}
}
五、AutowireCapableBeanFactory(可自动装配)
AutowireCapableBeanFactory
是 BeanFactory
接口的子接口之一, 提供了更高级的功能,可以手动实现自动装配、实例化和初始化 bean,以及其他与 bean 相关的操作。
(一)源码展示
AutowireCapableBeanFactory
接口提供了一系列方法,允许手动实现自动装配、实例化和初始化 bean。
java
public interface AutowireCapableBeanFactory extends BeanFactory {
// 将给定的现有 bean 实例应用 autowire bean 属性值
void autowireBean(Object existingBean) throws BeansException;
// 根据给定 bean 的类别自动装配其属性值
Object autowire(Class<?> beanClass, int autowireMode, boolean dependencyCheck) throws BeansException;
// 创建一个新的 bean 实例,并根据定义初始化该 bean
Object createBean(Class<?> beanClass) throws BeansException;
// 根据给定的 bean 类型和 AutowireMode 创建一个新的 bean 实例
Object autowireBeanProperties(Object existingBean, int autowireMode, boolean dependencyCheck) throws BeansException;
// 初始化给定的 bean,应用所有 bean 后处理器
Object initializeBean(Object existingBean, String beanName) throws BeansException;
// 销毁给定的 bean 实例
void destroyBean(Object existingBean);
// 在 bean 工厂关闭时调用,用于销毁所有缓存的单例 bean
void destroySingletons();
}
(二)设计目的和应用
AutowireCapableBeanFactory
接口的设计目的是为了提供更高级的、更灵活的 bean 操作和管理功能。它主要用于那些需要在运行时动态创建、初始化或者自动装配 bean 实例的场景,以及需要更精细地控制 bean 创建过程的场景。
在 Spring 框架中,确实有很多情况下我们不需要直接操作 AutowireCapableBeanFactory
接口。通常情况下,通过配置文件或者注解来定义 bean,并由 Spring 容器负责管理和实例化这些 bean,而无需手动干预 bean 的创建过程。因此,AutowireCapableBeanFactory这个API一般不需要我们去操纵,因为正常开发中不会使用,但如果需要获取AutowireCapableBeanFactory,可以通过ApplicationContext间接获取。
六、ConfigurableBeanFactory(可配置的 Bean 工厂)
ConfigurableBeanFactory
接口提供了一些方法来配置 Bean 工厂的行为和属性,使得我们可以动态地管理和调整 Bean 工厂的配置,从而更好地满足应用程序的需求。通过对 Bean 工厂的配置,可以实现更灵活、更定制化的 Bean 管理方式。
(一)源码展示
ConfigurableBeanFactory
接口提供了一系列操作 Bean 工厂的方法,使得我们可以动态地管理和调整 Bean 工厂的配置。
java
public interface ConfigurableBeanFactory extends HierarchicalBeanFactory, SingletonBeanRegistry {
// 设置父 Bean 工厂
void setParentBeanFactory(BeanFactory parentBeanFactory) throws IllegalStateException;
// 设置类加载器
void setBeanClassLoader(ClassLoader beanClassLoader);
// 获取类加载器
ClassLoader getBeanClassLoader();
// 设置是否缓存 bean 的元数据
void setCacheBeanMetadata(boolean cacheBeanMetadata);
// 是否缓存 bean 的元数据
boolean isCacheBeanMetadata();
// 设置 Bean 表达式解析器
void setBeanExpressionResolver(BeanExpressionResolver resolver);
// 获取 Bean 表达式解析器
BeanExpressionResolver getBeanExpressionResolver();
// 设置属性编辑器注册表
void setPropertyEditorRegistrar(PropertyEditorRegistrar registrar);
// 获取属性编辑器注册表
PropertyEditorRegistrar getPropertyEditorRegistrar();
// 添加 BeanPostProcessor 实例
void addBeanPostProcessor(BeanPostProcessor beanPostProcessor);
// 注册一个 Scope,用于管理作用域
void registerScope(String scopeName, Scope scope);
// 获取注册的 Scope
Scope getRegisteredScope(String scopeName);
// 获取当前 BeanFactory 使用的作用域集合
String[] getRegisteredScopeNames();
// 注册一个 BeanDefinition,将其添加到 BeanFactory 中
void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException;
// 移除指定名称的 BeanDefinition
void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
// 获取指定名称的 BeanDefinition
BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
// 判断是否包含指定名称的 BeanDefinition
boolean containsBeanDefinition(String beanName);
// 获取所有的 BeanDefinition 的名称
String[] getBeanDefinitionNames();
}
(二)思考使用
对之前的UserService
接口和两个实现类:AdminUserService
和 RegularUserService
。使用 ConfigurableBeanFactory
来注册 Bean 定义,并配置 Bean 的作用域和属性。
创建一个配置类 BeanConfig
,在其中使用 ConfigurableBeanFactory
注册 Bean 定义并配置作用域:
java
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
@Configuration
public class BeanConfig {
@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) // 设置作用域为原型
public UserService regularUserService() {
return new RegularUserService();
}
@Bean
@Scope(ConfigurableBeanFactory.SCOPE_SINGLETON) // 设置作用域为单例
public UserService adminUserService() {
return new AdminUserService();
}
}
regularUserService()
方法配置了作用域为原型,即每次请求该 Bean 时都会创建一个新的实例;而 adminUserService()
方法配置了作用域为单例,即整个应用程序中只会创建一个实例。创建一个测试类来验证配置是否生效:
java
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class UserServiceTest {
@Autowired
private UserService regularUserService;
@Autowired
private UserService adminUserService;
@Test
public void testBeanScope() {
UserService user1 = regularUserService;
UserService user2 = regularUserService;
UserService user3 = adminUserService;
UserService user4 = adminUserService;
// 验证作用域是否生效
assertNotSame(user1, user2); // 不同的请求应该返回不同的实例
assertSame(user3, user4); // 单例作用域应该返回相同的实例
}
}
其他暂时先不做分析应用了。
参考文章
BeanFactory (Spring Framework 6.1.5 API)
Guide to the Spring BeanFactory | Baeldung
https://www.youtube.com/watch?v=tH6rd_OkClM
【Spring源码分析】带你正视一下Spring祖容器之BeanFactory的原理与功能分析(1)_spring_洛神灬殇_InfoQ写作社区
https://www.cnblogs.com/zrtqsk/p/4028453.html
Spring源码分析之BeanFactory体系结构.md-阿里云开发者社区
Spring-BeanFactory源码分析(一)_setcurrentlyincreation-CSDN博客
Spring源码解析:BeanFactory深入理解-CSDN博客
BeanFactory getBean源码分析 | 奕林的技术博客