Spring原理篇--为什么你跟别的程序员一起去面试.同样问的Spring的原理;别人可以拿30K 你却只能要到15K;前面三章文章的铺垫,为的就是现在<Spring真正的生命周期-中>
Posted 喜欢编码的老胡
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring原理篇--为什么你跟别的程序员一起去面试.同样问的Spring的原理;别人可以拿30K 你却只能要到15K;前面三章文章的铺垫,为的就是现在<Spring真正的生命周期-中>相关的知识,希望对你有一定的参考价值。
@TOC# Spring系列
记录在程序走的每一步___auth:huf
拨开云雾见天日 守得云开见月明
Spring 真正的生命周期;
在很多文章中 写到这么个标题: XXXX原理 你只要看完这一篇就够; 作为一个技术苦行憎; 老衲很直白的说一句: 不可能的. 一个技术;需要大量时间去重复调研;最终才会摸清楚其原理; 我们还是一步一脚印;慢慢往里研究; 拨开云雾见天日 守得云开见月明;欢迎各路大神指正;共同进步
本文章开销时长 要比 之前的文章开销时长要大很多 本章节一共写了9个小时 ; 各位同学 记得三连
- 本文章 所有源码均是作者 自己从Spring源码中Copy 注释 之前有部分同学反映看不太清楚;所以把//去除以便源码的阅读;
承接周三的陈述; 我们讲到了Bean的创建; 以下是上个篇章尾部的描述:通过
1:ResourcePatternResolver获得指定包路径下的所有 .class 文件(Spring源码中将 此文件包装成了Resource对象
2:利用MetadataReaderFactory解析Resource对象得到MetadataReader(在Spring源码中 MetadataReaderFactory具体的实现类为CachingMetadataReaderFactory, MetadataReader的具体实现类为SimpleMetadataReader)
3:利用MetadataReader进行excludeFilters和includeFilters,以及条件注解@Conditional的筛选 (条件注解并不能解析某个类上是否存在@Conditional注解,如果存在则调用注解中所指定 的类的match方法进行匹配,匹配成功则通过筛选,匹配失败则pass掉。)
4.筛选通过后,基于metadataReader生成ScannedGenericBeanDefinition
5:再基于metadataReader判断是不是对应的类是不是接口或抽象类;
我们的主要目的是得到BeanDefinition 然后合成RootBeanDefinition;最后放进缓存集合中去
我们开始回顾; 之前的源码 就不会一遍一遍看了 如果有的 可能会一笔带过;
以下是我们创建容器的方法
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(testMain.class);
Object hufFactoryBean = context.getBean("hufFactoryBean");
System.out.println(hufFactoryBean);
再AnnotationConfigApplicationContext构造器 点进去后 我们发现 :
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
创建一个新的 context; 根据系统参数; 上一篇文章有讲到;
this();
注册Spring自己用的组件; 为创建容器 提供必须的条件; 这里不再累赘
register(componentClasses);
开始启动容器,重点关注该方法;
refresh();
}
AbstractApplicationContext.refresh() 其源码我给你们带进来这里 进行每一行代码的解释;
有部分如果内容比较多的 后面会有独立的篇章 去讲解相对应的内容; 看源码请勿心急; 如果有哪个地方没看懂;可以先放一下 把整个链路串起来 然后再看; 以下 是Spring的核心源码:
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
检查初始化环境
prepareRefresh();
通过子类获取它内部的Bean工厂 其内部有两个实现方法 如果有兴趣的同学 可以自行去查看
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
配置工厂的类加载器; 以及后置处理器; 内部使用了beanfactorypostprocessor 机制
prepareBeanFactory(beanFactory);
try {
所有 bean 定义都已加载,bean还没有 bean 被实例化。这里引出了实例化一个词
postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
实例化并调用所有已注册的 beanfactorypostprocessor 此时Bean还未实例化
仅仅是再处理配置文件的调度后置处理器
invokeBeanFactoryPostProcessors(beanFactory);
这里开始分装与注册 PostProcessor 例如MergedBeanDefinitionPostProcessor
就跟普通的Processor不一样 都再这个方法内进行分装
并且 这里创建出来了 BeanFactory 还有自己的配置 再初始化之前的接口 这里引入
InstantiationAwareBeanPostProcessor , MergedBeanDefinitionPostProcessor
再文章后面会有这两个接口的讲解 到这里 Bean的实例化还没有开始 更别说初始化
registerBeanPostProcessors(beanFactory);
这行不作解释;
beanPostProcess.end();
注册messageSource; 利用AbstractBeanFactory.dogetBean方法; 进行初始化;PostProcessor 就起效果了;
initMessageSource();
注册 初始化 特殊的Bean Spring的监听机制;
ApplicationListener及ApplicationEventMulticaster
initApplicationEventMulticaster();
初始化特定上下文子类中的其他特殊bean。 目前看源码没看到注册了什么Bean
在控制台也没看到有什么东西打印出来; 知道的小伙伴可以私聊 我们一起讨论
onRefresh();
注册Springlistener Bean 如果你实现了Listener 就会这这里被注册
registerListeners();
实例化所有 非 懒加载的 单例Bean; 本文中的重点;
finishBeanFactoryInitialization(beanFactory);
最后:发布相应的事件
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
注销Bean的逻辑 放到其他章节去讲;.
destroyBeans();
cancelRefresh(ex);
throw ex;
}
finally {
resetCommonCaches();
contextRefresh.end();
}
}
}
上面这个方法特别重要.也引出了很多关键的接口 以及关键的初始化;
总结;
1:初始化Bean之前 就必须实例化Bean 实例化过后才会初始化; 初始化过后的Bean才是完整的Bean
2:在初始化Bean的时候 我们有可能会影响Bean的 在实例化Bean的时候 我们也可以通过 PostProcessor来影响Bean的实例化; PostProcessor 作为Spring的"插件" 例如;InstantiationAwareBeanPostProcessor MergedBeanDefinitionPostProcessor
3:所有的监听机制 Listenner 以及 ApplicationEventMulticaster 都会再Bean 注册之前创建
4:最后创建 非 懒加载 的Bean ;
以下到 我们这篇文章的重点:
// 实例化所有 非 懒加载的 单例Bean; 本文中的重点; 该句源码是在上面源码里拿到的;
finishBeanFactoryInitialization(beanFactory);
继续往下走 点进这个方法:
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
为此上下文初始化转换服务
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));
}
如果没有BeanFactoryPostProcessor 就进行注册; 主要用于注释属性值中的Values
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
初始化回调 Bean 之后在其他章节中 讲解Aware;
这里同学可以试试 如果你实现LoadTimeWeaverAware 接口 那么就会在Bean注册之前 先注册这个Aware
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
停止使用临时类加载器进行类型匹配。
beanFactory.setTempClassLoader(null);
允许缓存所有bean定义元数据,不需要进一步更改。
beanFactory.freezeConfiguration();
实例化非懒加载Bean
beanFactory.preInstantiateSingletons();
}
这里 不做过多的解释; 继续往下面看;
beanFactory.preInstantiateSingletons();
进入该方法
@Override
public void preInstantiateSingletons() throws BeansException {
if (logger.isTraceEnabled()) {
logger.trace("Pre-instantiating singletons in " + this);
}
允许init方法注册新的bean定义
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
这里就可以看到 得到Bean的名字集合 开始触发所有Bean的初始化;
for (String beanName : beanNames) {
继前面文章面熟 所有Beandefinition 最终会合并成为RootBeanDefinition,然后进行Bean的初始化;
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
判断是不是抽象的Bean 判断是不是单例的Bean 判断是不是懒加载的Bean
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
判断是不是工厂的Bean
if (isFactoryBean(beanName)) {
如果是 那么就用&符号加 BeanName 得到工厂的Bean
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
得到Bean后 进行类型判断 是不是工厂bean;
如果不是 那么直接调度 getBean 这段IF里面的东西先进行屏蔽;
if (bean instanceof FactoryBean) {
if (isEagerInit) {
重点 重点 重点
getBean(beanName);
}
}
}
else {
重点 重点 重点
getBean(beanName);
}
}
}
触发所有适用bean的初始化后回调。。。 这里就不多过的冗余下去;
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize")
.tag("beanName", beanName);
SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
smartInitialize.end();
}
}
}
getBean(beanName);
点进去GetBean 方法中
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
继续往下点:
@SuppressWarnings("unchecked")
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
获取名字; 该名字 刚进来的时候也许是别名 也许是其他的名字
但是最终会通过这个方法获取到Bean的真实名字
String beanName = transformedBeanName(name);
Object beanInstance;
检查单例池是否有该Bean的存在
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
如果有 就返回 该方法里面还会有另外一个检查 此处不做细说
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
如果我们已经在创建此bean实则抛出异常;
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
检查工厂中是否存在bean定义;
BeanFactory parentBeanFactory = getParentBeanFactory();
如果有 就使用工厂的方法创建Bean
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
此处源码自行查看 为方便阅读 此处省略
}
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
Spring系统计算 程序开销时间 与容器启动 关系不大;
StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
.tag("beanName", name);
try {
if (requiredType != null) {
beanCreation.tag("beanType", requiredType::toString);
}
这里不再重复陈述
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
这里就要说一个注解了 @DependsOn 这个注解的意思是 在某个类初始化之前
另外一个类再在它之前被初始化 这里插一句话;
Spring解决了循环依赖 但是又没有完全解决循环依赖;
这里的循环依赖 无法解决的 假设使用这个注解 A依赖B B依赖A 是一定会报错的;
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
registerDependentBean(dep, beanName);
try {
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
创建bean实例。
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
else if (mbd.isPrototype()) {
这个逻辑是创建原型Bean的逻辑 也就是多例Bean
Object prototypeInstance = null;
try {
初始化前
beforePrototypeCreation(beanName);
初始化
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
初始化后
afterPrototypeCreation(beanName);
}
返回
beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {
单例bean的创建
String scopeName = mbd.getScope();
if (!StringUtils.hasLength(scopeName)) {
throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");
}
Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, () -> {
初始化前
beforePrototypeCreation(beanName);
try {
初始化
return createBean(beanName, mbd, args);
}
finally {
初始化后
afterPrototypeCreation(beanName);
}
});
beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new ScopeNotActiveException(beanName, scopeName, ex);
}
}
}
catch (BeansException ex) {
beanCreation.tag("exception", ex.getClass().toString());
beanCreation.tag("message", String.valueOf(ex.getMessage()));
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
finally {
beanCreation.end();
}
}
return adaptBeanInstance(name, beanInstance, requiredType);
}
本文章总结:
描述了 Bean 创建的大体流程 但是销毁流程 跟属性注入 没有讲到 后面会有单独的文章进行讲解;
seeyou
以上是关于Spring原理篇--为什么你跟别的程序员一起去面试.同样问的Spring的原理;别人可以拿30K 你却只能要到15K;前面三章文章的铺垫,为的就是现在<Spring真正的生命周期-中>的主要内容,如果未能解决你的问题,请参考以下文章
Java程序员如何从码农晋升为架构师,你跟架构师的差别在哪里?
Spring原理篇--BeanPostProcessor or BeanDefinition or Aware or InitializingBean