目录
一、理解BeanFactory
(一)功能性理解
(二)BeanFactory和它的子接口
(三)BeanFactory的实现类
二、BeanFactory根接口
(一)源码展示和理解
(二)基础特性总结
三、HierarchicalBeanFactory(分层 Bean 工厂)
(一)源码展示
(二)理解设计
(三)实际操作分析
四、ListableBeanFactory(可列表的 Bean 工厂)
(一)源码展示
(二)设计选择性列举的目的
(三)案例举例
五、AutowireCapableBeanFactory(可自动装配)
(一)源码展示
(二)设计目的和应用
六、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 还支持延迟加载、依赖注入和作用域管理等功能,以提高应用程序的性能、可维护性和可扩展性。
(一)源码展示和理解
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 定义的继承和覆盖。以下是 接口的部分源码展示:
public interface HierarchicalBeanFactory extends BeanFactory {// 获取该 BeanFactory 的父级 BeanFactory@NullableBeanFactory 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 定义。具体实现如下:
public class MainApplicationContext implements HierarchicalBeanFactory {private DefaultListableBeanFactory coreBeanFactory;private DefaultListableBeanFactory webBeanFactory;public MainApplicationContext() {// 初始化核心 BeanFactorycoreBeanFactory = 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");}@Overridepublic BeanFactory getParentBeanFactory() {return coreBeanFactory;}@Overridepublic boolean containsLocalBean(String name) {return coreBeanFactory.containsBeanDefinition(name) || webBeanFactory.containsBeanDefinition(name);}@Overridepublic 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 实例,从而方便地进行批量操作、批量注册等操作。
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
接口及其两个实现类:
public interface UserService {String getUserType();
}@Component
public class AdminUserService implements UserService {@Overridepublic String getUserType() {return "Admin";}
}@Component
public class RegularUserService implements UserService {@Overridepublic String getUserType() {return "Regular";}
}
创建一个测试类来验证容器中的 bean 实例:
@SpringBootTest
public class UserServiceTest {@Autowiredprivate ListableBeanFactory beanFactory;@Testpublic void testBeanDefinitionNames() {// 获取容器中所有的 bean 名称String[] beanNames = beanFactory.getBeanDefinitionNames();// 验证容器中是否包含了我们定义的两个 bean 实例的名称assertTrue(Arrays.asList(beanNames).contains("adminUserService"));assertTrue(Arrays.asList(beanNames).contains("regularUserService"));}@Testpublic 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。
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 实例,并根据定义初始化该 beanObject 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 工厂关闭时调用,用于销毁所有缓存的单例 beanvoid 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 工厂的配置。
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);// 获取注册的 ScopeScope getRegisteredScope(String scopeName);// 获取当前 BeanFactory 使用的作用域集合String[] getRegisteredScopeNames();// 注册一个 BeanDefinition,将其添加到 BeanFactory 中void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException;// 移除指定名称的 BeanDefinitionvoid removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;// 获取指定名称的 BeanDefinitionBeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;// 判断是否包含指定名称的 BeanDefinitionboolean containsBeanDefinition(String beanName);// 获取所有的 BeanDefinition 的名称String[] getBeanDefinitionNames();
}
(二)思考使用
对之前的UserService
接口和两个实现类:AdminUserService
和 RegularUserService
。使用 ConfigurableBeanFactory
来注册 Bean 定义,并配置 Bean 的作用域和属性。
创建一个配置类 BeanConfig
,在其中使用 ConfigurableBeanFactory
注册 Bean 定义并配置作用域:
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()
方法配置了作用域为单例,即整个应用程序中只会创建一个实例。创建一个测试类来验证配置是否生效:
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;@SpringBootTest
public class UserServiceTest {@Autowiredprivate UserService regularUserService;@Autowiredprivate UserService adminUserService;@Testpublic 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
BeanFactory体系结构分析 · 进击的java菜鸟
Spring源码分析之BeanFactory体系结构.md-阿里云开发者社区
Spring-BeanFactory源码分析(一)_setcurrentlyincreation-CSDN博客
Spring源码解析:BeanFactory深入理解-CSDN博客
BeanFactory getBean源码分析 | 奕林的技术博客
深入剖析 Spring 核心数据结构:BeanFactory - "地瓜哥"博客网
Spring的IOC,你真的能解释清楚吗? - 掘金