From 41854642403f4a95c88508964a3f6f87bf6e7279 Mon Sep 17 00:00:00 2001 From: xuchengsheng Date: Tue, 28 Nov 2023 16:17:07 +0800 Subject: [PATCH] =?UTF-8?q?BeanFactory=E6=8E=A5=E5=8F=A3=E6=BA=90=E7=A0=81?= =?UTF-8?q?=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 | 463 +++++++++++++++++- .../java/com/xcs/spring/BeanFactoryDemo.java | 50 +- 3 files changed, 479 insertions(+), 36 deletions(-) diff --git a/README.md b/README.md index 616c437..a3248f8 100644 --- a/README.md +++ b/README.md @@ -121,7 +121,7 @@ - Bean工厂 - - `BeanFactory`:Spring的核心接口,提供对Bean的配置、创建、管理的基本功能。 + - [`BeanFactory`](spring-factory/spring-factory-beanFactory/README.md):Spring的核心接口,提供对Bean的配置、创建、管理的基本功能。 - `ListableBeanFactory`:支持按类型获取Bean的集合。 diff --git a/spring-factory/spring-factory-beanFactory/README.md b/spring-factory/spring-factory-beanFactory/README.md index 9540f16..2755214 100644 --- a/spring-factory/spring-factory-beanFactory/README.md +++ b/spring-factory/spring-factory-beanFactory/README.md @@ -1,21 +1,480 @@ ## BeanFactory +- [BeanFactory](#beanfactory) + - [一、基本信息](#一基本信息) + - [二、基本描述](#二基本描述) + - [四、主要功能](#四主要功能) + - [五、接口源码](#五接口源码) + - [六、主要实现](#六主要实现) + - [七、最佳实践](#七最佳实践) + - [八、与其他组件的关系](#八与其他组件的关系) + - [九、常见问题](#九常见问题) + + ### 一、基本信息 ✒️ **作者** - Lex 📝 **博客** - [掘金](https://juejin.cn/user/4251135018533068/posts) 📚 **源码地址** - [github](https://github.com/xuchengsheng/spring-reading) ### 二、基本描述 - +`BeanFactory`接口是Spring框架中IoC容器的核心接口,定义了一套用于管理和获取Java对象实例的标准机制。通过`getBean`方法,可以按名称从容器中检索Bean实例,而`containsBean`方法用于检查容器中是否存在指定名称的Bean。提供的`getType`方法允许获取指定Bean名称的类型信息,而`isSingleton`方法则用于判断指定Bean是否为单例。该接口支持延迟加载,有助于提高性能。虽然`BeanFactory`是IoC容器的基础,但在实际应用中,通常使用`ApplicationContext`接口,它继承自`BeanFactory`并提供了更多高级特性,包括事件发布、AOP、国际化等,使得开发者更容易构建灵活且功能强大的应用。 ### 四、主要功能 +1. **获取Bean** + + + `BeanFactory` 提供了 `getBean(String name)` 方法,用于从容器中获取指定名称的Bean实例。这使得我们可以通过配置文件或注解将Bean定义在容器中,并在需要时获取它们。 + +2. **检查是否包含Bean** + + + 通过 `containsBean(String name)` 方法,我们可以检查容器是否包含指定名称的Bean。这对于避免重复定义相同名称的Bean以及检查Bean是否已被注册很有用。 + +3. **获取Bean类型** + + + 使用 `getType(String name)` 方法,我们可以获取指定名称的Bean的类型信息。这允许在运行时动态地了解Bean的类型,从而采取相应的处理措施。 + +4. **判断Bean是否为单例** + + + 通过 `isSingleton(String name)` 方法,我们可以判断指定名称的Bean是否为单例。这对于了解Bean的作用域,以及是否在容器中共享同一个实例,具有重要意义。 + ### 五、接口源码 +`BeanFactory`接口是Spring框架中负责管理和获取Java对象(即Bean)的根接口,作为Bean容器的基本客户端视图。它集中了应用程序组件的配置,支持不同类型的Bean实例,提供丰富的Bean生命周期管理和依赖注入功能,同时支持工厂之间的层次结构。通过这一接口,Spring实现了控制反转(IoC)和依赖注入,为构建灵活、可维护的应用程序提供了基础。 + +```java +/** + * Spring bean 容器访问的根接口。 + * + *

