spring-reading./spring-factory/spring-factory-beanFactory/README.md

480 lines
27 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

## 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 容器访问的根接口。
*
* <p>这是 bean 容器的基本客户端视图;
* 针对特定目的,还提供了其他接口,如 {@link ListableBeanFactory} 和
* {@link org.springframework.beans.factory.config.ConfigurableBeanFactory}。
*
* <p>此接口由包含多个 bean 定义的对象实现,每个 bean 定义都由字符串名称唯一标识。根据 bean 定义,
* 工厂将返回包含对象的独立实例(原型设计模式)或单个共享实例
* Singleton 设计模式的一种更好的替代,其中实例是工厂范围内的单例)。将返回哪种类型的实例取决于
* bean 工厂的配置API 是相同的。从 Spring 2.0 开始,根据具体的应用上下文,还可以使用进一步的范围
* (例如 Web 环境中的 "request" 和 "session" 范围)。
*
* <p>这种方法的要点是BeanFactory 是应用程序组件的中央注册表,集中配置应用程序组件
* 例如不再需要单独的对象读取属性文件。有关此方法优点的讨论请参阅《Expert One-on-One
* J2EE Design and Development》的第 4 章和第 11 章。
*
* <p>请注意,通常最好依赖于依赖注入("推"配置)通过 setter 或构造函数配置应用程序对象,
* 而不是使用任何形式的 "拉" 配置,如 BeanFactory 查找。Spring 的依赖注入功能使用此 BeanFactory
* 接口及其子接口实现。通常BeanFactory 将加载存储在配置源中的 bean 定义(例如 XML 文档),
* 并使用 {@code org.springframework.beans} 包来配置这些 bean。但是实现可以简单地直接在
* Java 代码中根据需要返回它创建的 Java 对象。关于定义可能存储在何处的约束没有限制LDAP、
* RDBMS、XML、属性文件等。鼓励实现支持 bean 之间的引用(依赖注入)。
*
* <p>与 {@link ListableBeanFactory} 中的方法不同,此接口中的所有操作还将检查
* 父工厂,如果这是 {@link HierarchicalBeanFactory}。如果在此工厂实例中找不到 bean
* 将询问直接父工厂。在此工厂实例中的 bean 应该覆盖任何父工厂中具有相同名称的 bean。
*
* <p>Bean 工厂实现应尽可能支持标准的 bean 生命周期接口。初始化方法及其标准顺序的完整集合是:
* <ol>
* <li>BeanNameAware 的 {@code setBeanName}
* <li>BeanClassLoaderAware 的 {@code setBeanClassLoader}
* <li>BeanFactoryAware 的 {@code setBeanFactory}
* <li>EnvironmentAware 的 {@code setEnvironment}
* <li>EmbeddedValueResolverAware 的 {@code setEmbeddedValueResolver}
* <li>ResourceLoaderAware 的 {@code setResourceLoader}
* (仅在运行在应用程序上下文中时适用)
* <li>ApplicationEventPublisherAware 的 {@code setApplicationEventPublisher}
* (仅在运行在应用程序上下文中时适用)
* <li>MessageSourceAware 的 {@code setMessageSource}
* (仅在运行在应用程序上下文中时适用)
* <li>ApplicationContextAware 的 {@code setApplicationContext}
* (仅在运行在应用程序上下文中时适用)
* <li>ServletContextAware 的 {@code setServletContext}
* (仅在运行在 Web 应用程序上下文中时适用)
* <li>BeanPostProcessors 的 {@code postProcessBeforeInitialization} 方法
* <li>InitializingBean 的 {@code afterPropertiesSet}
* <li>自定义 {@code init-method} 定义
* <li>BeanPostProcessors 的 {@code postProcessAfterInitialization} 方法
* </ol>
*
* <p>在关闭 bean 工厂时,以下生命周期方法适用:
* <ol>
* <li>DestructionAwareBeanPostProcessors 的 {@code postProcessBeforeDestruction} 方法
* <li>DisposableBean 的 {@code destroy}
* <li>自定义 {@code destroy-method} 定义
* </ol>
*
* @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 的实例,该实例可以是共享的或独立的。
* <p>此方法允许将 Spring BeanFactory 用作替代 Singleton 或 Prototype 设计模式。
* 在单例 bean 的情况下,调用者可以保留对返回对象的引用。
* <p>将别名转换回相应的规范 bean 名称。
* <p>如果在此工厂实例中找不到 bean则将询问父工厂。
* @param name 要检索的 bean 的名称
* @return bean 的实例
* @throws NoSuchBeanDefinitionException 如果没有具有指定名称的 bean
* @throws BeansException 如果无法获取 bean
*/
Object getBean(String name) throws BeansException;
/**
* 返回指定 bean 的实例,该实例可以是共享的或独立的。
* <p>与 {@link #getBean(String)} 行为相同,但通过抛出 BeanNotOfRequiredTypeException
* 来提供类型安全性。这意味着与 {@link #getBean(String)} 可能发生的正确类型转换上不会抛出 ClassCastException。
* <p>将别名转换回相应的规范 bean 名称。
* <p>如果在此工厂实例中找不到 bean则将询问父工厂。
* @param name 要检索的 bean 的名称
* @param requiredType bean 必须匹配的类型;可以是接口或超类
* @return bean 的实例
* @throws NoSuchBeanDefinitionException 如果没有这样的 bean 定义
* @throws BeanNotOfRequiredTypeException 如果 bean 不是所需类型
* @throws BeansException 如果无法创建 bean
*/
<T> T getBean(String name, Class<T> requiredType) throws BeansException;
/**
* 返回指定 bean 的实例,该实例可以是共享的或独立的。
* <p>允许指定显式构造函数参数/工厂方法参数,覆盖 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 实例(如果存在)。
* <p>此方法进入 {@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> T getBean(Class<T> requiredType) throws BeansException;
/**
* 返回指定 bean 的实例,该实例可以是共享的或独立的。
* <p>允许指定显式构造函数参数/工厂方法参数,覆盖 bean 定义中指定的默认参数(如果有)。
* <p>此方法进入 {@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> T getBean(Class<T> requiredType, Object... args) throws BeansException;
/**
* 返回指定 bean 的提供程序,允许进行延迟的按需检索实例,包括可用性和唯一性选项。
* @param requiredType bean 必须匹配的类型;可以是接口或超类
* @return 相应的提供程序句柄
* @since 5.1
* @see #getBeanProvider(ResolvableType)
*/
<T> ObjectProvider<T> getBeanProvider(Class<T> requiredType);
/**
* 返回指定 bean 的提供程序,允许进行延迟的按需检索实例,包括可用性和唯一性选项。
* @param requiredType bean 必须匹配的类型;可以是泛型类型声明。
* 请注意,此处不支持集合类型,与反射注入点形成对比。要以编程方式检索与特定类型匹配的 bean 列表,请在此处指定实际 bean 类型,
* 然后随后使用 {@link ObjectProvider#orderedStream()} 或其惰性流/迭代选项。
* @return 相应的提供程序句柄
* @since 5.1
* @see ObjectProvider#iterator()
* @see ObjectProvider#stream()
* @see ObjectProvider#orderedStream()
*/
<T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType);
/**
* 此 bean 工厂是否包含具有给定名称的 bean 定义或外部注册的单例实例?
* <p>如果给定的名称是一个别名,它将被转换回相应的规范 bean 名称。
* <p>如果此工厂是分层的,如果在此工厂实例中找不到 bean则将询问任何父工厂。
* <p>如果找到与给定名称匹配的 bean 定义或单例实例,
* 无论指定的 bean 定义是具体的还是抽象的,是懒加载的还是急加载的,是否在范围内,此方法都将返回 {@code true}。
* 因此,请注意,此方法的 {@code true} 返回值不一定表示 {@link #getBean}
* 将能够为相同名称获取实例。
* @param name 要查询的 bean 的名称
* @return 是否存在具有给定名称的 bean
*/
boolean containsBean(String name);
/**
* 此 bean 是否为共享单例?也就是说,{@link #getBean} 是否始终返回相同的实例?
* <p>注意:此方法返回 {@code false} 不清楚地指示独立的实例。
* 它表示非单例实例,这可能对应于作用域 bean。使用 {@link #isPrototype} 操作明确检查独立实例。
* <p>将别名转换回相应的规范 bean 名称。
* <p>如果在此工厂实例中找不到 bean则将询问父工厂。
* @param name 要查询的 bean 的名称
* @return 此 bean 是否对应于单例实例
* @throws NoSuchBeanDefinitionException 如果没有具有给定名称的 bean
* @see #getBean
* @see #isPrototype
*/
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
/**
* 此 bean 是否为原型?也就是说,{@link #getBean} 是否始终返回独立的实例?
* <p>注意:此方法返回 {@code false} 不清楚地指示单例对象。
* 它表示非独立实例,这可能对应于作用域 bean。使用 {@link #isSingleton} 操作明确检查共享单例实例。
* <p>将别名转换回相应的规范 bean 名称。
* <p>如果在此工厂实例中找不到 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} 调用是否会返回可分配给指定目标类型的对象。
* <p>将别名转换回相应的规范 bean 名称。
* <p>如果在此工厂实例中找不到 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} 调用是否会返回可分配给指定目标类型的对象。
* <p>将别名转换回相应的规范 bean 名称。
* <p>如果在此工厂实例中找不到 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} 对于给定名称将返回的对象的类型。
* <p>对于 {@link FactoryBean},返回 FactoryBean 创建的对象的类型,由 {@link FactoryBean#getObjectType()} 公开。
* 这可能导致以前未初始化的 {@code FactoryBean} 的初始化(请参阅 {@link #getType(String, boolean)})。
* <p>将别名转换回相应的规范 bean 名称。
* <p>如果在此工厂实例中找不到 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} 对于给定名称将返回的对象的类型。
* <p>对于 {@link FactoryBean},返回 FactoryBean 创建的对象的类型,由 {@link FactoryBean#getObjectType()} 公开。
* 根据 {@code allowFactoryBeanInit} 标志的不同,如果没有提供早期类型信息,则可能导致以前未初始化的 {@code FactoryBean} 的初始化。
* <p>将别名转换回相应的规范 bean 名称。
* <p>如果在此工厂实例中找不到 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 名称的别名,如果有的话。
* <p>在 {@link #getBean} 调用中,所有这些别名都指向相同的 bean。
* <p>如果给定的名称是别名,则将返回相应的原始 bean 名称和其他别名(如果有的话),
* 原始 bean 名称将是数组中的第一个元素。
* <p>如果在此工厂实例中找不到 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<MyBean> 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
获取BeanObjectProvider: org.springframework.beans.factory.support.DefaultListableBeanFactory$1@1aa7ecca
获取Bean的类型: class com.xcs.spring.bean.MyBean
判断是否包含Bean: true
判断是否为单例: true
判断是否为原型: false
判断是否匹配指定类型: true
获取Bean的所有别名:
```
### 七、与其他组件的关系
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 的定义文件,确保格式正确,路径正确。