Spring的一些常见面试题
Spring八股文
源码解析
反射
1、谈谈spring ioc的理解,原理和实现?
总:两层意思:控制反转和容器。
控制反转:他是一种思想理论,原来的对象是由我们使用者自己来进行控制的,而有了spring之后就把对象交给了spring来给我们进行管理;
容器:存放具体存储对象的。
分:
2、谈一下spring ioc的底层实现
1、xml 解析——XML有三种解析方式:DOM4J SAX STAX DOM
2、工厂模式——把对类的创建初始化全都交给一个工厂来执行,而用户不需要去关心创建的过程是什么样的
3、反射 ——反射可以在运行时根据指定的类名获得类的信息
可以参考一下这里关于IOC的底层实现
3、描述一下bean的生命周期?就是bean从创建到销毁的全过程
1.实例化
a.通过反射去推断构造函数进行实例化
b.实例工厂、静态工厂
2.属性赋值
a.解析自动装配(byname bytype constractor none @Autowired) DI的体现 b.循环依赖
3.初始化
a.调用XXXAware回调方法
b.调用初始化生命周期回调(三种)
c.如果bean实现aop 创建动态代理
4.销毁
a.在spring容器关闭的时候进行调用
b.调用销毁生命周期回调
4、spring 是如何解决循环依赖问题的?
5、spring中用到的设计模式
6、spring的AOP底层实现原理?
7、spring 的事务是如何回滚的?
8、谈一下spring 的事务传播?
spring 是如何解决循环依赖问题的?
可以使用 @Lazy 注解进行修饰
具体可以看 @Lazy注解的作用
什么时候用二级缓存什么时候用三级缓存解决
spring一级缓存二级缓存和三级缓存的区别
去看源码:DefaultSingletonBeanRegistry类中
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
//一级缓存
private final Map<String, Object> singletonObjects = new ConcurrentHashMap(256);
//二级缓存
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap(16);
//三级缓存
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap(16);
}
//三级缓存中map储存的value
@FunctionalInterface
public interface ObjectFactory<T> {
T getObject() throws BeansException;
}
解决循环依赖问题
答:Spring通过三级缓存解决了循环依赖(一二三级缓存分别时什么),其中一级缓存为单例池(singletonObjects)(已经初始化的bean),二级缓存为早期曝光对象earlySingletonObjects(已经实例化但未初始化),三级缓存为早期曝光对象工厂(创建bean对象对应的bean工厂)(singletonFactories)。
一二级缓存使用的是ConcurrentHashMap(为了安全,bean默认是单例)
三级缓存用的是HashMap
三级缓存中,有一个方法用了synchronized修饰
当A、B两个类发生循环引用时,在A完成实例化后,就使用实例化后的对象去创建一个对象工厂,添加到三级缓存中,如果A被AOP代理,那么通过这个工厂获取到的就是A代理后的对象,如果A没有被AOP代理,那么这个工厂获取到的就是A实例化的对象。
当A进行属性注入时,会去创建B,同时B又依赖了A,所以创建B的同时又会去调用getBean(a)来获取需要的依赖,此时的getBean(a)会从缓存中获取:
❝第一步:先获取到三级缓存中的工厂;
第二步:调用对象工工厂的getObject方法来获取到对应的对象,得到这个对象后将其注入到B中。紧接着B会走完它的生命周期流程,包括初始化、后置处理器等。
第三步:当B创建完后,会将B再注入到A中,此时A再完成它的整个生命周期。至此,循环依赖结束!
❞
面试官:为什么要使用三级缓存呢?二级缓存能解决循环依赖吗?
❝答:如果要使用二级缓存解决循环依赖,意味着所有Bean在实例化后就要完成AOP代理,这样违背了Spring设计的原则,Spring在设计之初就是通过AnnotationAwareAspectJAutoProxyCreator这个后置处理器来在Bean生命周期的最后一步来完成AOP代理,而不是在实例化后就立马进行AOP代理。
❞
Spring涉及的设计模式以及应用场景
【Spirng】8.spring框架中使用了哪些设计模式及应用场景_哔哩哔哩_bilibili
- 工厂模式,在各种BeanFactory以及ApplicationContext创建中都用到了
- 模版模式,在各种BeanFactory以及ApplicationContext实现中也都用到了
- 代理模式,Spring AOP利用了AspectJ AOP实现的! AspectJ AOP的底层用了动态代理
- 策略模式,加载资源文件的方式,使用了不同的方法,比如: ClassPathResourece,FileSystemResource,ServletContextResource,UrlResource但他们都有共同的借口Resource;在Aop的实现中,采用了两种不同的方式,JDK动态代理和CGLIB代理
- 单例模式,比如在创建bean的时候。
- 观察者模式,spring中的ApplicationEvent,ApplicationListener,ApplicationEventPublisher
- 适配器模式,MethodBeforeAdviceAdapter,ThrowsAdviceAdapter,AfterReturningAdapter
- 装饰者模式,源码中类型带Wrapper或者Decorator的都是
SpringBean的生命周期
1、解析xml配置或注解配置的类,得到BeanDefinition;
2、通过BeanDefinition反射创建Bean对象;
3、对Bean对象进行属性填充;
4、回调实现了Aware接口的方法,如BeanNameAware;
5、调用BeanPostProcessor的初始化前方法;
6、调用init初始化方法;
7、调用BeanPostProcessor的初始化后方法,此处会进行AOP;
8、将创建的Bean对象放入一个Map中;
9、业务使用Bean对象;
10、Spring容器关闭时调用DisposableBean的destory()方法;
Spring的核心是什么?
Spring是一个开源框架,他是为了简化企业开发而生的,更加优雅和简洁.
Spring是整个Spring生态中的基石,其他的框架都是在spring的基础上进行开发的
Spring 两大核心:IOC和AOP
IOC:
容器的一个创建过程.需要进行了解一下,拓展点,反射进行实例化....
IOC:是一种编程思想,原本对象的创建以及管理,都是由我们程序员自己来进行的,然后有了Spring之后呢,bean就交由Spring来替我们控制和进行管理,我们只需要专注于业务的处理就可以了,
IOC 是一种思想,如果问你DI是什么,他才是Spring的一个具体实现方式
容器
AOP:
AOP的使用
面向切面编程 , 为 解耦 而生 , 底层是 动态代理 , 动态代理有 jdk动态代理(代理接口的) 还有 cglib动态代理(代理类的) 两种实现方式
当我们项目需要用到跟业务不相关的公共功能的时候,例如日志,事务配置(@Transactional),异常处理,可以用到AOP,把一些关键的配置,插入到我们的业务代码中
定义一个切面类:
(首先需要导入两个包 : spring-aop 和 spring-aspects)
- 加上@Component注解 @Aspect注解,他就是一个切面类
- 定义一个@Pointcut , 再来一个 @After @Before 就可以执行了
- 他在spring底层会转换成对应个数的advisor
Spring的事务隔离级别
Mysql隔离级别|特性|传播行为
基本跟Mysql的事务隔离级别差不多,5种 ,多了一个默认ISOLATION_DEFAULT: 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别.另外四个与JDBC的隔离级别相对应。
Spring的5种事务隔离级别
例如A类用了事务,A类里面用到了B类,B类里面也有事务
若此时事务级别是required 因为A类有事务,所以用A的事务
Spring是如何简化开发的
- 基于POJO的轻量级和最小侵入性编程
- 通过依赖注入和面向接口实现松耦合
- 他有很多自带的可拓展的接口,你可以进行实现重写其中的方法即可使用
- 基于切面和惯例进行声明式编程,只需要在方法上加上@Transactional注解即可
- 通过切面和模板减少样板式代码,
- 例如:你要在一些方法中切入一些日志,你只需要写好一个切面,告诉他在哪些方法中切入即可
Spring bean中的id和name是否可以重复
同名bean:多个bean 有相同的 name 或者 id,称之为同名bean
bean 的id 和 name的区别
id和name都是spring 容器中bean 的唯一标识符。 name和id都不是必须的,可以没有
- id: 一个bean的唯一标识 , 命名格式必须符合XML ID属性的命名规范
- name: 可以用特殊字符,并且一个bean可以用多个名称:name=“bean1,bean2,bean3”
,用逗号或者分号或者空格隔开。如果没有id,则name的第一个名称默认是id
spring 容器如何处理同名bean?
- 同一个spring配置文件中,bean的 id、name是不能够重复的,否则spring容器启动时会报错。
如果一个spring容器从多个配置文件中加载配置信息,则多个配置文件中是允许有同名bean的,并且后面加载的配置文件的中的bean定义会覆盖前面加载的同名bean。
1、在spring同一个配置文件中,不能存在id相同的两个bean,否则会报错。
2、在两个不同的spring配置文件中,可以存在id相同的两个bean,启动时,不会报错。这是因为spring
ioc容器在加载bean的过程中,类DefaultListableBeanFactory会对id相同的bean进行处理:后加载的配置文件的bean,覆盖先加载的配置文件的bean。DefaultListableBeanFactory类中,有个属性allowBeanDefinitionOverriding,默认值为true,该值就是用来指定出现两个bean的id相同的情况下,如何进行处理。如果该值为false,则不会进行覆盖,而是抛出异常。
spring 容器如何处理没有指定id、name属性的bean?
如果 一个 bean 标签未指定 id、name 属性,则 spring容器会给其一个默认的id,值为其类全名。
如果有多个bean标签未指定 id、name 属性,则spring容器会按照其出现的次序,分别给其指定 id 值为 “类全名#1”, “类全名#2”
如下:
配置文件:
<bean class="com.xxx.UserInfo">
<property name="accountName" value="no-id-no-name0"></property>
</bean>
<bean class="com.xxx.UserInfo">
<property name="accountName" value="no-id-no-name1"></property>
</bean>
<bean class="com.xxx.UserInfo">
<property name="accountName" value="no-id-no-name2"></property>
</bean>
获取bean的方式:
UserInfo u4 = (UserInfo)ctx.getBean("com.xxx.UserInfo");
UserInfo u5 = (UserInfo)ctx.getBean("com.xxx.UserInfo#1");
UserInfo u6 = (UserInfo)ctx.getBean("com.xxx.UserInfo#2");
SpringBoot的自动装配原理
主要是启动类上的@SpringBootApplication注解
里面主要是三个注解
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan
大致流程
- 启动类
- SpringApplication的构造方法
- SpringApplication.run方法
- 启动过程中主要有两个方法:prepareContext()和 refreshContext()
- prepareContext方法中的 load()方法 ,将当前启动类作为一个BeanDefinition注册到BeanDefinitionMap中
- refreshContext()方法中的 refresh()方法,对整个容器进行refresh操作,执行BeanFactory的后置处理器(就是一些PostProcessors) 。。。
- @Configuration是Spring的一个注解,其修饰的类会加入Spring容器。这就说明SpringBoot的启动类会加入Spring容器。
- @ComponentScan注解: 从声明这个注解的类所在的包开始,扫描包及子包,把符合扫描规则的类装配到spring容器中。而我们的@SpringBootApplication注解声明的类就是main函数所在的启动类,因此扫描的包是该类所在包及其子包。因此,一般启动类会放在一个比较前的包目录中
- @EnableAutoConfiguration注解,(看下面对@Import注解的一个讲解)调用了Spring容器中SpringFactoriesLoader类的loadSpringFactories方法,他是基于SPI机制,扫描当前ClassPath下所有的配置类,调用所有导入的依赖包下的 MATE-INF包下面的Spring.factories文件中key为EnableAutoConfiguration的所有value。
里面有@Import注解,解析@Import注解的时候比较特别,会有一个collectImports()方法,会把所有包含@Import的注解都解析到BeanDefinitionMap中。 - 至此,springboot的自动装配就完成了
参考 Spring自动装配概述
也可以看看这篇文章:关于@SpringBootApplication注解的一些讲解
@Impot注解中的AutoConfigurationImportSelector
调用AutoConfigurationImportSelector类(相当于一个处理器)中的process()方法进而触发getCandidateConfigurations()方法获取Spring.factories文件下的key为EnableAutoConfiguration的所有value,所以这就是为什么很多人的文章中都说Springboot的自动装配就是调用@EnableAutoConfiguration注解下的@Import中的AutoConfigurationImportSelector类,主要就是通过这种不断解析注解的方法去调用的
@EnableAutoConfiguration下的@AutoConfigurationPackage注解
basePackages是个set集合,但是容器当中始终只有一个BasePackagesBeanDefinition对象,也就是只要代码当中添加@AutoConfigurationPackage注解,就会将注解所在的包名添加到basePackages集合当中。
然后@Import注解是如何获取到类的?
可以看出来AnnotationMetadata其实就是@Import所在的类当中的元数据。这个元数据就是@Import所在的类信息,例如这个类的全类名以及所用到了哪些注解等等…
所以他是通过传入 Metadata 参数来拿到当前传入的类的
关于@Import注解的一些讲解
Spring的一些常见面试题的更多相关文章
- Spring 常见面试题总结 | JavaGuide
首发于 JavaGuide 在线网站:Spring 常见面试题总结 最近在对 JavaGuide 的内容进行重构完善,同步一下最新更新,希望能够帮助你. Spring 基础 什么是 Spring 框架 ...
- Vue常见面试题汇总
Vue框架常见面试题 1.active-class是哪个组件的属性?嵌套路由怎么定义? 答:vue-router模块的router-link组件. 2.怎么定义vue-router的动态路由?怎么 ...
- 【搞定 Java 并发面试】面试最常问的 Java 并发基础常见面试题总结!
本文为 SnailClimb 的原创,目前已经收录自我开源的 JavaGuide 中(61.5 k Star![Java学习+面试指南] 一份涵盖大部分Java程序员所需要掌握的核心知识.欢迎 Sta ...
- 【搞定 Java 并发面试】面试最常问的 Java 并发进阶常见面试题总结!
本文为 SnailClimb 的原创,目前已经收录自我开源的 JavaGuide 中(61.5 k Star![Java学习+面试指南] 一份涵盖大部分Java程序员所需要掌握的核心知识.觉得内容不错 ...
- SpringMVC常见面试题总结(超详细回答)
SpringMVC常见面试题总结(超详细回答) 1.什么是Spring MVC ?简单介绍下你对springMVC的理解? Spring MVC是一个基于Java的实现了MVC设计模式的请求驱动类型的 ...
- JAVA常见面试题问题简述(持续更新中)
JAVA常见面试题问题简述 1. springcloud和dubbo的区别 ①相比之下springcloud 的社区会更加活跃,解决问题的速度也会越来越快,dubbo相对来说如果碰到没有解决的问题,就 ...
- java常见面试题及答案 1-10(基础篇)
java常见面试题及答案 1.什么是Java虚拟机?为什么Java被称作是"平台无关的编程语言"? Java 虚拟机是一个可以执行 Java 字节码的虚拟机进程.Java 源文件被 ...
- Web开发的常见面试题HTML和HTML5等
作为一名前端开发人员,HTML,HTML5以及网站优化都是必须掌握的技术,下面列举一下HTML, HTML5, 网站优化等常见的面试题: HTML常见面试题: 1. 什么是Semantic HTML( ...
- 常见面试题之ListView的复用及如何优化
经常有人问我,作为刚毕业的要去面试,关于安卓开发的问题,技术面试官会经常问哪些问题呢?我想来想去不能一股脑的全写出来,我准备把这些问题单独拿出来写,并详细的分析一下,这样对于初学者是最有帮助的.这次的 ...
- iOS常见面试题汇总
iOS常见面试题汇总 1. 什么是 ARC? (ARC 是为了解决什么问题而诞生的?) ARC 是 Automatic Reference Counting 的缩写, 即自动引用计数. 这是苹果在 i ...
随机推荐
- 一文速通Python并行计算:00 并行计算的基本概念
一文速通 Python 并行计算:00 并行计算的基本概念 摘要: 该文介绍了 Python 并行计算的核心概念.编程模型及其应用,并介绍了了并行程序的性能分析与优化方法,如并行效率.加速比及 Amd ...
- B@se-还原错误字母表转码的base64编码
题目: 密文:MyLkTaP3FaA7KOWjTmKkVjWjVzKjdeNvTnAjoH9iZOIvTeHbvD== JASGBWcQPRXEFLbCDIlmnHUVKTYZdMovwipatNOe ...
- VSCode 中 Json 文件介绍
Visual Studio Code 官方文档 1. Json 配置文件 Editing JSON with Visual Studio Code settings.json 分类 defaultse ...
- 在 CentOS 系统下搭建 ZeroTier Moon
在 CentOS 系统下搭建 ZeroTier Moon 服务器时,生成的配置文件位置是在 /var/lib/zerotier-one/ 目录下.该目录包含了 ZeroTier One 的运行时数据, ...
- 虚拟机为什么ping不通主机
在虚拟机里各种操作都正常.就是ping不通主机.为什么? NAT模式下(网络地址转换模式),虚拟机后网络适配器就会出现VMnet8网卡: 把VMnet8的ip4设定成你主机同段IP.这个VMnet8地 ...
- 跨网段和局域网的SQL SERVER发布订阅配置图解和常见问题
非常详细,傻瓜式依葫芦画瓢即可. 特别提示:订阅机器上的防火墙以及发布机器远程登录订阅机的问题 通过非命令行方式配置同步订阅 (1)实验环境说明 (2)实验前准备 (3)订阅设置 (4)测试同步订阅 ...
- 使用Nginx反向代理本地服务(无固定公网IP通过端口映射公开的服务)的坑
使用Nginx反向代理本地服务(无固定公网IP通过端口映射公开的服务)的坑 前言:之前公司的服务器都是云服务器,性能比较差,而我们有一些内部使用的系统和极少数外部用户使用的系统,对资源有一定的要求,也 ...
- 在类 Unix 系统中将 Nginx 源码导入 CLion 并调试运行
零.写在最前面 0.1 关于系统 如标题所述,本文的操作需要一个类 Unix 系统(MacOS.CentOS.Ubuntu 等). 同时这些类 Unix 系统还需要有 gcc 编译器.具体如何搞定这些 ...
- 面试官:如果某个业务量突然提升100倍QPS你会怎么做?
"假设你负责的系统,某个业务线的QPS突然暴增100倍,你会怎么应对?" --这是上周朋友去面试,被问到一道题,他答了"加机器扩容",结果面试官眉头一皱:&qu ...
- NetCAT:来自网络的实用缓存攻击
不断增加的外围设备正在增加现代处理器中内存管理子系统的压力,例如:DRAM的可用吞吐量已经不能满足现代网卡的传输速率.为了达到承诺的传输性能,Intel处理器使IO操作直接在末级缓存(LLC)上进行, ...