这是 bean 容器的基本客户端视图; + * 针对特定目的,还提供了其他接口,如 {@link ListableBeanFactory} 和 + * {@link org.springframework.beans.factory.config.ConfigurableBeanFactory}。 + * + *

此接口由包含多个 bean 定义的对象实现,每个 bean 定义都由字符串名称唯一标识。根据 bean 定义, + * 工厂将返回包含对象的独立实例(原型设计模式)或单个共享实例 + * (Singleton 设计模式的一种更好的替代,其中实例是工厂范围内的单例)。将返回哪种类型的实例取决于 + * bean 工厂的配置:API 是相同的。从 Spring 2.0 开始,根据具体的应用上下文,还可以使用进一步的范围 + * (例如 Web 环境中的 "request" 和 "session" 范围)。 + * + *

这种方法的要点是,BeanFactory 是应用程序组件的中央注册表,集中配置应用程序组件 + * (例如,不再需要单独的对象读取属性文件)。有关此方法优点的讨论,请参阅《Expert One-on-One + * J2EE Design and Development》的第 4 章和第 11 章。 + * + *

请注意,通常最好依赖于依赖注入("推"配置)通过 setter 或构造函数配置应用程序对象, + * 而不是使用任何形式的 "拉" 配置,如 BeanFactory 查找。Spring 的依赖注入功能使用此 BeanFactory + * 接口及其子接口实现。通常,BeanFactory 将加载存储在配置源中的 bean 定义(例如 XML 文档), + * 并使用 {@code org.springframework.beans} 包来配置这些 bean。但是,实现可以简单地直接在 + * Java 代码中根据需要返回它创建的 Java 对象。关于定义可能存储在何处的约束没有限制:LDAP、 + * RDBMS、XML、属性文件等。鼓励实现支持 bean 之间的引用(依赖注入)。 + * + *

与 {@link ListableBeanFactory} 中的方法不同,此接口中的所有操作还将检查 + * 父工厂,如果这是 {@link HierarchicalBeanFactory}。如果在此工厂实例中找不到 bean, + * 将询问直接父工厂。在此工厂实例中的 bean 应该覆盖任何父工厂中具有相同名称的 bean。 + * + *

Bean 工厂实现应尽可能支持标准的 bean 生命周期接口。初始化方法及其标准顺序的完整集合是: + *

    + *
  1. BeanNameAware 的 {@code setBeanName} + *
  2. BeanClassLoaderAware 的 {@code setBeanClassLoader} + *
  3. BeanFactoryAware 的 {@code setBeanFactory} + *
  4. EnvironmentAware 的 {@code setEnvironment} + *
  5. EmbeddedValueResolverAware 的 {@code setEmbeddedValueResolver} + *
  6. ResourceLoaderAware 的 {@code setResourceLoader} + * (仅在运行在应用程序上下文中时适用) + *
  7. ApplicationEventPublisherAware 的 {@code setApplicationEventPublisher} + * (仅在运行在应用程序上下文中时适用) + *
  8. MessageSourceAware 的 {@code setMessageSource} + * (仅在运行在应用程序上下文中时适用) + *
  9. ApplicationContextAware 的 {@code setApplicationContext} + * (仅在运行在应用程序上下文中时适用) + *
  10. ServletContextAware 的 {@code setServletContext} + * (仅在运行在 Web 应用程序上下文中时适用) + *
  11. BeanPostProcessors 的 {@code postProcessBeforeInitialization} 方法 + *
  12. InitializingBean 的 {@code afterPropertiesSet} + *
  13. 自定义 {@code init-method} 定义 + *
  14. BeanPostProcessors 的 {@code postProcessAfterInitialization} 方法 + *
+ * + *

在关闭 bean 工厂时,以下生命周期方法适用: + *

    + *
  1. DestructionAwareBeanPostProcessors 的 {@code postProcessBeforeDestruction} 方法 + *
  2. DisposableBean 的 {@code destroy} + *
  3. 自定义 {@code destroy-method} 定义 + *
