文章目录
- Spring源码分析(BeanFactory)
- 一、BeanFactory
- [二、ApplicationContext 的父系](#二、ApplicationContext 的父系)
- [三、ApplicationContext 的实现](#三、ApplicationContext 的实现)
- 四、BeanFactory的创建
- 五、DefaultListableBeanFactory
-
- [1、为什么选择 DefaultListableBeanFactory?](#1、为什么选择 DefaultListableBeanFactory?)
- [2、运行时获取 DefaultListableBeanFactory](#2、运行时获取 DefaultListableBeanFactory)
Spring源码分析(BeanFactory)
一、BeanFactory
BeanFactory
是最顶层 的容器接口,只提供了获取Bean相关的一些方法。
java
public interface BeanFactory {
// 对FactoryBean的转义定义,因为如果使用bean的名字检索FactoryBean得到的对象是工厂生成的对象
String FACTORY_BEAN_PREFIX = "&";
// 根据bean的名字,在IOC容器中得到bean实例,
Object getBean(String name) throws BeansException;
// 根据bean的名字,在IOC容器中得到bean实例,args:显式参数(必须为非单例模式)
Object getBean(String name, Object... args) throws BeansException;
// 根据bean的名字获得对象,并转换为Class类型(可以不用进行类型转换)
<T> T getBean(String name, Class<T> requiredType);
// 根据bean的类型获得对象(必须是拥有唯一实现类)
<T> T getBean(Class<T> requiredType) throws BeansException;
// 根据bean的类型获得对象,args:显式参数
<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
// 判断IOC容器是否有这个名字的bean
boolean containsBean(String name);
// 判断这个bean是不是单例
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
// 判断这个bean是不是多例
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
// 获取bean实例的Class类型
Class<?> getType(String name) throws NoSuchBeanDefinitionException;
// 这里得到bean的别名,如果根据别名检索,那么其原名也会被检索出来
String[] getAliases(String name);
}
二、ApplicationContext 的父系
ApplicationContext
是更高级的容器接口,继承了许多其他接口,提供了更多的功能。
- 获取 Environment(EnvironmentCapable)
- getBean 的扩展(ListableBeanFactory)
- 事件的发布与监听机制(ApplicationEventPublisher)
- 支持父子容器(HierarchicalBeanFactory)
- 国际化(MessageSource)
- 事件的发布与监听机制(ApplicationEventPublisher)
- 资源访问(ResourcePatternResolver)
java
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
@Nullable
String getId();
String getApplicationName();
String getDisplayName();
long getStartupDate();
@Nullable
ApplicationContext getParent();
// 用于进行手动的 Bean 注入和依赖注入
AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException;
}
1、HierarchicalBeanFactory
HierarchicalBeanFactory
用于表示具有层次结构的 BeanFactory 容器。
-
支持父子容器的关系,一个 BeanFactory 可以有一个或多个父容器。
子容器可以访问父容器中定义的 Bean,但父容器不能访问子容器中定义的 Bean。
-
如果子容器中不存在某个 Bean,则会委托父容器进行查找。
java
public interface HierarchicalBeanFactory extends BeanFactory {
@Nullable
BeanFactory getParentBeanFactory();
boolean containsLocalBean(String name);
}
2、ListableBeanFactory
ListableBeanFactory
扩展了 BeanFactory 接口,提供了额外的功能来 获取 Bean 及其相关信息
java
public interface ListableBeanFactory extends BeanFactory {
// 获取 Bean 的定义信息
boolean containsBeanDefinition(String beanName);
int getBeanDefinitionCount();
String[] getBeanDefinitionNames();
// 通过 类型 获取 Bean
String[] getBeanNamesForType(ResolvableType type);
String[] getBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit);
String[] getBeanNamesForType(@Nullable Class<?> type);
String[] getBeanNamesForType(@Nullable Class<?> type, boolean includeNonSingletons, boolean allowEagerInit);
// 通过 注解 获取Bean
String[] getBeanNamesForAnnotation(Class<? extends Annotation> annotationType);
// 获取 <beanName, type>
<T> Map<String, T> getBeansOfType(@Nullable Class<T> type) throws BeansException;
<T> Map<String, T> getBeansOfType(@Nullable Class<T> type, boolean includeNonSingletons, boolean allowEagerInit) throws BeansException;
// 获取 <beanName, annotation>
Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType) throws BeansException;
// 获取bean的注解
@Nullable
<A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType)
throws NoSuchBeanDefinitionException;
}
3、EnvironmentCapable
EnvironmentCapable
接口用于获取 Environment
实例
java
public interface EnvironmentCapable {
Environment getEnvironment();
}
Environment
用于表示运行时环境(例如配置文件、系统属性、环境变量等)的抽象,提供了访问应用程序配置信息的统一接口。
java
public interface Environment extends PropertyResolver {
// 返回激活profile名称的数组
String[] getActiveProfiles();
// 返回默认profile名称的数组
String[] getDefaultProfiles();
// environment是否支持给定profile
boolean acceptsProfiles(Profiles profiles);
@Deprecated // 弃用
boolean acceptsProfiles(String... profiles);
}
java
public interface PropertyResolver {
// 检查某个属性是否存在
boolean containsProperty(String key);
// 获取指定属性的值(不存在则返回null)
String getProperty(String key);
// 获取指定属性的值(不存在则返回默认值)
String getProperty(String key, String defaultValue);
// 获取指定属性的值,可以指定要返回对象的类型(不存在则返回null)
<T> T getProperty(String key, Class<T> targetType);
// 获取指定属性的值,可以指定要返回对象的类型(不存在则返回默认值)
<T> T getProperty(String key, Class<T> targetType, T defaultValue);
// 获取指定属性的值(不存在则抛出异常)
String getRequiredProperty(String key) throws IllegalStateException;
<T> T getRequiredProperty(String key, Class<T> targetType) throws IllegalStateException;
String resolvePlaceholders(String text);
String resolveRequiredPlaceholders(String text) throws IllegalArgumentException;
}
4、ApplicationEventPublisher
ApplicationEventPublisher
用于发布应用程序事件并通知所有已注册的事件监听器。
java
@FunctionalInterface
public interface ApplicationEventPublisher {
default void publishEvent(ApplicationEvent event) {
publishEvent((Object) event);
}
void publishEvent(Object event);
}
5、MessageSource
MessageSource
是 Spring Framework 中用于国际化支持的接口之一。
- 它提供了一种统一的方式来访问应用程序中的消息资源,支持多语言和多地区的国际化功能。
java
public interface MessageSource {
String getMessage(String code, Object[] args, String defaultMessage, Locale locale);
String getMessage(String code, Object[] args, Locale locale) throws NoSuchMessageException;
String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException;
}
6、ResourcePatternResolver
ResourcePatternResolver
加载和访问应用程序中的资源,支持通配符和模式匹配,可以方便地加载多个资源。
java
public interface ResourcePatternResolver extends ResourceLoader {
String CLASSPATH_ALL_URL_PREFIX = "classpath*:";
Resource[] getResources(String var1) throws IOException;
}
java
public interface ResourceLoader {
String CLASSPATH_URL_PREFIX = "classpath:";
Resource getResource(String var1);
@Nullable
ClassLoader getClassLoader();
}
三、ApplicationContext 的实现
ApplicationContext
负责创建和管理应用程序中的所有 Bean 对象,其实现类的区别仅仅在于如何加载配置
AnnotationConfigApplicationContext
:使用「注解方式」加载配置ClassPathXmlApplicationContext
:从「资源根目录」下加载配置FileSystemXmlApplicationContext
:从「文件路径下」加载配置
四、BeanFactory的创建
1、Spring中的创建
java
// org.springframework.context.support.AbstractApplicationContext
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// ...
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// ...
}
}
java
// org.springframework.context.support.AbstractApplicationContext
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
// 刷新 BeanFactory(关闭旧的,创建新的)
refreshBeanFactory();
// 返回 BeanFactory
return getBeanFactory();
}
java
// org.springframework.context.support.AbstractRefreshableApplicationContext
@Override
protected final void refreshBeanFactory() throws BeansException {
// ...
try {
// 创建 DefaultListableBeanFactory
DefaultListableBeanFactory beanFactory = createBeanFactory();
// ...
} catch (IOException ex) {
throw new ApplicationContextException(...., ex);
}
}
protected DefaultListableBeanFactory createBeanFactory() {
return new DefaultListableBeanFactory(getInternalParentBeanFactory());
}
可以看到,创建的 BeanFactory 是 DefaultListableBeanFactory
2、SpringBoot中的创建
java
@SpringBootApplication
public class BasicProjectApplication {
public static void main(String[] args) {
SpringApplication.run(BasicProjectApplication.class, args);
}
}
java
// org.springframework.boot.SpringApplication
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
return run(new Class[]{primarySource}, args);
}
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
// 构建 SpringApplication实例 并执行run方法
return (new SpringApplication(primarySources)).run(args);
}
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
return (new SpringApplication(primarySources)).run(args);
}
public ConfigurableApplicationContext run(String... args) {
// Spring容器
ConfigurableApplicationContext context = null;
try {
// 构建Spring容器
context = this.createApplicationContext();
}
// ...
}
protected ConfigurableApplicationContext createApplicationContext() {
Class<?> contextClass = this.applicationContextClass;
if (contextClass == null) {
try {
switch (this.webApplicationType) {
case SERVLET:
// AnnotationConfigServletWebServerApplicationContext
contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);
break;
case REACTIVE:
// AnnotationConfigReactiveWebServerApplicationContext
contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
break;
default:
// AnnotationConfigApplicationContext
contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);
}
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Unable create a default ApplicationContext, please specify an ApplicationContextClass", ex);
}
}
// 构建IoC容器
return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
}
可以看到,三种 contextClass 都是 GenericApplicationContext 的子类
在实例化之前,会先进行父类 GenericApplicationContext 的初始化
java
// org.springframework.context.support.GenericApplicationContext
public GenericApplicationContext() {
this.beanFactory = new DefaultListableBeanFactory();
}
可以看到,创建的 BeanFactory 是 DefaultListableBeanFactory
五、DefaultListableBeanFactory
1、为什么选择 DefaultListableBeanFactory?
为什么创建的 BeanFactory 要选择 DefaultListableBeanFactory
呢?
分析一下继承图:
可以看到:
ConfigurableListableBeanFactory
只有一个实现类DefaultListableBeanFactory
DefaultListableBeanFactory
还通过实现右边的AbstractAutowireCapableBeanFactory
通吃了右路
因此,DefaultListableBeanFactory
基本上是最牛的 BeanFactory
了,这也是为什么会选择实例化这个类的原因。
2、运行时获取 DefaultListableBeanFactory
如何在运行时获取 DefaultListableBeanFactory
实例呢?
getAutowireCapableBeanFactory
获取AutowireCapableBeanFactory
AutowireCapableBeanFactory
向下转型得到DefaultListableBeanFactory
java
public class GetDefaultListableBeanFactory {
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext();
DefaultListableBeanFactory autowireCapableBeanFactory =
(DefaultListableBeanFactory) applicationContext.getAutowireCapableBeanFactory();
}
}