SpringIOC容器初始化源码解析(4)—— 手撕Spring容器的刷新逻辑(较硬核

// 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();

}

}

}

在refresh方法里主要做的事情我以脑图的形式给出,各位读者可以从宏观上感受一下:

请添加图片描述

直接在AbstractApplicationContext的refresh方法的第一行加上断点:

请添加图片描述无论是注解还是xml的方式,都会执行这个refresh方法,用注解的程序作为入口进行调试。

调试程序源码

加锁是为了防止容器处在refresh阶段时,其他线程对容器进行了初始化或者销毁的操作。

先进入prepareRefresh方法里:

protected void prepareRefresh() {

// Switch to active.

this.startupDate = System.currentTimeMillis();

this.closed.set(false);

// 设置容器状态为激活

this.active.set(true);

if (logger.isDebugEnabled()) {

if (logger.isTraceEnabled()) {

logger.trace("Refreshing " + this);

}

else {

logger.debug("Refreshing " + getDisplayName());

}

}

// Initialize any placeholder property sources in the context environment.

// 2.初始化Environment的 propertySources 属性

// 样例<context:property-placeholder location=“classpath*:/config/load.properties”/>

initPropertySources();

// Validate that all properties marked as required are resolvable:

// see ConfigurablePropertyResolver#setRequiredProperties

// 3.校验 Environment 的 requiredProperties 是否都存在

// 请参考ConfigurablePropertyResolver#setRequiredProperties

getEnvironment().validateRequiredProperties();

// Store pre-refresh ApplicationListeners…

if (this.earlyApplicationListeners == null) {

this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);

}

else {

// Reset local application listeners to pre-refresh state.

this.applicationListeners.clear();

this.applicationListeners.addAll(this.earlyApplicationListeners);

}

// Allow for the collection of early ApplicationEvents,

// to be published once the multicaster is available…

// 4. 创建事件集合

this.earlyApplicationEvents = new LinkedHashSet<>();

}

先记录时间用于日志记录,随后将容器的状态设为激活,然后根据配置的日至等级决定是否记录详细的日志。

然后初始化环境的propertySources属性(initPropertySources();),然后验证上一步之后还有没有一些必要的要设置上的属性没有加载进来(getEnvironment().validateRequiredProperties()),然后再看下是否有一些容器启动的时候加载进一些监听器,有的话则加载到earlyApplicationListeners这个监听者列表中,默认情况下为空,最后创建事件集合,因为仅有监听者是不够的。


接下来就来到refresh方法的obtainFreshBeanFactory,对于xml方式来说,这一步特别重要,主要涉及到BeanDefinition的注册,但对于注解方式来说,该方法仅仅是调用了子类的refreshBeanFactory。

进入该方法:

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {

refreshBeanFactory();

return getBeanFactory();

}

refreshBeanFactory()是个抽象方法,等待子类来实现,可以step into进入到实际的方法里

@Override

protected final void refreshBeanFactory() throws IllegalStateException {

if (!this.refreshed.compareAndSet(false, true)) {

throw new IllegalStateException(

“GenericApplicationContext does not support multiple refresh attempts: just call ‘refresh’ once”);

}

this.beanFactory.setSerializationId(getId());

}

对于注解来讲,它实际调用的是GenericApplicationContext的refreshBeanFactory方法,xml主要是生成DefaultListableBeanFactory的内部容器实例,然后将BeanDefinition实例给注册到内部容器实例中。

针对于这里注解方式来讲,DefaultListableBeanFactory已经在注册类之前在调用容器的构造函数时就已经注册出来了,因此这里主要就是更新AnnotationConfigApplicationContecxt容器实例的刷新状态,把它内部的DefaultListableBeanFactory实例设置上序列化的id,就可以通过外部通过网络来逆序列化获得此处专属的DefaultListableBeanFactory实例


来到prepareBeanFactory(beanFactory)方法,此时已经获取到了DefaultListableBeanFactory的实例:

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {

// Tell the internal bean factory to use the context’s class loader etc.

// 给内置容器设置上外部容器的加载器

beanFactory.setBeanClassLoader(getClassLoader());

// 设置beanFactory的表达式语言处理器,Spring3开始增加了对语言表达式的支持,默认可以使用#{bean.xxx}的形式来调用相关属性值

beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));

