准备一个干净的Spring项目,创建Spring核心配置文件,然后随便写几句能将Spring项目跑起来的代码。
打好断点,我们开始了!
F7进入代码中☝
这里是WebLogic的一个小问题不用管它,继续F8直至跳出到原来的main方法后,再次F7进入代码中就可以看到真正Spring的启动流程☝
加载核心applicationContext.xml配置文件☝
super(parent); // 调用父类构造方法,进行相关的对象创建
相当于进行一些初始化的操作
setConfigLocations(configLocations); // 设置配置路径
就是将刚刚加载的applicationContext配置文件读取进来
refresh()这个方法重中之重,F7进入代码中查看☝
refresh()中的这13个方法是可谓是整个Spring源码中的灵魂,将这13个方法弄懂明白,可以说等于就弄懂了整个Spring框架的源码了。接下来这些方法一个一个来仔细看下:
prepareRefresh();
准备刷新,做一些容器刷新前最基本的准备工作
this.startupDate = System.currentTimeMillis(); // 设置Spring当前启动时间
this.closed.set(false); // 关闭状态记为false
this.active.set(true); // 活跃状态记为true
initPropertySources(); // 初始化属性资源:当前这一步来说没多大作用
getEnvironment().validateRequiredProperties();
这里注意一下,进入里面看虽然只是简单new一个StandardEnvironment,但是StandardEnvironment继承了AbstractEnvironment。在这个AbstractEnvironment构造方法中,有一个customizePropertySources(this.propertySources),本身没做实现,等到具体执行的时候由子类来实现。
if (this.earlyApplicationListeners == null) {
this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
} else {
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}
准备一些必要的监听器的集合
this.earlyApplicationEvents = new LinkedHashSet<>();
准备一些监听器事件的集合
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
获取一个刷新的Bean容器对象,创建一个工厂,这边需要注意几个具体的实现类及相关的类图关系
打开BeanFactory接口,在注释中有提到两个重要的接口:ListableBeanFactory和ConfigurableBeanFactory
再打开DefaultListableBeanFactory这个类的类图,这个类是接下来使用非常非常多的一个类,将这个类图大概有个印象记住
好了,继续回到刚刚的位置,进入到obtainFreshBeanFactory()中,执行refreshBeanFactory()刷新Bean工厂,而在刷新中,会进行判断
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
如果有Bean工厂,销毁Bean,关闭工厂
try {
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
loadBeanDefinitions(beanFactory);
this.beanFactory = beanFactory;
}
然后再创建新的Bean工厂,也就是说这么一来,获取的必然是新的工厂。而在createBeanFactory()中,执行的就是return new DefaultListableBeanFactory(getInternalParentBeanFactory())这个方法创建当前的工厂对象。至此,对象工厂也就创建完成
工厂创建好以后,接着就要往里面开始设值。所以下一步就会看到
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory); // 这个方法里面进行属性值的设置:
beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
beanFactory.setAllowCircularReferences(this.allowCircularReferences);
loadBeanDefinitions(beanFactory); // 设置完属性后,加载配置文件读取
这个方法下特别多各种重载的方法,想方设法各种保证执行完一个完整的加载流程
整体上来讲,在这个ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory()大方法中:
① 就是在创建容器对象:DefaultListableBeanFactory;
② 加载xml配置文件的属性值到当前工厂中,最重要的就是BeanDefinition;
prepareBeanFactory(beanFactory); // 准备Bean工厂
再上一步骤中创建好了Bean工厂,这一步就需要对创建出来的Bean工厂设置属性值
F7进入方法中,走来就是两个set一个add
beanFactory.setBeanClassLoader(getClassLoader());
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
beanFactory.ignoreDependencyInterface(ApplicationStartupAware.class);
设置忽略Aware接口的处理,后面会有统一的处理
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
处理一些依赖
这里的代码几乎一样,不是set就是add,prepareBeanFactory(beanFactory)这个方法基本就是为了完成Bean工厂的初始化操作☝
postProcessBeanFactory(beanFactory);
这个方法F7进去之后,发现里面空了,为了方便后面的扩展操作,用户可以自己实现
invokeBeanFactoryPostProcessors(beanFactory);
实例化并执行所有的BeanFactoryPostProcessors Bean,这个方法进入里面虽然深入剖析的话,比较麻烦,后面再细说
registerBeanPostProcessors(beanFactory); // 注册实现
F7进入方法中,代码很少就一句PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this),实例化并注册所有的BeanPostProcessors Bean,和上一步一样,其实也是准备工作
initMessageSource(); // 初始化消息资源,其实说白了就是一个国际化的操作,可以先不用重点关注
initApplicationEventMulticaster(); // 初始化应用程序时间广播器,当监听器进入到广播事件中以后,可以执行一些对应的操作
onRefresh();
这个方法也是一个空实现,也是留给子类做一些扩展工作,目前不用重点关注,后续用到在细说
registerListeners();
注册监听器,具体用到哪些监听器,后面用到的时候再细说
可以看到上面的几个方法:
registerBeanPostProcessors(beanFactory);
initMessageSource();
initApplicationEventMulticaster();
onRefresh();
registerListeners();
其中initMessageSource()用来国际化的不用管,onRefresh()本身就是个空实现,剩余的几个方法都是用来做实例化前的一系列准备
finishBeanFactoryInitialization(beanFactory); // 实例化所有剩下的非懒加载的单例对象
这个方法非常关键,如果说工作中真的会动用到Spring源码级别的话,这个方法是绕不开的一个必经之地
F7进入方法,首先第一步
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
这一步是将类型转换的操作设置进入beanFactory中,这一步不用重点关注
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
判断当前的beanFactory有没有内置的值处理器
…..
beanFactory.freezeConfiguration();
如果某些Bean的配置不需要进行修改,可以进行冻结
beanFactory.preInstantiateSingletons();
这一步才是核心的实例化所有剩下的非懒加载的单例对象
F7进入方法中,这个方法还是比较复杂,很多关键点在这里面完成
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
把获取的beanDefinitionName塞进一个集合,下面会循环这些名字
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
RootBeanDefinition是Bean的描述定义信息,而有了这些信息以后,方便下面的实例化操作
if (isFactoryBean(beanName))
判断当前的这个Bean有没有实现FactoryBean接口,没有实现则直接实例化getBean(beanName),进入里面就是doGetBean
而在Spring源码中,do…开头的都是正经实际干活的代码,F7进入方法中
Object sharedInstance = getSingleton(beanName);
Bean实例化之后放入容器中,而容器是放在一堆容器Map中,而在Map中又有一级二级三级缓存,所以这个方法里面其实是先去缓存中找有没有这个实例,没有缓存直接创建
if (isPrototypeCurrentlyInCreation(beanName))
当对象都是单例的时候会尝试解决循环依赖问题,但是原型模式下如果存在循环依赖的情况,则直接抛出异常
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
如果不是做类型检查,那么表示要创建Bean,此处在结合中做一个标记
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null)
如果存在依赖Bean的话,则优先实例化依赖的Bean
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {…..}
}
getSingleton方法里面的doCreateBean()方法才是利用反射机制来正经创建Bean
而在doCreateBean()中,首先是在内存中开辟空间,然后做一些前置的判断处理
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace(“Eagerly caching bean ‘” + beanName +”‘ to allow for resolving potential circular references”);
}
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
这几句代码非常重要,解决了一个非常重要的问题:循环依赖
解决循环依赖的一个重要思想就是:提前暴露。在进行对象创建的时候,为什么要把实例化和初始化分的那么清楚,实例化只是完成了当前对象的一个创建,暴露的就是只完成了实例化,还没有完成初始化,此时将对象提前暴露出去。在addSingletonFactory()方法里面,this.singletonFactories.put(beanName, singletonFactory)这一句意思是先放到三级缓存中去。
那么,为什么要使用三级缓存?关键点在于getEarlyBeanReference(beanName, mbd, bean)这个方法中:当需要对象被代理的时候,就必须要三级缓存来实现了。
好,继续往下走,来到:
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
完成当前对象属性值的注入,完成属性值的填充
再往下,registerDisposableBeanIfNecessary(beanName, bean, mbd);
当容器关闭的时候,需要销毁当前的对象。当需要进行销毁的时候,创建一个销毁的方法,确实正确的销毁
当执行完上述这些步骤之后,基本上Bean的实例化就基本完成
finishRefresh();
Bean创建完成之后,完成整体的刷新,基本上就是发布时间,重置缓存等等,这一步结束之后,就可以拿到创建完成的Bean进行业务操作了
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/111917.html