SpringBoot源码阅读之AnnotationConfigApplicationContext类分析

1.通过SpringApplication.run方法进入查看源码,会发现代码中下面的这段代码创建了IOC容器。 

context = createApplicationContext();

跟进去找到下面这段代码,spring boot创建了AnnotationConfigApplicationContext类的Class信息,并且实例化,赋值给context。后面的一系列操作都会依托这个类,所以该类是本文分析的重点。

contextClass = Class.forName(this.webEnvironment ? DEFAULT_WEB_CONTEXT_CLASS : DEFAULT_CONTEXT_CLASS)
public static final String DEFAULT_CONTEXT_CLASS = "org.springframework.context."
      + "annotation.AnnotationConfigApplicationContext";

2. 下面是AnnotationConfigApplicationContext类的类图,我们可以看到AnnotationConfigApplicationContext类具备非常多接口和类的功能,下面就自顶向下逐个分析各个接口的作用。

3.BeanFactory接口

String FACTORY_BEAN_PREFIX = "&";
//根据名称得到bean实例
Object getBean(String name) throws BeansException;
//根据名称和类型得到bean实例,类型可为基类
<T> T getBean(String name, Class<T> requiredType) throws BeansException;
//根据名称和构造函数参数获取bean实例
Object getBean(String name, Object... args) throws BeansException;
//根据类型获取bean实例,类型可以为基类,如果有大于一个的实例则会抛出异常
<T> T getBean(Class<T> requiredType) throws BeansException;
//根据类型和构造函数参数获取bean实例
<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
//根据名称判断是否包含bean
boolean containsBean(String name);
//根据名称判断bean是否为单例
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
//根据名称判断bean是否为原型
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
//根据名称和可解析类型进行匹配
boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
//根据名称和类信息进行匹配
boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;
//根据名称得到类型
Class<?> getType(String name) throws NoSuchBeanDefinitionException;
//根据名称获取别名
String[] getAliases(String name);

BeanFactory是最基本的容器,唯一的属性定义了FactoryBean的前缀。该接口的含义即为:只要实现了BeanFactory接口的类,都可以读取IOC容器中的bean,但是容器中的bean从哪里来呢?答案是通过实现Registry接口来具备注册bean的功能。

4.下面看一下BeanFactory的子接口——ListableBeanFactory。

//查看当前容器是否包含beanName对应的BeanDefinition
boolean containsBeanDefinition(String beanName);
//查看容器中Bean定义的总数
int getBeanDefinitionCount();
//查看容器中所有BeanDefinition的名称
String[] getBeanDefinitionNames();
//根据可解析类型得到所有Bean的名称
String[] getBeanNamesForType(ResolvableType type);
//根据类型得到所有Bean的名称
String[] getBeanNamesForType(Class<?> type);
//根据类型得到所有Bean的名称,includeNonSingletons含义为是否包含原型实例,
//allowEagerInit含义为是否将懒加载的实例立即初始化
String[] getBeanNamesForType(Class<?> type, boolean includeNonSingletons, boolean allowEagerInit);
//根据类型得到bean实例的Map,key为bean的name
<T> Map<String, T> getBeansOfType(Class<T> type) throws BeansException;
//根据类型、是否包含非单例、是否立即初始化懒加载的类,得到相应的bean实例,key为bean的name
<T> Map<String, T> getBeansOfType(Class<T> type, boolean includeNonSingletons, boolean allowEagerInit)    throws BeansException;
//找到所有标注了相应注解类型且未被初始化的bean实例的名称
String[] getBeanNamesForAnnotation(Class<? extends Annotation> annotationType);
//根据注解类型得到所有标注了该注解的bean实例,key为bean的name,value为bean实例
Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType) throws BeansException;
//根据bean的名称和注解类型找到相应的注解,如果实例bean上没有相应的注解则会抛错
<A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType)
			throws NoSuchBeanDefinitionException;

该接口主要是提供了bean的批量读取的功能,以及加入了注解作为查询条件。这个接口是BeanFactory一个很好的补充,由于有的容器可能不需要具备批量操作功能和注解的作用,所以将这部分功能放在了ListableBeanFactory当中,而不是BeanFactory当中,这样解耦也会非常好。

