《面试八股文》之 Spring 18卷,2024年最新解析 互联网Java工程师面试全解析

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

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

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

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

如果你需要这些资料,可以添加V获取:vip1024b (备注Java)
img

正文

那么究竟**「什么是控制反转」**?

控制反转就是说,「把对象的控制权交给了 spring,由 spring 容器进行管理」,我们不进行任何操作

那么为**「什么需要控制反转」**?

我们想象一下,没有控制反转的时候,我们需要**「自己去创建对象,配置对象」,还要「人工去处理对象与对象之间的各种复杂的依赖关系」**,当一个工程的量起来之后,这种关系的维护是非常令人头痛的,所以就有了控制反转这个概念,将对象的创建、配置等一系列操作交给 spring 去管理,我们在使用的时候只要去取就好了

4.spring 中的 IOC 容器有哪些?有什么区别?


spring 主要提供了**「两种 IOC 容器」**,一种是 「BeanFactory」,还有一种是 「ApplicationContext」

它们的区别就在于,BeanFactory 「只提供了最基本的实例化对象和拿对象的功能」,而 ApplicationContext 是继承了 BeanFactory 所派生出来的产物,是其子类,它的作用更加的强大,比如支持注解注入、国际化等功能

5.那 BeanFactory 和 FactoryBean 又有什么区别?


这两个是**「不同的产物」**

「BeanFactory 是 IOC 容器」,是用来承载对象的

「FactoryBean 是一个接口」,为 Bean 提供了更加灵活的方式,通过代理一个Bean对象,对方法前后做一些操作。

6.@Repository、@Service、@Compent、@Controller它们有什么区别?


这四个注解的**「本质都是一样的,都是将被该注解标识的对象放入 spring 容器当中,只是为了在使用上区分不同的应用分层」**

  • @Repository:dao层

  • @Service:service层

  • @Controller:controller层

  • @Compent:其他不属于以上三层的统一使用该注解

7.那么 DI 又是什么?


DI 就是依赖注入,其实和 IOC 大致相同,只不过是**「同一个概念使用了不同的角度去阐述」**

DI 所描述的**「重点是在于依赖」**,我们说了 「IOC 的核心功能就是在于在程序运行时动态的向某个对象提供其他的依赖对象」,而这个功能就是依靠 DI 去完成的,比如我们需要注入一个对象 A,而这个对象 A 依赖一个对象 B,那么我们就需要把这个对象 B 注入到对象 A 中,这就是依赖注入

spring 中有三种注入方式

  • 接口注入

  • 构造器注入

  • set注入

8.说说 AOP 是什么?


AOP 意为:「面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术」

AOP 是 「OOP(面向对象编程) 的延续」,是 Spring 框架中的一个重要内容,是函数式编程的一种衍生范型。利用 AOP 可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

「AOP 实现主要分为两类:」

图片

  • 「静态 AOP 实现」, AOP 框架**「在编译阶段」**对程序源代码进行修改,生成了静态的 AOP 代理类(生成的 *.class 文件已经被改掉了,需要使用特定的编译器),比如 AspectJ

  • 「动态 AOP 实现」, AOP 框架**「在运行阶段」**对动态生成代理对象(在内存中以 JDK 动态代理,或 CGlib 动态地生成 AOP 代理类),如 SpringAOP

spring 中 AOP 的实现是**「通过动态代理实现的」**,如果是实现了接口就会使用 JDK 动态代理,否则就使用 CGLIB 代理。

图片

「有 5 种通知类型:」

  • 「@Before」:在目标方法调用前去通知

  • 「@AfterReturning」:在目标方法返回或异常后调用

  • 「@AfterThrowing」:在目标方法返回后调用

  • 「@After」:在目标方法异常后调用

  • 「@Around」:将目标方法封装起来,自己确定调用时机

9.动态代理和静态代理有什么区别?


「静态代理」

  • 由程序员创建或由特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了

  • 静态代理通常只代理一个类

  • 静态代理事先知道要代理的是什么

「动态代理」

  • 在程序运行时,运用反射机制动态创建而成

  • 动态代理是代理一个接口下的多个实现类

  • 动态代理不知道要代理什么东西,只有在运行时才知道

10.JDK 动态代理和 CGLIB 代理有什么区别?


JDK 动态代理时业务类**「必须要实现某个接口」,它是「基于反射的机制实现的」**,生成一个实现同样接口的一个代理类,然后通过重写方法的方式,实现对代码的增强。

CGLIB 动态代理是使用字节码处理框架 ASM,其原理是通过字节码技术为一个类**「创建子类,然后重写父类的方法」**,实现对代码的增强。

11.Spring AOP 和 AspectJ AOP 有什么区别?


Spring AOP 是运行时增强,是通过**「动态代理实现」**的

AspectJ AOP 是编译时增强,需要特殊的编译器才可以完成,是通过**「修改代码来实现」的,支持「三种织入方式」**

  • 「编译时织入」:就是在编译字节码的时候织入相关代理类

  • 「编译后织入」:编译完初始类后发现需要 AOP 增强,然后织入相关代码

  • 「类加载时织入」:指在加载器加载类的时候织入

图片

| 主要区别 | Spring AOP | AspecjtJ AOP |

| — | — | — |

| 增强方式 | 运行时增强 | 编译时增强 |