+ * + * @author Rod Johnson + * @author Juergen Hoeller + * @author Chris Beams + * @since 13 April 2001 + * @see BeanNameAware#setBeanName + * @see BeanClassLoaderAware#setBeanClassLoader + * @see BeanFactoryAware#setBeanFactory + * @see org.springframework.context.EnvironmentAware#setEnvironment + * @see org.springframework.context.EmbeddedValueResolverAware#setEmbeddedValueResolver + * @see org.springframework.context.ResourceLoaderAware#setResourceLoader + * @see org.springframework.context.ApplicationEventPublisherAware#setApplicationEventPublisher + * @see org.springframework.context.MessageSourceAware#setMessageSource + * @see org.springframework.context.ApplicationContextAware#setApplicationContext + * @see org.springframework.web.context.ServletContextAware#setServletContext + * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization + * @see InitializingBean#afterPropertiesSet + * @see org.springframework.beans.factory.support.RootBeanDefinition#getInitMethodName + * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization + * @see org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor#postProcessBeforeDestruction + * @see DisposableBean#destroy + * @see org.springframework.beans.factory.support.RootBeanDefinition#getDestroyMethodName + */ +public interface BeanFactory { + + /** + * 用于取消引用 {@link FactoryBean} 实例并将其与由 FactoryBean 创建的 bean 区分开。 + * 例如,如果名为 {@code myJndiObject} 的 bean 是 FactoryBean,则获取 {@code &myJndiObject} + * 将返回工厂,而不是工厂返回的实例。 + */ + String FACTORY_BEAN_PREFIX = "&"; + + /** + * 返回指定 bean 的实例,该实例可以是共享的或独立的。 + *

此方法允许将 Spring BeanFactory 用作替代 Singleton 或 Prototype 设计模式。 + * 在单例 bean 的情况下,调用者可以保留对返回对象的引用。 + *

将别名转换回相应的规范 bean 名称。 + *

