<blockquote>
<p><strong>Spring大家族在Java技术生态体系中占有重要地位,其中Spring更是其中的佼佼者。它极大的简化了我们的代码开发量,提高我们的工作效率。</strong></p>
<p><strong>其中Spring两大特性中的IOC特性是至关重要的。今天来从底层看一看Spring的容器的初始化过程。<span style="color:#e579b6;">算是我的学习笔记,也希望能对你有所帮助!</span></strong></p>
</blockquote>
<p>(如果有不懂IOC的小伙伴们可以去看一看我前面写的文章<strong><a href="https://blog.csdn.net/m0_46405589/article/details/107977319"><span style="color:#f33b45;">传送门在此</span></a></strong>)。</p>
<p><span style="color:#f33b45;">在开始之前,先思考几个问题。</span></p>
<ul><li><strong><span style="color:#3399ea;">@Component,@Service,@Controller,@Repository@Bean等注解怎么实现的?</span></strong></li><li><span style="color:#3399ea;"><strong>@Autowired,@Resource 是怎么自动装配的?</strong></span></li><li><span style="color:#3399ea;"><strong>@ComponentScan 为什么就可以扫描注册Bean</strong></span></li></ul>
<p> </p>
<p><strong>对此我在其他博客看到一张图,感觉很生动形象。</strong></p>
<h3><span style="color:#f33b45;">IOC 容器 示意图</span></h3>
<blockquote>
<p><strong><span style="color:#3399ea;">Spring IOC :</span></strong></p>
<ol><li><strong>Bean定义的定位,Bean 可以定义在<span style="color:#e579b6;">XML</span>中,或者一个<span style="color:#e579b6;">注解</span>,或者其他形式。这些都被用<span style="color:#e579b6;">Resource</span>来定位, 读取Resource获取<span style="color:#e579b6;">BeanDefinition </span>注册到 Bean定义注册表中。</strong></li><li><strong>第一次向容器getBean操作会触发Bean的创建过程,实列化一个Bean时 ,根据BeanDefinition中类信息等实列化Bean.</strong></li><li><strong>将实列化的Bean放到单列Bean缓存内。</strong></li><li><strong>此后再次获取向容器getBean就会从缓存中获取。</strong></li></ol>
</blockquote>
<p><br><img alt="" src="https://beijingoptbbs.oss-cn-beijing.aliyuncs.com/cs/5606289-566c2931fc689ffc4e0b5e1358916d4d.png"></p>
<p> </p>
<p>OK,下面来看容器的初始化方法。</p>
<p><span style="color:#f33b45;"><strong>源码如下:</strong></span></p>
<pre class="blockcode"><code class="language-java">public void refresh() throws BeansException, IllegalStateException {
//同步代码块 。
synchronized (this.startupShutdownMonitor) {
// 准备刷新.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}</code></pre>
<h3><span style="color:#f33b45;"><strong>1. prepareRefresh 准备刷新</strong></span></h3>
<blockquote>
<ul><li>设置启动时间,设计容器激活标志(active=true)</li><li>初始化 properties 资源</li><li>验证必须存在的properties(validateRequiredProperties)</li><li>初始earlyApplicationEnvents.用于收集已经产生的ApplicationEnvents.</li></ul>
</blockquote>
<h3><span style="color:#f33b45;"><strong>2.obtainFreshBeanFactory 获取容器</str |
|