// 为beanFactory增加一个默认的propertyEditor

beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

// Configure the bean factory with context callbacks.

// 添加该处理器的作用:当应用程序定义的Bean实现ApplicationContextAware接口时注入ApplicationContext

beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));

// 如果某个bean 依赖于以下几个接口的实现类,在自动装配的时候忽略它们

// Spring 会通过其他方式来处理这些依赖。

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 interface not registered as resolvable type in a plain factory.

// MessageSource registered (and found for autowiring) as a bean.

// 修正依赖,这里是注册一些自动装配的特殊规则,比如是BeanFactory class接口的实现类,则在运行时修指定为当前BeanFactory

beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);

beanFactory.registerResolvableDependency(ResourceLoader.class, this);

beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);

beanFactory.registerResolvableDependency(ApplicationContext.class, this);

// Register early post-processor for detecting inner beans as ApplicationListeners.

// 注册早期后置处理器,用于检测内部bean作为应用程序监听器

// ApplicationListenerDetector的作用就是判断某个Bean是否是ApplicationListener,

// 如果是,加入到事件监听者队列。

beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

// Detect a LoadTimeWeaver and prepare for weaving, if found.

// 如果找到一个LoadTimeWeaver,那么就准备将后置处理器“织入"bean工厂

if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {

beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));

// Set a temporary ClassLoader for type matching.

// 为类型匹配设置临时类加载器

beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));

}

// Register default environment beans.

// 注册默认environment环境bean

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());

}

}

  • 先给内置容器设置上外部容器的加载器,这样就可以让内部容器通过此类加载器去加载外部容器指定的资源了;

  • 第2步主要给内置容器设置上表达式语言处理器;

  • 之后就给内置容器加上一个默认的属性编辑器,用来编辑属性值的;

  • 之后会添加一个ApplicationContextAwareProcessor后置器,该后置器的作用是当应用程序定义的bean出现了ApplicationContextAware接口时,去给这些bean实例注入ApplicationContext对象;

  • 之后对于一些实现了特殊的接口的实现类,先忽略,随后通过其他方式再来处理;

  • 注册一些自动装配的规则,在运行时动态指定这些class对应的实现类;

  • 往容器里设置一个用来检查容器bean里是否有事件监听器的bean的beanPostProcessor;

  • 之后看看是否需要一个LTW织入器,在类加载的时候进行AOP的增强操作,如果有的话,就把该LWT级别的后置处理器添加到容器里;同时设置一个临时类加载器来负责加载并修改bean对应的行为;在AOP的时候会产生很多临时类,把他们放在临时类加载器里会更好;

  • 最后会设置一些默认环境的bean,承接一些默认的系统环境变量。


之后会来到postProcessBeanFactory(beanFactory),该方法允许子类去注册一些postProcessor,是一个钩子方法(子类可选择是否实现)

protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {

}

发现针对于本容器而言,是不需要注册子类的postProcessor的


接下来执行invokeBeanFactoryPostProcessors(beanFactory),进入到相应方法里

请添加图片描述

public static void invokeBeanFactoryPostProcessors(

ConfigurableListableBeanFactory beanFactory, List beanFactoryPostProcessors) {

// Invoke BeanDefinitionRegistryPostProcessors first, if any.

// 如果有BeanDefinitionRegistryPostProcessor的话优先执行

Set processedBeans = new HashSet<>();

// 如果是BeanDefinitionRegistry类型的话

if (beanFactory instanceof BeanDefinitionRegistry) {

BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;

// 用于记录常规BeanFactoryPostProcessor

List regularPostProcessors = new ArrayList<>();

// 用于记录BeanDefinitionRegistryPostProcessor

List registryProcessors = new ArrayList<>();

// 遍历所有参数传递进来的 BeanFactoryPostProcessor(它们并没有作为bean注册在容器中)

for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {

if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {

BeanDefinitionRegistryPostProcessor registryProcessor =

(BeanDefinitionRegistryPostProcessor) postProcessor;

registryProcessor.postProcessBeanDefinitionRegistry(registry);

registryProcessors.add(registryProcessor);

}

else {

regularPostProcessors.add(postProcessor);

}

}

// Do not initialize FactoryBeans here: We need to leave all regular beans

// uninitialized to let the bean factory post-processors apply to them!

// Separate between BeanDefinitionRegistryPostProcessors that implement

// PriorityOrdered, Ordered, and the rest.

List currentRegistryProcessors = new ArrayList<>();

// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.

String[] postProcessorNames =

beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);

for (String ppName : postProcessorNames) {

if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {

currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));

processedBeans.add(ppName);

}

}