| 实现方式 | 动态代理 | 修改代码 |

| 编译器 | javac | 特殊的编译器 ajc |

| 效率 | 较低(运行时反射损耗性能) | 较高 |

| 织入方式 | 运行时 | 编译时、编译后、类加载时 |

12.spring 中 Bean 的生命周期是怎样的?


SpringBean 生命周期大致分为4个阶段:

图片

  • 1.「实例化」,实例化该 Bean 对象

  • 2.「填充属性」,给该 Bean 赋值

  • 3.「初始化」

  • 如果实现了 Aware 接口,会通过其接口获取容器资源

  • 如果实现了 BeanPostProcessor 接口,则会回调该接口的前置和后置处理增强

  • 如果配置了 init-method 方法,]会执行该方法

  • 4.「销毁」

  • 如果实现了 DisposableBean 接口,则会回调该接口的 destroy 方法

  • 如果配置了 destroy-method 方法,则会执行 destroy-method 配置的方法

13.spring 是怎么解决循环依赖的?


图片

循环依赖就是说两个对象相互依赖,形成了一个环形的调用链路

spring 使用三级缓存去解决循环依赖的,其**「核心逻辑就是把实例化和初始化的步骤分开,然后放入缓存中」**,供另一个对象调用

  • 「第一级缓存」:用来保存实例化、初始化都完成的对象

  • 「第二级缓存」:用来保存实例化完成,但是未初始化完成的对象

  • 「第三级缓存」:用来保存一个对象工厂,提供一个匿名内部类,用于创建二级缓存中的对象


当 A、B 两个类发生循环引用时 大致流程

  • 1.A 完成实例化后,去**「创建一个对象工厂,并放入三级缓存」**当中

  • 如果 A 被 AOP 代理,那么通过这个工厂获取到的就是 A 代理后的对象

  • 如果 A 没有被 AOP 代理,那么这个工厂获取到的就是 A 实例化的对象

  • 2.A 进行属性注入时,去**「创建 B」**

  • 3.B 进行属性注入,需要 A ,则**「从三级缓存中去取 A 工厂代理对象」**并注入,然后删除三级缓存中的 A 工厂,将 A 对象放入二级缓存

  • 4.B 完成后续属性注入,直到初始化结束,将 B 放入一级缓存

  • 5.「A 从一级缓存中取到 B 并且注入 B」, 直到完成后续操作,将 A 从二级缓存删除并且放入一级缓存,循环依赖结束


spring 解决循环依赖有两个前提条件:

  • 1.**「不全是构造器方式」**的循环依赖(否则无法分离初始化和实例化的操作)

  • 2.「必须是单例」(否则无法保证是同一对象)

14.为什么要使用三级缓存,二级缓存不能解决吗?


可以,三级缓存的功能是只有真正发生循环依赖的时候,才去提前生成代理对象,否则只会**「创建一个工厂并将其放入到三级缓存」**中,但是不会去通过这个工厂去真正创建对象。

如果使用二级缓存解决循环依赖,意味着所有 Bean 在实例化后就要完成 AOP 代理,这样**「违背了 Spring 设计的原则」**,Spring 在设计之初就是在 Bean 生命周期的最后一步来完成 AOP 代理,而不是在实例化后就立马进行 AOP 代理。

15.@Autowired 和 @Resource 有什么区别?


  • 「@Resource 是 Java 自己的注解」,@Resource 有两个属性是比较重要的,分是 name 和 type;Spring 将 @Resource 注解的 name 属性解析为 bean 的名字,而 type 属性则解析为 bean 的类型。所以如果使用 name 属性,则使用 byName 的自动注入策略,而使用 type 属性时则使用 byType 自动注入策略。如果既不指定 name 也不指定 type 属性,这时将通过反射机制使用 byName 自动注入策略。

  • 「@Autowired 是spring 的注解」,是 spring2.5 版本引入的,Autowired 只根据 type 进行注入,「不会去匹配 name」。如果涉及到 type 无法辨别注入对象时,那需要依赖 @Qualifier 或 @Primary 注解一起来修饰。

完结

Redis基于内存,常用作于缓存的一种技术,并且Redis存储的方式是以key-value的形式。Redis是如今互联网技术架构中,使用最广泛的缓存,在工作中常常会使用到。Redis也是中高级后端工程师技术面试中,面试官最喜欢问的问题之一,因此作为Java开发者,Redis是我们必须要掌握的。

Redis 是 NoSQL 数据库领域的佼佼者,如果你需要了解 Redis 是如何实现高并发、海量数据存储的,那么这份腾讯专家手敲《Redis源码日志笔记》将会是你的最佳选择。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Java)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
网技术架构中,使用最广泛的缓存,在工作中常常会使用到。Redis也是中高级后端工程师技术面试中,面试官最喜欢问的问题之一,因此作为Java开发者,Redis是我们必须要掌握的。

Redis 是 NoSQL 数据库领域的佼佼者,如果你需要了解 Redis 是如何实现高并发、海量数据存储的,那么这份腾讯专家手敲《Redis源码日志笔记》将会是你的最佳选择。

[外链图片转存中…(img-6HwCtGsQ-1713430394249)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Java)
[外链图片转存中…(img-i1nBBsRB-1713430394250)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值