牧原集团视频面试攻略,Spring IoC源码学习,2024年大厂Java面经

// 用于存放实现了PriorityOrdered接口的BeanFactoryPostProcessor

List priorityOrderedPostProcessors = new ArrayList();

// 用于存放实现了Ordered接口的BeanFactoryPostProcessor的beanName

List orderedPostProcessorNames = new ArrayList();

// 用于存放普通BeanFactoryPostProcessor的beanName

List nonOrderedPostProcessorNames = new ArrayList();

// 8.1 遍历postProcessorNames, 将BeanFactoryPostProcessor按实现PriorityOrdered、实现Ordered接口、普通三种区分开

for (String ppName : postProcessorNames) {

// 8.2 跳过已经执行过的

if (processedBeans.contains(ppName)) {

// skip - already processed in first phase above

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

// 8.3 添加实现了PriorityOrdered接口的BeanFactoryPostProcessor

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

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

// 8.4 添加实现了Ordered接口的BeanFactoryPostProcessor的beanName

orderedPostProcessorNames.add(ppName);

} else {

// 8.5 添加剩下的普通BeanFactoryPostProcessor的beanName

nonOrderedPostProcessorNames.add(ppName);

}

}

// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.

// 9.调用所有实现PriorityOrdered接口的BeanFactoryPostProcessor

// 9.1 对priorityOrderedPostProcessors排序

sortPostProcessors(priorityOrderedPostProcessors, beanFactory);

// 9.2 遍历priorityOrderedPostProcessors, 执行postProcessBeanFactory方法

invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

// Next, invoke the BeanFactoryPostProcessors that implement Ordered.

// 10.调用所有实现Ordered接口的BeanFactoryPostProcessor

List orderedPostProcessors = new ArrayList();

for (String postProcessorName : orderedPostProcessorNames) {

// 10.1 获取postProcessorName对应的bean实例, 添加到orderedPostProcessors, 准备执行

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

}

// 10.2 对orderedPostProcessors排序

sortPostProcessors(orderedPostProcessors, beanFactory);

// 10.3 遍历orderedPostProcessors, 执行postProcessBeanFactory方法

invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

// Finally, invoke all other BeanFactoryPostProcessors.

// 11.调用所有剩下的BeanFactoryPostProcessor

List nonOrderedPostProcessors = new ArrayList();

for (String postProcessorName : nonOrderedPostProcessorNames) {

// 11.1 获取postProcessorName对应的bean实例, 添加到nonOrderedPostProcessors, 准备执行

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

}

// 11.2 遍历nonOrderedPostProcessors, 执行postProcessBeanFactory方法

invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

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

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

// 12.清除元数据缓存(mergedBeanDefinitions、allBeanNamesByType、singletonBeanNamesByType),

// 因为后处理器可能已经修改了原始元数据,例如, 替换值中的占位符…

beanFactory.clearMetadataCache();

}

1.判断 beanFactory 是否为 BeanDefinitionRegistry。beanFactory 是在之前的 obtainFreshBeanFactory 方法构建的,具体代码在:AbstractRefreshableApplicationContext.refreshBeanFactory() 方法,代码如下。

@Override

protected final void refreshBeanFactory() throws BeansException {

if (hasBeanFactory()) {

destroyBeans();

closeBeanFactory();

}

try {

// 创建一个新的BeanFactory

DefaultListableBeanFactory beanFactory = createBeanFactory();

beanFactory.setSerializationId(getId());

customizeBeanFactory(beanFactory);

loadBeanDefinitions(beanFactory);

synchronized (this.beanFactoryMonitor) {

this.beanFactory = beanFactory;

}

}

catch (IOException ex) {

throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);

}

}

可以看出,我们构建的 beanFactory 是一个 DefaultListableBeanFactory ,而 DefaultListableBeanFactory 实现了BeanDefinitionRegistry 接口,因此 beanFactory instanceof BeanDefinitionRegistry 结果为 true。

3.4 获取 ppName 对应的 bean 实例,添加到 currentRegistryProcessors 中,准备执行。beanFactory.getBean 方法会触发创建 ppName 对应的 bean 实例对象,创建 bean 实例是 IoC 的另一个核心内容,之后会单独解析,目前暂不深入解析。

3.6 进行排序,该方法在下面也被调用了好几次,见代码块3详解。

代码块3:sortPostProcessors


private static void sortPostProcessors(List<?> postProcessors, ConfigurableListableBeanFactory beanFactory) {

Comparator comparatorToUse = null;

if (beanFactory instanceof DefaultListableBeanFactory) {

// 1.获取设置的比较器

comparatorToUse = ((DefaultListableBeanFactory) beanFactory).getDependencyComparator();

}

if (comparatorToUse == null) {

// 2.如果没有设置比较器, 则使用默认的OrderComparator

comparatorToUse = OrderComparator.INSTANCE;

}

// 3.使用比较器对postProcessors进行排序

Collections.sort(postProcessors, comparatorToUse);

}

默认情况下,比较器为 OrderComparator;如果配置了 annotation-config,并且值为true,使用的是 AnnotationAwareOrderComparator( Spring IoC:context:component-scan节点解析 代码块17中设置了dependencyComparator 属性为 AnnotationAwareOrderComparator.INSTANCE),AnnotationAwareOrderComparator 继承自 OrderComparator,只是重写了部分方法,比较器的部分代码如下:

@Override

public int compare(Object o1, Object o2) {

return doCompare(o1, o2, null);

}