5.HierarchicalBeanFactory——分层的BeanFactory

//得到父容器
BeanFactory getParentBeanFactory();
//判断当前容器是否包含相应的Bean实例,不包含父类容器的
boolean containsLocalBean(String name);

该接口的出现使容器具备了继承的作用:子容器可以得到父容器的实例从而拿到父容器持有的的bean实例,同时子容器也可以单独判断当前容器是否包含bean实例。

6.ApplicationContext——具备完整功能的接口,应用上下文

//应用的ID,唯一标识
String getId();
//应用的名称
String getApplicationName();
//应用的展示名称
String getDisplayName();
//应用的启动时间
long getStartupDate();
//得到父应用
ApplicationContext getParent();
//暴露AutowireCapableBeanFactory 
AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException;

概述:ApplicationContext接口定义了应用的一些行为,实现这个接口的类则表示属于一个完整的应用。该接口实现了BeanFactory类族以及ResourceLoader类族,还有EnvironmentCapable、ApplicationEventPublisher、MessageSource等接口,具备IOC的储存功能和资源的加载功能,以及剩下的几个接口的功能(后文会分析这几个接口的作用)。

接口的作用:ApplicationContext的作用更像是一个整合,赋予了应用的一些个性标识,不过也定义了父子应用的概念。AutowireCapableBeanFactory 接口的作用也是后文分析。

这个接口的重大意义在于,从单一的IOC容器转变成了应用容器,还具备资源加载功能。

7.ConfigurableApplicationContext——可配置的应用上下文

//上下文路径的分隔符,意思是一个字符串如果是上下文路径,且包含以下符号,那么就是多个上下文路径,
//中间被以下分隔符隔开。
String CONFIG_LOCATION_DELIMITERS = ",; \t\n";
//ConversionService的默认名称
String CONVERSION_SERVICE_BEAN_NAME = "conversionService";
//LoadTimeWeaver的默认名称
String LOAD_TIME_WEAVER_BEAN_NAME = "loadTimeWeaver";
//Environment的默认名称
String ENVIRONMENT_BEAN_NAME = "environment";
//java.lang.System的getProperties()方法的默认名称
String SYSTEM_PROPERTIES_BEAN_NAME = "systemProperties";
//java.lang.System的getenv()方法的默认名称
String SYSTEM_ENVIRONMENT_BEAN_NAME = "systemEnvironment";
//给应用上下文设置唯一ID
void setId(String id);
//给应用上下文设置父应用上下文
void setParent(ApplicationContext parent);
//给应用上下文设置ConfigurableEnvironment
void setEnvironment(ConfigurableEnvironment environment);
//得到Environment,返回值类型是ConfigurableEnvironment,重写是因为父接口返回的是Environment
@Override
ConfigurableEnvironment getEnvironment();
//给应用上下文添加后置处理器
void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor);
//给应用上下文添加应用监听器
void addApplicationListener(ApplicationListener<?> listener);
//给应用上下文添加协议解析器
void addProtocolResolver(ProtocolResolver resolver);
//刷新应用上下文
void refresh() throws BeansException, IllegalStateException;
//注册钩子,应用上下文关闭的时候会调用
void registerShutdownHook();
//关闭应用上下文,重写了父接口Closeable的close()方法,因为父接口的close()抛的是IO异常,属于关
//闭流的作用,而这里只是关闭应用上下文
@Override
void close();
//判断当前应用上下文是否为激活状态
boolean isActive();
//得到ConfigurableListableBeanFactory这个IOC容器(这个接口后文分析)
ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;

该接口是ApplicationContext的补充,ApplicationContext定义了一个应用应该有哪些东西,但是没有定义这些东西从哪里来,也就是说ApplicationContext无法改变其中的状态,所以实现ConfigurableApplicationContext接口的类除了能够改变应用上下文的状态,还能够管理其生命周期(实现了Lifecycle接口)。

8.AbstractApplicationContext——抽象的应用上下文,给出了部分具体实现,部分方法仍然保留为抽象方法(未完待续)

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值