sortPostProcessors(currentRegistryProcessors, beanFactory);

registryProcessors.addAll(currentRegistryProcessors);

invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);

currentRegistryProcessors.clear();

// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.

postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);

for (String ppName : postProcessorNames) {

if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {

currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));

processedBeans.add(ppName);

}

}

sortPostProcessors(currentRegistryProcessors, beanFactory);

registryProcessors.addAll(currentRegistryProcessors);

invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);

currentRegistryProcessors.clear();

// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.

boolean reiterate = true;

while (reiterate) {

reiterate = false;

postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);

for (String ppName : postProcessorNames) {

if (!processedBeans.contains(ppName)) {

currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));

processedBeans.add(ppName);

reiterate = true;

}

}

sortPostProcessors(currentRegistryProcessors, beanFactory);

registryProcessors.addAll(currentRegistryProcessors);

invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);

currentRegistryProcessors.clear();

}

// Now, invoke the postProcessBeanFactory callback of all processors handled so far.

// 因为BeanDefinitionRegistryPostProcessor继承自BeanFactoryPostProcessor,所以这里

// 也对所有 BeanDefinitionRegistryPostProcessor 调用其方法 postProcessBeanFactory()

invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);

// 对所有常规 BeanFactoryPostProcessor 调用其方法 postProcessBeanFactory()

invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);

}

else {

// Invoke factory processors registered with the context instance.

invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);

}

// Do not initialize FactoryBeans here: We need to leave all regular beans

// uninitialized to let the bean factory post-processors apply to them!

String[] postProcessorNames =

beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,

// Ordered, and the rest.

List priorityOrderedPostProcessors = new ArrayList<>();

List orderedPostProcessorNames = new ArrayList<>();

List nonOrderedPostProcessorNames = new ArrayList<>();

for (String ppName : postProcessorNames) {

if (processedBeans.contains(ppName)) {

// skip - already processed in first phase above

}

else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {

priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));

}

else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {

orderedPostProcessorNames.add(ppName);

}

else {

nonOrderedPostProcessorNames.add(ppName);

}

}

// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.

sortPostProcessors(priorityOrderedPostProcessors, beanFactory);

invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

// Next, invoke the BeanFactoryPostProcessors that implement Ordered.

List orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());

for (String postProcessorName : orderedPostProcessorNames) {

orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));

}

sortPostProcessors(orderedPostProcessors, beanFactory);

invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

// Finally, invoke all other BeanFactoryPostProcessors.

List nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());

for (String postProcessorName : nonOrderedPostProcessorNames) {

nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));

}

invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

// Clear cached merged bean definitions since the post-processors might have

// modified the original metadata, e.g. replacing placeholders in values…

beanFactory.clearMetadataCache();

}

将容器或者从参数传入进来的,包括实现了BeanDefinitionRegistryPostProcessorBeanFactoryPostProcessor的容器级别的PostProcessor接口的类按照优先级来执行一遍;

由于注解这一块先前obtainFreshBeanFactory方法执行的时候并没有把业务的BeanDefinition实例给定位、解析、注册到容器里,因此这里便调用实现了BeanDefinitionRegistryPostProcessor接口的ConfigurationClassPostProcessor这个后置处理器里面的postProcessBeanDefinitionRegistry方法,最终调用DefaultListableBeanFactory的方法来进行BeanDefinition实例的注册。


