网站首页 > 技术教程 正文
这章开始Spring框架的源码剖析之旅。我们知道直接使用Spring框架可以使用AnnotationConfigApplicationContext注解方式或者ClassPathXmlApplicationContext这种xml配置文件方式,两者底层代码差不多,我们后续以AnnotationConfigApplicationContext进行分析,当前笔者使用的Spring版本是5.2.4。
我们可以直接使用AnnotationConfigApplicationContext的无参构造方法,也可以使用有参构造方法,我们今天主要是把构造函数的整体流程和主要做了哪些事情描述下,有些方法比较复杂,我们后续会有专门章节来详细说明:
有参构造:
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);无参构造:
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.register(AppConfig.class);
applicationContext.refresh();有参构造方法在构造函数里面会调用refresh方法,所以我们这里使用有参构造方法进行分析;
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
this();
register(componentClasses);
refresh();
}- 一、首先调用无参构造函数完成如下任务:
1. 创建BeanFactory,这个就是我们常说的Bean工厂,可以理解为存放、创建信息的地方;
2. 生成AnnotatedBeanDefinitionReader,它可以将一个类注册成为BeanDefinition,这不马上要用到了;
3. 生成ClassPathBeanDefinitionScanner,它是一个扫描器。
- 二、register方法调用了this.reader.register(componentClasses),将一个类注册成了BeanDefinition,这里为啥要将类注册成为BeanDefinition呢?原因是Spring扫描总得知道从哪里开始吧,所以这里就是告诉Spring扫描的入口。
- 三、refresh方法,核心方法,上代码:
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
prepareRefresh();
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // co
prepareBeanFactory(beanFactory);
try {
postProcessBeanFactory(beanFactory);
invokeBeanFactoryPostProcessors(beanFactory);
registerBeanPostProcessors(beanFactory);
initMessageSource();
initApplicationEventMulticaster();
onRefresh();
registerListeners();
finishBeanFactoryInitialization(beanFactory);
finishRefresh();
}catch (BeansException ex) {
......
}
}
}来逐行说说每个方法的主要作用:
prepareRefresh
里面有一个initPropertySources方法,可以允许子容器设置一些内容到Environment中。
prepareBeanFactory
准备BeanFactory,代码如下:
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
//设置BeanFactory的类加载器、表达式解析器、类型转化注册器
beanFactory.setBeanClassLoader(getClassLoader());
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
//设置以下几个类不自动注入
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
//将以下几个类直接添加到bean工厂中,表明可以直接通过类型获取到实例对象了
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
//添加了一个应用监听器的后置处理器
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
//这里对切面编程感兴趣的朋友可以研究研究,笔者没有深入研究过
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
//往bean工厂中添加环境变量对象,表明我们可以直接从Spring中获取到环境变量信息
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
}postProcessBeanFactory
子类可以对BeanFactory进行进一步初始化
invokeBeanFactoryPostProcessors
这个方法很关键,是扫描BeanDefinition的地方,后面我们会单独篇幅来详细说明,这里大概说明下它的作用。
BeanFactory准备好了之后,执行BeanFactoryPostProcessor,开始对BeanFactory进行处理,会使用ConfigurationClassPostProcessor扫描得到所有的BeanDefinition,并注册到Bean工厂中,并且会执行扫描到的BeanFactoryPostProcessor。
registerBeanPostProcessors
将上面扫描得到的BeanPostProcessor实例化并注册到Bean工厂中。
initMessageSource
这里是国际化的资源的实现地方,初始化MessageSource。
initApplicationEventMulticaster
初始化ApplicationContext的applicationEventMulticaster。
onRefresh
这里执行子类的onFrefresh方法,给子类提供的扩展点。
registerListeners
注册监听器,这里使用到了applicationEventMulticaster,往applicationEventMulticaster里面添加监听器。
finishBeanFactoryInitialization
完成beanFactory的初始化,在这里实例化非懒加载的单例bean,后面会单独篇幅介绍。
finishRefresh
这里主要是发布ContextRefreshedEvent事件,底层调用applicationEventMulticaster的multicastEvent方法,循环调用监听器的listener.onApplicationEvent(event)方法进行处理。
猜你喜欢
- 2024-10-19 Java 项目编译提示 javax.xml.bind.annotation does not exist 错误
- 2024-10-19 Android annotation包下常用的注解
- 2024-10-19 SpringMVC疑难一:mvc:annotation-dr
- 2024-10-19 Spring 中 AnnotationConfigUtils
- 2024-10-19 spring mvc 配置失效了?(springmvc的配置)
- 2024-10-19 为什么都爱着江南?黛瓦白墙,烟雨朦胧,是文人魂牵梦绕的故乡
- 2024-10-19 基于.NET6包含DDD,ES,CQRS等概念的开源
- 2024-10-19 spring 中 AnnotationUtils 的常用方法
- 2024-10-19 SpringBoot实战4-Spring基础-IoC容器
- 2024-10-19 Intellij IDEA安装并使用阿里p3c代码规约插件
欢迎 你 发表评论:
- 10-23Excel计算工龄和年份之差_excel算工龄的公式year
- 10-23Excel YEARFRAC函数:时间的"年份比例尺"详解
- 10-23最常用的10个Excel函数,中文解读,动图演示,易学易用
- 10-23EXCEL中如何计算截止到今日(两个时间中)的时间
- 10-2390%人不知道的Excel神技:DATEDIF 精准计算年龄,告别手动算错!
- 10-23计算工龄及工龄工资(90%的人搞错了):DATE、DATEDIF组合应用
- 10-23Excel中如何计算工作日天数?用这两个函数轻松计算,附新年日历
- 10-23怎样快速提取单元格中的出生日期?用「Ctrl+E」批量搞定
- 最近发表
-
- Excel计算工龄和年份之差_excel算工龄的公式year
- Excel YEARFRAC函数:时间的"年份比例尺"详解
- 最常用的10个Excel函数,中文解读,动图演示,易学易用
- EXCEL中如何计算截止到今日(两个时间中)的时间
- 90%人不知道的Excel神技:DATEDIF 精准计算年龄,告别手动算错!
- 计算工龄及工龄工资(90%的人搞错了):DATE、DATEDIF组合应用
- Excel中如何计算工作日天数?用这两个函数轻松计算,附新年日历
- 怎样快速提取单元格中的出生日期?用「Ctrl+E」批量搞定
- Excel日期函数之DATEDIF函数_excel函数datedif在哪里
- Excel函数-DATEDIF求司龄_exceldatedif函数计算年龄
- 标签列表
-
- 下划线是什么 (87)
- 精美网站 (58)
- qq登录界面 (90)
- nginx 命令 (82)
- nginx .http (73)
- nginx lua (70)
- nginx 重定向 (68)
- Nginx超时 (65)
- nginx 监控 (57)
- odbc (59)
- rar密码破解工具 (62)
- annotation (71)
- 红黑树 (57)
- 智力题 (62)
- php空间申请 (61)
- 按键精灵 注册码 (69)
- 软件测试报告 (59)
- ntcreatefile (64)
- 闪动文字 (56)
- guid (66)
- abap (63)
- mpeg 2 (65)
- column (63)
- dreamweaver教程 (57)
- excel行列转换 (56)

本文暂时没有评论,来添加一个吧(●'◡'●)