From 4533061e79336a669e815b48eaa9850a21156ba6 Mon Sep 17 00:00:00 2001 From: xuchengsheng Date: Tue, 28 Nov 2023 16:48:33 +0800 Subject: [PATCH] =?UTF-8?q?HierarchicalBeanFactory=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E6=BA=90=E7=A0=81=E5=88=86=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- .../spring-factory-beanFactory/README.md | 24 +-- .../README.md | 160 ++++++++++++++++++ .../spring/HierarchicalBeanFactoryDemo.java | 17 +- 4 files changed, 181 insertions(+), 22 deletions(-) create mode 100644 spring-factory/spring-factory-hierarchicalBeanFactory/README.md diff --git a/README.md b/README.md index a3248f8..13f12b2 100644 --- a/README.md +++ b/README.md @@ -123,7 +123,7 @@ - [`BeanFactory`](spring-factory/spring-factory-beanFactory/README.md):Spring的核心接口,提供对Bean的配置、创建、管理的基本功能。 - - `ListableBeanFactory`:支持按类型获取Bean的集合。 + - [`ListableBeanFactory`](spring-factory/spring-factory-hierarchicalBeanFactory/README.md):支持按类型获取Bean的集合。 - `HierarchicalBeanFactory`:支持父子容器关系,实现Bean定义的层次结构。 diff --git a/spring-factory/spring-factory-beanFactory/README.md b/spring-factory/spring-factory-beanFactory/README.md index 2755214..8814db4 100644 --- a/spring-factory/spring-factory-beanFactory/README.md +++ b/spring-factory/spring-factory-beanFactory/README.md @@ -3,12 +3,12 @@ - [BeanFactory](#beanfactory) - [一、基本信息](#一基本信息) - [二、基本描述](#二基本描述) - - [四、主要功能](#四主要功能) - - [五、接口源码](#五接口源码) - - [六、主要实现](#六主要实现) - - [七、最佳实践](#七最佳实践) - - [八、与其他组件的关系](#八与其他组件的关系) - - [九、常见问题](#九常见问题) + - [三、主要功能](#三主要功能) + - [四、接口源码](#四接口源码) + - [五、主要实现](#五主要实现) + - [六、最佳实践](#六最佳实践) + - [七、与其他组件的关系](#七与其他组件的关系) + - [八、常见问题](#八常见问题) ### 一、基本信息 @@ -19,7 +19,7 @@ `BeanFactory`接口是Spring框架中IoC容器的核心接口,定义了一套用于管理和获取Java对象实例的标准机制。通过`getBean`方法,可以按名称从容器中检索Bean实例,而`containsBean`方法用于检查容器中是否存在指定名称的Bean。提供的`getType`方法允许获取指定Bean名称的类型信息,而`isSingleton`方法则用于判断指定Bean是否为单例。该接口支持延迟加载,有助于提高性能。虽然`BeanFactory`是IoC容器的基础,但在实际应用中,通常使用`ApplicationContext`接口,它继承自`BeanFactory`并提供了更多高级特性,包括事件发布、AOP、国际化等,使得开发者更容易构建灵活且功能强大的应用。 -### 四、主要功能 +### 三、主要功能 1. **获取Bean** @@ -37,7 +37,7 @@ + 通过 `isSingleton(String name)` 方法,我们可以判断指定名称的Bean是否为单例。这对于了解Bean的作用域,以及是否在容器中共享同一个实例,具有重要意义。 -### 五、接口源码 +### 四、接口源码 `BeanFactory`接口是Spring框架中负责管理和获取Java对象(即Bean)的根接口,作为Bean容器的基本客户端视图。它集中了应用程序组件的配置,支持不同类型的Bean实例,提供丰富的Bean生命周期管理和依赖注入功能,同时支持工厂之间的层次结构。通过这一接口,Spring实现了控制反转(IoC)和依赖注入,为构建灵活、可维护的应用程序提供了基础。 @@ -351,12 +351,12 @@ public interface BeanFactory { } ``` -### 六、主要实现 +### 五、主要实现 + `DefaultListableBeanFactory` + `DefaultListableBeanFactory`是Spring框架中实现`BeanFactory`接口的关键类之一,负责注册、管理和初始化应用程序中的所有Bean定义。它支持依赖注入、不同作用域的Bean管理、处理`FactoryBean`、层次性容器、以及各种生命周期回调等功能,是Spring IoC容器的核心实现,提供了灵活而强大的Bean管理和配置机制。 -### 七、最佳实践 +### 六、最佳实践 使用`BeanFactory`接口的不同方法来操作和查询Spring容器中的Bean,涵盖了获取Bean、类型判断、别名查询等功能。 @@ -415,7 +415,7 @@ public class BeanFactoryDemo { 获取Bean的所有别名: ``` -### 八、与其他组件的关系 +### 七、与其他组件的关系 1. **ApplicationContext** @@ -445,7 +445,7 @@ public class BeanFactoryDemo { - `BeanFactoryPostProcessor` 是一个接口,用于在容器实例化任何 Bean 之前修改容器的配置。允许在容器启动时对 `BeanFactory` 进行修改,例如修改属性值、注册新的 Bean 等。 -### 九、常见问题 +### 八、常见问题 1. **NoSuchBeanDefinitionException** diff --git a/spring-factory/spring-factory-hierarchicalBeanFactory/README.md b/spring-factory/spring-factory-hierarchicalBeanFactory/README.md new file mode 100644 index 0000000..f323a88 --- /dev/null +++ b/spring-factory/spring-factory-hierarchicalBeanFactory/README.md @@ -0,0 +1,160 @@ +## HierarchicalBeanFactory + + +### 一、基本信息 + +✒️ **作者** - Lex 📝 **博客** - [掘金](https://juejin.cn/user/4251135018533068/posts) 📚 **源码地址** - [github](https://github.com/xuchengsheng/spring-reading) + +### 二、基本描述 + +`HierarchicalBeanFactory` 接口是Spring框架中的一个接口,用于表示具有层次结构的`BeanFactory`,即支持父子容器的概念。通过继承 `BeanFactory` 接口,它定义了一些方法,使得容器能够组织成为层次结构,其中子容器可以访问父容器的 Bean 定义。 + +### 三、主要功能 + +1. **获取父容器** + + - 通过 `getParentBeanFactory()` 方法,可以获取当前 `BeanFactory` 的父级 `BeanFactory`,允许在子容器中访问和使用父容器中定义的 Bean。 + +2. **本地 Bean 的检查** + + - 通过 `containsLocalBean(String name)` 方法,可以检查当前 `BeanFactory` 是否包含具有给定名称的本地 Bean。本地 Bean 是指在当前容器中定义的 Bean,而不是从父容器继承的。 + +### 四、接口源码 + +`HierarchicalBeanFactory` 接口是由能够成为Spring容器层次结构一部分的Bean工厂实现的子接口。它定义了获取父级Bean工厂和检查本地Bean工厂是否包含指定名称的Bean的方法 + +```java +/** + * 由能够成为层次结构一部分的Bean工厂实现的子接口。 + * + *

对于那些允许以可配置的方式设置父级的Bean工厂, + * 相应的 {@code setParentBeanFactory} 方法可以在 ConfigurableBeanFactory 接口中找到。 + * + * @author Rod Johnson + * @author Juergen Hoeller + * @since 07.07.2003 + * @see org.springframework.beans.factory.config.ConfigurableBeanFactory#setParentBeanFactory + */ +public interface HierarchicalBeanFactory extends BeanFactory { + + /** + * 返回父级Bean工厂,如果没有则返回 {@code null}。 + */ + @Nullable + BeanFactory getParentBeanFactory(); + + /** + * 返回本地Bean工厂是否包含给定名称的Bean, + * 忽略在祖先上下文中定义的Bean。 + *

这是 {@code containsBean} 的替代方法,忽略来自祖先Bean工厂的给定名称的Bean。 + * @param name 要查询的Bean的名称 + * @return 本地工厂中是否定义了具有给定名称的Bean + * @see BeanFactory#containsBean + */ + boolean containsLocalBean(String name); +} +``` + +### 五、主要实现 + +- `DefaultListableBeanFactory` + - `DefaultListableBeanFactory`是Spring框架中实现`BeanFactory`接口的关键类之一,负责注册、管理和初始化应用程序中的所有Bean定义。它支持依赖注入、不同作用域的Bean管理、处理`FactoryBean`、层次性容器、以及各种生命周期回调等功能,是Spring IoC容器的核心实现,提供了灵活而强大的Bean管理和配置机制。 + +### 六、最佳实践 + +创建了一个包含父子层次结构的Spring容器,其中父容器包含一个名为`MyBean`的Bean,子容器继承了父容器并尝试获取这个Bean。代码通过`HierarchicalBeanFactory`接口的方法展示了如何在子容器中访问父容器的Bean,判断本地和整个BeanFactory中是否包含特定名称的Bean,并获取父级BeanFactory。 + +```java +public class HierarchicalBeanFactoryDemo { + + public static void main(String[] args) { + // 创建父级容器 + AnnotationConfigApplicationContext parentContext = new AnnotationConfigApplicationContext(MyBean.class); + // 创建子级容器 + AnnotationConfigApplicationContext childContext = new AnnotationConfigApplicationContext(); + childContext.setParent(parentContext); + + // 在子级 BeanFactory 中获取 bean + HierarchicalBeanFactory childHierarchicalBeanFactory = childContext.getBeanFactory(); + System.out.println("在子级BeanFactory中获取Bean: " + childHierarchicalBeanFactory.getBean(MyBean.class)); + + // 在父级 BeanFactory 中获取 bean + HierarchicalBeanFactory parentHierarchicalBeanFactory = parentContext.getBeanFactory(); + System.out.println("在父级BeanFactory中获取Bean: " + parentHierarchicalBeanFactory.getBean(MyBean.class)); + + // 获取父级 BeanFactory + BeanFactory parentBeanFactory = childHierarchicalBeanFactory.getParentBeanFactory(); + System.out.println("获取父级BeanFactory: " + parentBeanFactory); + + // 判断本地 BeanFactory 是否包含指定名称的 bean + boolean containsLocalBean = childHierarchicalBeanFactory.containsLocalBean("myBean"); + System.out.println("判断本地BeanFactory是否包含指定名称的Bean: " + containsLocalBean); + + // 判断整个 BeanFactory 是否包含指定名称的 bean + boolean containsBean = childHierarchicalBeanFactory.containsBean("myBean"); + System.out.println("判断整个BeanFactory是否包含指定名称的Bean: " + containsBean); + } +} +``` + +运行结果发现,容器层次结构的特性,包括父子容器之间的Bean继承和在不同层次的容器中判断Bean的存在。 + +```java +在子级BeanFactory中获取Bean: com.xcs.spring.bean.MyBean@6379eb +在父级BeanFactory中获取Bean: com.xcs.spring.bean.MyBean@6379eb +获取父级BeanFactory: org.springframework.beans.factory.support.DefaultListableBeanFactory@2f112965: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.event.internalEventListenerProcessor,org.springframework.context.event.internalEventListenerFactory,myBean]; root of factory hierarchy +判断本地BeanFactory是否包含指定名称的Bean: false +判断整个BeanFactory是否包含指定名称的Bean: true +``` + +### 七、与其他组件的关系 + +1. **ApplicationContext接口** + + - `HierarchicalBeanFactory` 接口是 `ApplicationContext` 接口的子接口。因此,任何实现了 `HierarchicalBeanFactory` 的类也是 `ApplicationContext` 的子类。`ApplicationContext` 是 Spring 中应用程序上下文的核心接口,提供了更多的功能,包括事件发布、国际化支持等。 + +2. **ConfigurableApplicationContext接口** + + - `ConfigurableApplicationContext` 是 `ApplicationContext` 的子接口,同时也扩展了 `HierarchicalBeanFactory`。它定义了一些用于配置应用程序上下文的额外方法,例如设置父级上下文、激活和取消激活配置文件等。 + +3. **BeanFactory接口** + + - `HierarchicalBeanFactory` 扩展了 `BeanFactory` 接口,因此它继承了 `BeanFactory` 中定义的许多方法,用于获取和管理 Bean 实例。 + +4. **DefaultListableBeanFactory类** + + - `DefaultListableBeanFactory` 是 Spring 框架中 `HierarchicalBeanFactory` 接口的默认实现类。它实现了 `HierarchicalBeanFactory` 接口,并提供了标准的 `BeanFactory` 功能。`DefaultListableBeanFactory` 也是 `ConfigurableListableBeanFactory` 接口的实现类,进一步增强了配置的能力。 + +5. **BeanDefinition接口** + + - `HierarchicalBeanFactory` 与 `BeanDefinition` 接口密切相关。`BeanDefinition` 定义了 Bean 的元数据,包括类名、属性值、构造函数参数等。在容器层次结构中,`HierarchicalBeanFactory` 负责管理和维护这些 `BeanDefinition`。 + +6. **ApplicationContext层次结构** + + - `HierarchicalBeanFactory` 接口支持 Spring 容器的层次结构。通过父子关系,容器可以继承和覆盖 Bean 定义。这有助于实现模块化和组织化的应用程序架构,不同层次的容器之间可以共享或隔离 Bean。 + +### 八、常见问题 + +1. **Bean名称冲突** + + - 当子容器和父容器中都定义了相同名称的Bean时,可能会导致Bean名称冲突。在设计时,避免在父子容器中定义相同名称的Bean。如果冲突是不可避免的,可以通过在子容器中重新定义Bean来覆盖父容器中的定义。 + +2. **父子容器的初始化顺序** + + - 容器的初始化顺序可能会导致在子容器初始化之前尝试访问父容器中的Bean。我们需要确保在访问子容器中的Bean之前,子容器已经成功初始化。可以使用事件监听器等机制来确保容器的正确初始化顺序。 + +3. **父容器中Bean的更新** + + - 子容器在初始化时会获取父容器中的Bean定义,并且在后续运行时不会再次更新。如果需要动态更新父容器中的Bean定义,可以考虑在特定的时机重新刷新子容器。 + +4. **对父容器中Bean的引用** + + - 子容器中的Bean可以直接引用父容器中的Bean。Spring会自动处理这些引用,确保在子容器中正确注入父容器中的Bean。 + +5. **层次结构的深度** + + - 尽管Spring支持容器层次结构,但在设计时要考虑层次结构的深度。深层次结构可能会导致容器初始化和访问的复杂性,可能影响性能。 + +6. **配置错误** + + - 定期审查配置,确保正确设置了父子容器关系。使用合适的配置和注解来避免潜在的错误。 \ No newline at end of file diff --git a/spring-factory/spring-factory-hierarchicalBeanFactory/src/main/java/com/xcs/spring/HierarchicalBeanFactoryDemo.java b/spring-factory/spring-factory-hierarchicalBeanFactory/src/main/java/com/xcs/spring/HierarchicalBeanFactoryDemo.java index 8a988bc..0bfb59a 100644 --- a/spring-factory/spring-factory-hierarchicalBeanFactory/src/main/java/com/xcs/spring/HierarchicalBeanFactoryDemo.java +++ b/spring-factory/spring-factory-hierarchicalBeanFactory/src/main/java/com/xcs/spring/HierarchicalBeanFactoryDemo.java @@ -14,29 +14,28 @@ public class HierarchicalBeanFactoryDemo { public static void main(String[] args) { // 创建父级容器 AnnotationConfigApplicationContext parentContext = new AnnotationConfigApplicationContext(MyBean.class); - // 创建子级容器 AnnotationConfigApplicationContext childContext = new AnnotationConfigApplicationContext(); childContext.setParent(parentContext); // 在子级 BeanFactory 中获取 bean HierarchicalBeanFactory childHierarchicalBeanFactory = childContext.getBeanFactory(); - System.out.println("1.在子级BeanFactory中获取Bean: " + childHierarchicalBeanFactory.getBean(MyBean.class)); + System.out.println("在子级BeanFactory中获取Bean: " + childHierarchicalBeanFactory.getBean(MyBean.class)); // 在父级 BeanFactory 中获取 bean HierarchicalBeanFactory parentHierarchicalBeanFactory = parentContext.getBeanFactory(); - System.out.println("2.在父级BeanFactory中获取Bean: " + parentHierarchicalBeanFactory.getBean(MyBean.class)); + System.out.println("在父级BeanFactory中获取Bean: " + parentHierarchicalBeanFactory.getBean(MyBean.class)); - // 示例:获取父级 BeanFactory + // 获取父级 BeanFactory BeanFactory parentBeanFactory = childHierarchicalBeanFactory.getParentBeanFactory(); - System.out.println("3.获取父级BeanFactory: " + parentBeanFactory); + System.out.println("获取父级BeanFactory: " + parentBeanFactory); - // 示例:判断本地 BeanFactory 是否包含指定名称的 bean + // 判断本地 BeanFactory 是否包含指定名称的 bean boolean containsLocalBean = childHierarchicalBeanFactory.containsLocalBean("myBean"); - System.out.println("4.判断本地BeanFactory是否包含指定名称的Bean: " + containsLocalBean); + System.out.println("判断本地BeanFactory是否包含指定名称的Bean: " + containsLocalBean); - // 示例:判断整个 BeanFactory 是否包含指定名称的 bean + // 判断整个 BeanFactory 是否包含指定名称的 bean boolean containsBean = childHierarchicalBeanFactory.containsBean("myBean"); - System.out.println("5.判断整个BeanFactory是否包含指定名称的Bean: " + containsBean); + System.out.println("判断整个BeanFactory是否包含指定名称的Bean: " + containsBean); } }