完成了容器级别的后置处理器之后就是bean级别的后置处理器了registerBeanPostProcessors(beanFactory),将先前定义的bean级别的后置处理器给注册到容器里,方便之后在调用getBean方法去创建bean实例的时候,在特定的环节去触发这些后置处理器,执行一些特定的逻辑,如AOP织入。


注册完BeanPostProcessor后就到了下一步,initMessageSource()是进行一些国际化的配置,主要是针对不同的地区去展示不同的语言。


接下来就是初始化事件发布器initApplicationEventMulticaster(),用于接受实现了ApplicationEventPublisher接口的类发送过来的不同的事件,并派发给不同的事件监听者来处理。

protected void initApplicationEventMulticaster() {

ConfigurableListableBeanFactory beanFactory = getBeanFactory();

if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {

this.applicationEventMulticaster =

beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);

if (logger.isTraceEnabled()) {

logger.trace(“Using ApplicationEventMulticaster [” + this.applicationEventMulticaster + “]”);

}

}

else {

this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);

beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);

if (logger.isTraceEnabled()) {

logger.trace(“No '” + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "’ bean, using " +

“[” + this.applicationEventMulticaster.getClass().getSimpleName() + “]”);

}

}

}

先判断容器有没有注册过自定义的事件发布器,有的话直接使用,否则就用默认的SimpleApplicationEventMulticaster作为事件发布器,进入到SimpleApplicationEventMulticaster

@Override

public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {

ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));

Executor executor = getTaskExecutor();

for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {

if (executor != null) {

// 异步发布事件

executor.execute(() -> invokeListener(listener, event));

}

else {

// 同步发布事件

invokeListener(listener, event);

}

}

}

该事件发布器既支持同步发布事件,又支持异步发布事件去给注册的监听器去做处理。


接下来执行onRefresh()方法

protected void onRefresh() throws BeansException {

// For subclasses: do nothing by default.

}

这是一个钩子方法,主要是预留给AbstractApplicationContext的子类用于初始化其他特殊的bean,该方法会发生在refresh的finishBeanFactoryInitialization(beanFactory);之前,也就是会发生在单例的bean的实例前去执行.

针对这个容器实例而言,并没有相关的onRefresh()方法的实现,onRefresh()方法主要是用在一些web容器上,比如AbstractRefreshableWebApplicationContext的onRefresh()方法:

@Override

protected void onRefresh() {

this.themeSource = UiApplicationContextUtils.initThemeSource(this);

}

在这里会初始化一些和主题相关的bean


之后会执行registerListeners()方法,往先前已经注册出来的ApplicationEventMulticaster(事件发布器)中去注册相应的监听器,用来监听不同的事件,至此,事件、事件发布器、事件监听器就都有了。


接下来来到finishBeanFactoryInitialization(beanFactory)方法里,

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {

// Initialize conversion service for this context.

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));

}

// Register a default embedded value resolver if no bean post-processor

最后

总而言之,面试官问来问去,问的那些Redis知识点也就这么多吧,复习的不够到位,知识点掌握不够熟练,所以面试才会卡壳。将这些Redis面试知识解析以及我整理的一些学习笔记分享出来给大家参考学习

还有更多学习笔记面试资料也分享如下:

都是“Redis惹的祸”,害我差点挂在美团三面,真是“虚惊一场”

nitThemeSource(this);

}

在这里会初始化一些和主题相关的bean


之后会执行registerListeners()方法,往先前已经注册出来的ApplicationEventMulticaster(事件发布器)中去注册相应的监听器,用来监听不同的事件,至此,事件、事件发布器、事件监听器就都有了。


接下来来到finishBeanFactoryInitialization(beanFactory)方法里,

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {

// Initialize conversion service for this context.

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));

}

// Register a default embedded value resolver if no bean post-processor

最后

总而言之,面试官问来问去,问的那些Redis知识点也就这么多吧,复习的不够到位,知识点掌握不够熟练,所以面试才会卡壳。将这些Redis面试知识解析以及我整理的一些学习笔记分享出来给大家参考学习

还有更多学习笔记面试资料也分享如下:

[外链图片转存中…(img-stuQcvE5-1714150636389)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值