如果在此工厂实例中找不到 bean,则将询问父工厂。 + * @param name 要检索的 bean 的名称 + * @return bean 的实例 + * @throws NoSuchBeanDefinitionException 如果没有具有指定名称的 bean + * @throws BeansException 如果无法获取 bean + */ + Object getBean(String name) throws BeansException; + + /** + * 返回指定 bean 的实例,该实例可以是共享的或独立的。 + *

与 {@link #getBean(String)} 行为相同,但通过抛出 BeanNotOfRequiredTypeException + * 来提供类型安全性。这意味着与 {@link #getBean(String)} 可能发生的正确类型转换上不会抛出 ClassCastException。 + *

将别名转换回相应的规范 bean 名称。 + *

如果在此工厂实例中找不到 bean,则将询问父工厂。 + * @param name 要检索的 bean 的名称 + * @param requiredType bean 必须匹配的类型;可以是接口或超类 + * @return bean 的实例 + * @throws NoSuchBeanDefinitionException 如果没有这样的 bean 定义 + * @throws BeanNotOfRequiredTypeException 如果 bean 不是所需类型 + * @throws BeansException 如果无法创建 bean + */ + T getBean(String name, Class requiredType) throws BeansException; + + /** + * 返回指定 bean 的实例,该实例可以是共享的或独立的。 + *

允许指定显式构造函数参数/工厂方法参数,覆盖 bean 定义中指定的默认参数(如果有)。 + * @param name 要检索的 bean 的名称 + * @param args 在使用显式参数创建 bean 实例时使用的参数 + * (仅在创建新实例而不是检索现有实例时应用) + * @return bean 的实例 + * @throws NoSuchBeanDefinitionException 如果没有这样的 bean 定义 + * @throws BeanDefinitionStoreException 如果给定参数但受影响的 bean 不是原型 + * @throws BeansException 如果无法创建 bean + * @since 2.5 + */ + Object getBean(String name, Object... args) throws BeansException; + + /** + * 返回与给定对象类型唯一匹配的 bean 实例(如果存在)。 + *

此方法进入 {@link ListableBeanFactory} 按类型查找领域, + * 但也可以根据给定类型的名称将其转换为传统的按名称查找。 + * 要在一组 bean 中执行更广泛的检索操作,请使用 {@link ListableBeanFactory} 和/或 {@link BeanFactoryUtils}。 + * @param requiredType bean 必须匹配的类型;可以是接口或超类 + * @return 匹配所需类型的单个 bean 的实例 + * @throws NoSuchBeanDefinitionException 如果没有找到给定类型的 bean + * @throws NoUniqueBeanDefinitionException 如果找到给定类型的多个 bean + * @throws BeansException 如果无法创建 bean + * @since 3.0 + * @see ListableBeanFactory + */ + T getBean(Class requiredType) throws BeansException; + + /** + * 返回指定 bean 的实例,该实例可以是共享的或独立的。 + *

允许指定显式构造函数参数/工厂方法参数,覆盖 bean 定义中指定的默认参数(如果有)。 + *

此方法进入 {@link ListableBeanFactory} 按类型查找领域, + * 但也可以根据给定类型的名称将其转换为传统的按名称查找。 + * 要在一组 bean 中执行更广泛的检索操作,请使用 {@link ListableBeanFactory} 和/或 {@link BeanFactoryUtils}。 + * @param requiredType bean 必须匹配的类型;可以是接口或超类 + * @param args 在使用显式参数创建 bean 实例时使用的参数 + * (仅在创建新实例而不是检索现有实例时应用) + * @return bean 的实例 + * @throws NoSuchBeanDefinitionException 如果没有这样的 bean 定义 + * @throws BeanDefinitionStoreException 如果给定参数但受影响的 bean 不是原型 + * @throws BeansException 如果无法创建 bean + * @since 4.1 + */ + T getBean(Class requiredType, Object... args) throws BeansException; + + /** + * 返回指定 bean 的提供程序,允许进行延迟的按需检索实例,包括可用性和唯一性选项。 + * @param requiredType bean 必须匹配的类型;可以是接口或超类 + * @return 相应的提供程序句柄 + * @since 5.1 + * @see #getBeanProvider(ResolvableType) + */ + ObjectProvider getBeanProvider(Class requiredType); + + /** + * 返回指定 bean 的提供程序,允许进行延迟的按需检索实例,包括可用性和唯一性选项。 + * @param requiredType bean 必须匹配的类型;可以是泛型类型声明。 + * 请注意,此处不支持集合类型,与反射注入点形成对比。要以编程方式检索与特定类型匹配的 bean 列表,请在此处指定实际 bean 类型, + * 然后随后使用 {@link ObjectProvider#orderedStream()} 或其惰性流/迭代选项。 + * @return 相应的提供程序句柄 + * @since 5.1 + * @see ObjectProvider#iterator() + * @see ObjectProvider#stream() + * @see ObjectProvider#orderedStream() + */ + ObjectProvider getBeanProvider(ResolvableType requiredType); + + /** + * 此 bean 工厂是否包含具有给定名称的 bean 定义或外部注册的单例实例? + *

如果给定的名称是一个别名,它将被转换回相应的规范 bean 名称。 + *

如果此工厂是分层的,如果在此工厂实例中找不到 bean,则将询问任何父工厂。 + *

如果找到与给定名称匹配的 bean 定义或单例实例, + * 无论指定的 bean 定义是具体的还是抽象的,是懒加载的还是急加载的,是否在范围内,此方法都将返回 {@code true}。 + * 因此,请注意,此方法的 {@code true} 返回值不一定表示 {@link #getBean} + * 将能够为相同名称获取实例。 + * @param name 要查询的 bean 的名称 + * @return 是否存在具有给定名称的 bean + */ + boolean containsBean(String name); + + /** + * 此 bean 是否为共享单例?也就是说,{@link #getBean} 是否始终返回相同的实例? + *

注意:此方法返回 {@code false} 不清楚地指示独立的实例。 + * 它表示非单例实例,这可能对应于作用域 bean。使用 {@link #isPrototype} 操作明确检查独立实例。 + *

将别名转换回相应的规范 bean 名称。 + *

如果在此工厂实例中找不到 bean,则将询问父工厂。 + * @param name 要查询的 bean 的名称 + * @return 此 bean 是否对应于单例实例 + * @throws NoSuchBeanDefinitionException 如果没有具有给定名称的 bean + * @see #getBean + * @see #isPrototype + */ + boolean isSingleton(String name) throws NoSuchBeanDefinitionException; + + /** + * 此 bean 是否为原型?也就是说,{@link #getBean} 是否始终返回独立的实例? + *

注意:此方法返回 {@code false} 不清楚地指示单例对象。 + * 它表示非独立实例,这可能对应于作用域 bean。使用 {@link #isSingleton} 操作明确检查共享单例实例。 + *

将别名转换回相应的规范 bean 名称。 + *

如果在此工厂实例中找不到 bean,则将询问父工厂。 + * @param name 要查询的 bean 的名称 + * @return 此 bean 是否始终生成独立实例 + * @throws NoSuchBeanDefinitionException 如果没有具有给定名称的 bean + * @since 2.0.3 + * @see #getBean + * @see #isSingleton + */ + boolean isPrototype(String name) throws NoSuchBeanDefinitionException; + + /** + * 检查具有给定名称的 bean 是否与指定类型匹配。 + * 更具体地说,检查对给定名称的 {@link #getBean} 调用是否会返回可分配给指定目标类型的对象。 + *

将别名转换回相应的规范 bean 名称。 + *

如果在此工厂实例中找不到 bean,则将询问父工厂。 + * @param name 要查询的 bean 的名称 + * @param typeToMatch 要匹配的类型(作为 {@code ResolvableType}) + * @return 如果 bean 类型匹配,则为 {@code true}, + * 如果不匹配或尚不能确定,则为 {@code false} + * @throws NoSuchBeanDefinitionException 如果没有具有给定名称的 bean + * @since 4.2 + * @see #getBean + * @see #getType + */ + boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException; + + /** + * 检查具有给定名称的 bean 是否与指定类型匹配。 + * 更具体地说,检查对给定名称的 {@link #getBean} 调用是否会返回可分配给指定目标类型的对象。 + *

将别名转换回相应的规范 bean 名称。 + *

如果在此工厂实例中找不到 bean,则将询问父工厂。 + * @param name 要查询的 bean 的名称 + * @param typeToMatch 要匹配的类型(作为 {@code Class}) + * @return 如果 bean 类型匹配,则为 {@code true}, + * 如果不匹配或尚不能确定,则为 {@code false} + * @throws NoSuchBeanDefinitionException 如果没有具有给定名称的 bean + * @since 2.0.1 + * @see #getBean + * @see #getType + */ + boolean isTypeMatch(String name, Class typeToMatch) throws NoSuchBeanDefinitionException; + + /** + * 确定具有给定名称的 bean 的类型。 + * 更具体地说,确定 {@link #getBean} 对于给定名称将返回的对象的类型。 + *

对于 {@link FactoryBean},返回 FactoryBean 创建的对象的类型,由 {@link FactoryBean#getObjectType()} 公开。 + * 这可能导致以前未初始化的 {@code FactoryBean} 的初始化(请参阅 {@link #getType(String, boolean)})。 + *

将别名转换回相应的规范 bean 名称。 + *

如果在此工厂实例中找不到 bean,则将询问父工厂。 + * @param name 要查询的 bean 的名称 + * @return bean 的类型,如果无法确定则为 {@code null} + * @throws NoSuchBeanDefinitionException 如果没有具有给定名称的 bean + * @since 1.1.2 + * @see #getBean + * @see #isTypeMatch + */ + @Nullable + Class getType(String name) throws NoSuchBeanDefinitionException; + + /** + * 确定具有给定名称的 bean 的类型。 + * 更具体地说,确定 {@link #getBean} 对于给定名称将返回的对象的类型。 + *

对于 {@link FactoryBean},返回 FactoryBean 创建的对象的类型,由 {@link FactoryBean#getObjectType()} 公开。 + * 根据 {@code allowFactoryBeanInit} 标志的不同,如果没有提供早期类型信息,则可能导致以前未初始化的 {@code FactoryBean} 的初始化。 + *

将别名转换回相应的规范 bean 名称。 + *

如果在此工厂实例中找不到 bean,则将询问父工厂。 + * @param name 要查询的 bean 的名称 + * @param allowFactoryBeanInit 是否可能为了确定其对象类型而初始化 {@code FactoryBean} + * @return bean 的类型,如果无法确定则为 {@code null} + * @throws NoSuchBeanDefinitionException 如果没有具有给定名称的 bean + * @since 5.2 + * @see #getBean + * @see #isTypeMatch + */ + @Nullable + Class getType(String name, boolean allowFactoryBeanInit) throws NoSuchBeanDefinitionException; + + /** + * 返回给定 bean 名称的别名,如果有的话。 + *

在 {@link #getBean} 调用中,所有这些别名都指向相同的 bean。 + *

如果给定的名称是别名,则将返回相应的原始 bean 名称和其他别名(如果有的话), + * 原始 bean 名称将是数组中的第一个元素。 + *

如果在此工厂实例中找不到 bean,则将询问父工厂。 + * @param name 要检查别名的 bean 名称 + * @return 别名,如果没有则为空数组 + * @see #getBean + */ + String[] getAliases(String name); + +} +``` + ### 六、主要实现 ++ `DefaultListableBeanFactory` + + `DefaultListableBeanFactory`是Spring框架中实现`BeanFactory`接口的关键类之一,负责注册、管理和初始化应用程序中的所有Bean定义。它支持依赖注入、不同作用域的Bean管理、处理`FactoryBean`、层次性容器、以及各种生命周期回调等功能,是Spring IoC容器的核心实现,提供了灵活而强大的Bean管理和配置机制。 + ### 七、最佳实践 +使用`BeanFactory`接口的不同方法来操作和查询Spring容器中的Bean,涵盖了获取Bean、类型判断、别名查询等功能。 + +```java +public class BeanFactoryDemo { + + public static void main(String[] args) { + // 创建 BeanFactory + BeanFactory beanFactory = new AnnotationConfigApplicationContext(MyBean.class).getBeanFactory(); + + // 根据名称获取 bean + Object bean = beanFactory.getBean("myBean"); + System.out.println("通过名称获取Bean: " + bean); + + // 获取 bean 的 ObjectProvider + ObjectProvider objectProvider = beanFactory.getBeanProvider(MyBean.class); + System.out.println("获取Bean的ObjectProvider: " + objectProvider); + + // 获取 bean 的类型 + Class beanType = beanFactory.getType("myBean"); + System.out.println("获取Bean的类型: " + beanType); + + // 判断是否包含某个 bean + boolean containsBean = beanFactory.containsBean("myBean"); + System.out.println("判断是否包含Bean: " + containsBean); + + // 判断 bean 是否为单例 + boolean isSingleton = beanFactory.isSingleton("myBean"); + System.out.println("判断是否为单例: " + isSingleton); + + // 判断 bean 是否为原型 + boolean isPrototype = beanFactory.isPrototype("myBean"); + System.out.println("判断是否为原型: " + isPrototype); + + // 判断 bean 是否匹配指定类型 + boolean isTypeMatch = beanFactory.isTypeMatch("myBean", ResolvableType.forClass(MyBean.class)); + System.out.println("判断是否匹配指定类型: " + isTypeMatch); + + // 获取 bean 的所有别名 + String[] aliases = beanFactory.getAliases("myBean"); + System.out.println("获取Bean的所有别名: " + String.join(", ", aliases)); + } +} +``` + +运行结果发现,容器中成功创建并管理了名为`myBean`的`MyBean`实例,并提供了相应的类型信息、别名等。 + +```java +通过名称获取Bean: com.xcs.spring.bean.MyBean@7b9a4292 +获取Bean的ObjectProvider: org.springframework.beans.factory.support.DefaultListableBeanFactory$1@1aa7ecca +获取Bean的类型: class com.xcs.spring.bean.MyBean +判断是否包含Bean: true +判断是否为单例: true +判断是否为原型: false +判断是否匹配指定类型: true +获取Bean的所有别名: +``` + ### 八、与其他组件的关系 -### 九、常见问题 \ No newline at end of file +1. **ApplicationContext** + + - `ApplicationContext` 是 `BeanFactory` 的子接口之一,提供了更多的企业级功能,是 Spring 应用程序的上下文容器。它扩展了 `BeanFactory`,并在其基础上添加了事件发布、国际化支持、AOP 功能等。 + +2. **ListableBeanFactory** +- `ListableBeanFactory` 是继承自 `BeanFactory` 接口的子接口,它扩展了 `BeanFactory`,提供了更多的方法用于列举 Bean。可以列举所有的 Bean,包括按类型查找、按名称查找、获取所有 Bean 的名称等。 + +3. **ConfigurableBeanFactory** + + - `ConfigurableBeanFactory` 是继承自 `AutowireCapableBeanFactory` 接口的子接口,它扩展了 `BeanFactory`,提供了更多的配置方法。允许配置属性编辑器、作用域、类加载器等。 + +4. **AutowireCapableBeanFactory** + + - `AutowireCapableBeanFactory` 是继承自 `BeanFactory` 接口的子接口,它扩展了 `BeanFactory`,提供了更多的自动装配方法。允许通过构造函数注入、属性注入等方式进行自动装配。 + +5. **SingletonBeanRegistry** +- `SingletonBeanRegistry` 是定义了对单例 Bean 的注册和获取的接口。定义了注册和获取单例 Bean 的方法,允许在容器中注册和获取单例 Bean。 + +6. **BeanDefinitionRegistry** +- `BeanDefinitionRegistry` 定义了对 Bean 定义的注册和获取的接口。允许在容器中注册和获取 Bean 定义,包括根据名称和类型注册 Bean。 + +7. **BeanPostProcessor** +- `BeanPostProcessor` 是一个接口,允许在 Bean 的初始化前后执行自定义的逻辑。`BeanFactory` 通过注册 `BeanPostProcessor` 实现了对 Bean 生命周期的定制。 + +8. **BeanFactoryPostProcessor** + + - `BeanFactoryPostProcessor` 是一个接口,用于在容器实例化任何 Bean 之前修改容器的配置。允许在容器启动时对 `BeanFactory` 进行修改,例如修改属性值、注册新的 Bean 等。 + +### 九、常见问题 + +1. **NoSuchBeanDefinitionException** + + - 在尝试通过 `getBean` 方法获取 Bean 时,抛出 `NoSuchBeanDefinitionException` 异常,表示找不到指定名称的 Bean。可能原因Bean 的名称拼写错误、Bean 没有被正确注册、或者 Bean 的作用域不符合预期。需要检查 Bean 的定义、名称是否正确,并确保 Bean 在容器中被正确注册。 + +2. **BeanCreationException** + + - 在容器初始化或获取 Bean 时,抛出 `BeanCreationException` 异常,表示无法创建指定的 Bean。可能原因Bean 的依赖项无法满足、Bean 构造函数抛出异常、或者其他初始化问题。需要检查 Bean 的依赖关系,确保构造函数和初始化方法不会抛出异常。 + +3. **CircularDependencyException** + + - Spring 容器检测到循环依赖,抛出 `CircularDependencyException` 异常。可能原因类之间存在循环依赖,A 类依赖 B 类,同时 B 类也依赖 A 类。需要重新设计类之间的依赖关系,使用构造函数注入或者 `@Autowired` 注解避免循环依赖。 + +4. **BeanNotOfRequiredTypeException** + + - 在获取 Bean 时,抛出 `BeanNotOfRequiredTypeException` 异常,表示获取到的 Bean 类型与期望的类型不匹配。可能原因获取 Bean 时指定的类型与实际类型不一致。需要检查获取 Bean 的代码,确保指定的类型正确。 + +5. **BeanInitializationException** + + - 在 Bean 初始化过程中,抛出 `BeanInitializationException` 异常,表示初始化时发生了异常。可能原因在初始化方法中发生了异常,可能是依赖项不满足或其他原因。需要检查初始化方法,确保不会抛出异常,或者处理异常情况。 + +6. **BeanCurrentlyInCreationException** + + - 在尝试获取正在创建中的 Bean 时,抛出 `BeanCurrentlyInCreationException` 异常。可能原因存在循环依赖,导致正在创建中的 Bean 尚未完成创建。需要检查类之间的依赖关系,避免循环依赖。 + +7. **NoUniqueBeanDefinitionException** + + - 在按类型获取 Bean 时,存在多个符合条件的 Bean,抛出 `NoUniqueBeanDefinitionException` 异常。可能原因存在多个同类型的 Bean,并且未指定具体的 Bean 名称。需要指定具体的 Bean 名称,或者使用 `@Qualifier` 注解消除歧义。 + +8. **BeanDefinitionStoreException** + + - 在加载 Bean 定义时,抛出 `BeanDefinitionStoreException` 异常,表示无法正确加载 Bean 的定义。可能原因Bean 的定义文件格式错误、路径问题等。需要检查 Bean 的定义文件,确保格式正确,路径正确。 \ No newline at end of file diff --git a/spring-factory/spring-factory-beanFactory/src/main/java/com/xcs/spring/BeanFactoryDemo.java b/spring-factory/spring-factory-beanFactory/src/main/java/com/xcs/spring/BeanFactoryDemo.java index 62a2751..1a3def1 100644 --- a/spring-factory/spring-factory-beanFactory/src/main/java/com/xcs/spring/BeanFactoryDemo.java +++ b/spring-factory/spring-factory-beanFactory/src/main/java/com/xcs/spring/BeanFactoryDemo.java @@ -16,52 +16,36 @@ public class BeanFactoryDemo { // 创建 BeanFactory BeanFactory beanFactory = new AnnotationConfigApplicationContext(MyBean.class).getBeanFactory(); - // 1. 根据名称获取 bean - Object bean1 = beanFactory.getBean("myBean"); - System.out.println("1.通过名称获取Bean: " + bean1); + // 根据名称获取 bean + Object bean = beanFactory.getBean("myBean"); + System.out.println("通过名称获取Bean: " + bean); - // 2. 根据名称和类型获取 bean - MyBean bean2 = beanFactory.getBean("myBean", MyBean.class); - System.out.println("2.通过名称和类型获取Bean: " + bean2); - - // 3. 根据名称和参数获取 bean - Object bean3 = beanFactory.getBean("myBean", "自定义消息"); - System.out.println("3.通过名称和参数获取Bean: " + bean3); - - // 4. 根据类型获取 bean - MyBean bean4 = beanFactory.getBean(MyBean.class); - System.out.println("4.通过类型获取Bean: " + bean4); - - // 5. 根据类型和参数获取 bean - MyBean bean5 = beanFactory.getBean(MyBean.class, "自定义消息"); - System.out.println("5.通过类型和参数获取Bean: " + bean5); - - // 6. 获取 bean 的 ObjectProvider + // 获取 bean 的 ObjectProvider ObjectProvider objectProvider = beanFactory.getBeanProvider(MyBean.class); - System.out.println("6.Bean的ObjectProvider: " + objectProvider.getObject()); + System.out.println("获取Bean的ObjectProvider: " + objectProvider); - // 7. 获取 bean 的类型 + // 获取 bean 的类型 Class beanType = beanFactory.getType("myBean"); - System.out.println("7.Bean的类型: " + beanType); + System.out.println("获取Bean的类型: " + beanType); - // 8. 判断是否包含某个 bean + // 判断是否包含某个 bean boolean containsBean = beanFactory.containsBean("myBean"); - System.out.println("8.是否包含Bean: " + containsBean); + System.out.println("判断是否包含Bean: " + containsBean); - // 9. 判断 bean 是否为单例 + // 判断 bean 是否为单例 boolean isSingleton = beanFactory.isSingleton("myBean"); - System.out.println("9.是否为单例: " + isSingleton); + System.out.println("判断是否为单例: " + isSingleton); - // 10. 判断 bean 是否为原型 + // 判断 bean 是否为原型 boolean isPrototype = beanFactory.isPrototype("myBean"); - System.out.println("10.是否为原型: " + isPrototype); + System.out.println("判断是否为原型: " + isPrototype); - // 11. 判断 bean 是否匹配指定类型 + // 判断 bean 是否匹配指定类型 boolean isTypeMatch = beanFactory.isTypeMatch("myBean", ResolvableType.forClass(MyBean.class)); - System.out.println("11.是否匹配指定类型: " + isTypeMatch); + System.out.println("判断是否匹配指定类型: " + isTypeMatch); - // 12. 获取 bean 的所有别名 + // 获取 bean 的所有别名 String[] aliases = beanFactory.getAliases("myBean"); - System.out.println("12.Bean的所有别名: " + String.join(", ", aliases)); + System.out.println("获取Bean的所有别名: " + String.join(", ", aliases)); } }