private int doCompare(Object o1, Object o2, OrderSourceProvider sourceProvider) {

// 判断o1是否实现了PriorityOrdered接口

boolean p1 = (o1 instanceof PriorityOrdered);

// 判断o2是否实现了PriorityOrdered接口

boolean p2 = (o2 instanceof PriorityOrdered);

// 1.如果o1实现了PriorityOrdered接口, 而o2没有, 则o1排前面

if (p1 && !p2) {

return -1;

}

// 2.如果o2实现了PriorityOrdered接口, 而o1没有, 则o2排前面

else if (p2 && !p1) {

return 1;

}

// 3.如果o1和o2都实现(都没实现)PriorityOrdered接口

// Direct evaluation instead of Integer.compareTo to avoid unnecessary object creation.

// 拿到o1的order值, 如果没实现Ordered接口, 值为Ordered.LOWEST_PRECEDENCE

int i1 = getOrder(o1, sourceProvider);

// 拿到o2的order值, 如果没实现Ordered接口, 值为Ordered.LOWEST_PRECEDENCE

int i2 = getOrder(o2, sourceProvider);

// 4.通过order值(order值越小, 优先级越高)排序

return (i1 < i2) ? -1 : (i1 > i2) ? 1 : 0;

}

比较器的逻辑很简单,实现 PriorityOrdered 接口的优先级最高,如果两个对象都实现(都没实现)PriorityOrdered 接口,则根据 order 值(实现 Ordered 接口时,需要实现 getOrder() 方法,返回 order 值)来进行比较,order 值越小,优先级越高。

基本使用

====

1.BeanDefinitionRegistryPostProcessor 的扩展使用


使用方法比较简单,新建一个类实现 BeanDefinitionRegistryPostProcessor 接口,并将该类注册到 Spring IoC 容器中。

package com.joonwhee.open.demo.spring;

import org.springframework.beans.BeansException;

import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;

import org.springframework.beans.factory.support.BeanDefinitionRegistry;

import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;

import org.springframework.core.Ordered;

import org.springframework.stereotype.Component;

/**

  • @author joonwhee

  • @date 2019/2/18

*/

@Component

public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor, Ordered {

@Override

public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {

System.out.println(“MyBeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry”);

// 自己的逻辑处理

}

@Override

public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

System.out.println(“MyBeanDefinitionRegistryPostProcessor#postProcessBeanFactory”);

// 自己的逻辑处理

}

@Override

public int getOrder() {

return 0;

}

}

具体的使用场景,需要读者自己去探讨,这边给一个常见的使用例子。

例子:

我们通常在使用 Mybatis + Spring 时,经常用到的 org.mybatis.spring.mapper.MapperScannerConfigurer 就是一个BeanDefinitionRegistryPostProcessor。MapperScannerConfigurer 在 postProcessBeanDefinitionRegistry 方法中进行了一些操作,主要是:扫描 basePackage 指定的目录,将该目录下的类(通常是 DAO/MAPPER 接口)封装成 BeanDefinition 并加载到 BeanFactory 中。因此,我们可以看到我们项目中的 DAO(MAPPER)接口,通常都没有使用注解或 XML 的方式注册到 Spring 容器,但是我们还是可以在 Service 服务中,使用 @Autowire 注解来将其注入到 Service 中,就是因为这个原因。

MapperScannerConfigurer.java

2.BeanFactoryPostProcessor 的扩展使用


使用方法跟 BeanDefinitionRegistryPostProcessor 类似。

package com.joonwhee.open.demo.spring;

import org.springframework.beans.BeansException;

import org.springframework.beans.factory.config.BeanFactoryPostProcessor;

import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;

import org.springframework.stereotype.Component;

/**

  • @author joonwhee

  • @date 2019/2/18

*/

@Component

public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
img

总结

一般像这样的大企业都有好几轮面试,所以自己一定要花点时间去收集整理一下公司的背景,公司的企业文化,俗话说「知己知彼百战不殆」,不要盲目的去面试,还有很多人关心怎么去跟HR谈薪资。

这边给大家一个建议,如果你的理想薪资是30K,你完全可以跟HR谈33~35K,而不是一下子就把自己的底牌暴露了出来,不过肯定不能说的这么直接,比如原来你的公司是25K,你可以跟HR讲原来的薪资是多少,你们这边能给到我的是多少?你说我这边希望可以有一个20%涨薪。

最后再说几句关于招聘平台的,总之,简历投递给公司之前,请确认下这家公司到底咋样,先去百度了解下,别被坑了,每个平台都有一些居心不良的广告党等着你上钩,千万别上当!!!

Java架构学习资料,学习技术内容包含有:Spring,Dubbo,MyBatis, RPC, 源码分析,高并发、高性能、分布式,性能优化,微服务 高级架构开发等等。

还有Java核心知识点+全套架构师学习资料和视频+一线大厂面试宝典+面试简历模板可以领取+阿里美团网易腾讯小米爱奇艺快手哔哩哔哩面试题+Spring源码合集+Java架构实战电子书。
在这里插入图片描述

一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!

AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算

高性能、分布式,性能优化,微服务 高级架构开发等等。

还有Java核心知识点+全套架构师学习资料和视频+一线大厂面试宝典+面试简历模板可以领取+阿里美团网易腾讯小米爱奇艺快手哔哩哔哩面试题+Spring源码合集+Java架构实战电子书。
[外链图片转存中…(img-3k272uTB-1712521977443)]

一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!

AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算

  • 17
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值