面试题(3)

本文详细讨论了AQS的可重入锁机制、IoC的理解、单例模式与Bean的区别、Spring事务的传播机制、事务失效条件、Bean生命周期、线程安全、ApplicationContext和BeanFactory的关系、事务实现原理、Spring容器启动流程、设计模式在Spring中的应用、SpringBoot注解及其实现、Mybatis优缺点、SQL占位符区别、索引设计原则以及MVCC的概念。
摘要由CSDN通过智能技术生成

目录

41.谈谈你对AQS的理解,AQS如何实现可重入锁?

42.谈谈你对IOC的理解

43.单例Bean和单例模式

44.Spring事务传播机制

45.Spring事务什么时候会失效?

46.Spring中的Bean创建的生命周期有哪些步骤

47.Spring中Bean是线程安全的吗

48.ApplicationContext和BeanFactory有什么区别

49.Spring中的事务是如何实现的

50.Spring中什么时候@Transactional会失效

51.Spring容器启动流程是怎样的

52.Spring用到了哪些设计模式

53. Spring Boot中常用注解及其底层实现

54.Spring Boot是如何启动Tomcat的

55.Mybatis的优缺点

56.#{}和${}的区别是什么?

 57.索引的基本原理

 58.索引设计的原则?

59.事务的基本特性和隔离级别

60.什么是MVCC


41.谈谈你对AQS的理解,AQS如何实现可重入锁?


1. AQS是⼀个JAVA线程同步的框架。是JDK中很多锁⼯具的核⼼实现框架。
2. 在AQS中,维护了⼀个信号量state和⼀个线程组成的双向链表队列。其中,这个线程队列,就是⽤ 来给线程排队的,⽽state就像是⼀个红绿灯,⽤来控制线程排队或者放⾏的。 在不同的场景下,有不⽤的意义。
3. 在可重⼊锁这个场景下,state就⽤来表示加锁的次数。0标识⽆锁,每加⼀次锁,state就加1。释放锁state就减1。


42.谈谈你对IOC的理解

  • 提到Spring 我们都能想到核心是,IOC和AOP
  • 那么我就谈一谈IOC的理解,说到IOC就要想到他的核心就是控制反转。
  • 对于我来说,控制反转就是把对于成员变量赋值的控制权,从代码中反转(转移)Spring工厂和配置文件中完成,他的好处就是解耦合,底层实现是工厂设计模式。


43.单例Bean和单例模式

  • 单例模式表示JVM中某个类的对象只会存在唯⼀⼀个。
  • ⽽单例Bean并不表示JVM中只能存在唯⼀的某个类的Bean对象。


44.Spring事务传播机制

  • 多个事务⽅法相互调⽤时,事务如何在这些⽅法间传播,⽅法A是⼀个事务的⽅法,⽅法A执⾏过程中调 ⽤了⽅法B,那么⽅法B有⽆事务以及⽅法B对事务的要求不同都会对⽅法A的事务具体执⾏造成影响, 同时⽅法A的事务对⽅法B的事务执⾏也有影响,这种影响具体是什么就由两个⽅法所定义的事务传播类型所决定。
  • REQUIRED(Spring中默认的传播类型):  如果a有事务,那么b就加入, 如果a没有事务,b就创建一个事务执行。
  • SUPPORT: 如果a有事务,b就加入,如果a没有事务,那么b也没有必要有事务
  • MANDATORY:如果a有事务,b就加入,没有事务,就抛出异常
  • REQUIRES_NEW: 如果a有事务,b暂时挂起,互不影响,各自执行
  • NOT_SUPPORTS:如果a有事务,则挂起事务,以非事务方式
  • NEVER:不使用事务,如果有事务就抛出异常
  • NESTED:如果当前有事务存在,就嵌套执行,跟REQUIRED一样。


45.Spring事务什么时候会失效?


Spring的事务其实就是Aop,进行了切面增强,如果事务失效就说明Aop动态代理失效。

  • 发生自身调用,类方法调用本类的this方法(this通常省略),动态代理就会失效
  • 数据库不支持事务
  • 有异常被吃掉,事务没有回滚
  • 没有被spring容器管理
  • @Transactional 注解需要在public方法上面,如果不是public修饰,导致事务失效


46.Spring中的Bean创建的生命周期有哪些步骤


实例化:

  •   通过推断构造方法(反射)
  •    实例工厂、静态工厂

属性注入:

  •  解析自动装配(@Autowried,byname,bytype,@Resource,@constractor),DI
  •  循环依赖

初始化:

  • 实现不同的XXXAware的回调方法
  • 调用初始化生命周期回调(实现init().@PostConstruct,实现InitializingBean接口)
  • 如bean实现Aop,创建动态代理

销毁:

  • Spring容器关闭时回调
  • 调用摧毁时回调

47.Spring中Bean是线程安全的吗


Spring本身并没有针对Bean做线程安全的处理,所以:

  • 如果Bean是⽆状态的,那么Bean则是线程安全的
  • 如果Bean是有状态的,那么Bean则不是线程安全的
  • 另外,Bean是不是线程安全,跟Bean的作⽤域没有关系,Bean的作⽤域只是表示Bean的⽣命周期范 围,对于任何⽣命周期的Bean都是⼀个对象,这个对象是不是线程安全的,还是得看这个Bean对象本身。


48.ApplicationContext和BeanFactory有什么区别

  • BeanFactory 是Spring的核心组件,表示bean工厂,管理bean,维护bean。ApplicationContext 继承了Beanfactory,不仅有BeanFactory所有的方法,还继承了诸如 EnvironmentCapable、MessageSource、ApplicationEventPublisher等接⼝,从⽽ ApplicationContext还有获取系统环境变量、国际化、事件发布等功能。
  • BeanFactory是延迟加载的,调用得时候才会getBean获取
  • ApplicationContext是积极加载的,new 出来的时候会加载所有的bean
  • Beanfactory 是手动注册的,ApplicationContext 是自动注册的

49.Spring中的事务是如何实现的


1. Spring事务底层是基于数据库事务和AOP机制的
2. ⾸先对于使⽤了@Transactional注解的Bean,Spring会创建⼀个代理对象作为Bean
3. 当调⽤代理对象的⽅法时,会先判断该⽅法上是否加了@Transactional注解
4. 如果加了,那么则利⽤事务管理器创建⼀个数据库连接
5. 并且修改数据库连接的autocommit属性为false,禁⽌此连接的⾃动提交,这是实现Spring事务⾮ 常重要的⼀步
6. 然后执⾏当前⽅法,⽅法中会执⾏sql
7. 执⾏完当前⽅法后,如果没有出现异常就直接提交事务
8. 如果出现了异常,并且这个异常是需要回滚的就会回滚事务,否则仍然提交事务
9. Spring事务的隔离级别对应的就是数据库的隔离级别
10. Spring事务的传播机制是Spring事务⾃⼰实现的,也是Spring事务中最复杂的
11. Spring事务的传播机制是基于数据库连接来做的,⼀个数据库连接⼀个事务,如果传播机制配置为 需要新开⼀个事务,那么实际上就是先建⽴⼀个数据库连接,在此新数据库连接上执⾏sql


50.Spring中什么时候@Transactional会失效


        因为Spring事务是基于代理来实现的,所以某个加了@Transactional的⽅法只有是被代理对象调⽤时, 那么这个注解才会⽣效,所以如果是被代理对象来调⽤这个⽅法,那么@Transactional是不会失效的。 同时如果某个⽅法是private的,那么@Transactional也会失效,因为底层cglib是基于⽗⼦类来实现 的,⼦类是不能重载⽗类的private⽅法的,所以⽆法很好的利⽤代理,也会导致@Transactianal失效


51.Spring容器启动流程是怎样的


1. 在创建Spring容器,也就是启动Spring时:
2. ⾸先会进⾏扫描,扫描得到所有的BeanDefinition对象,并存在⼀个Map中
3. 然后筛选出⾮懒加载的单例BeanDefinition进⾏创建Bean,对于多例Bean不需要在启动过程中去进 ⾏创建,对于多例Bean会在每次获取Bean时利⽤BeanDefinition去创建
4. 利⽤BeanDefinition创建Bean就是Bean的创建⽣命周期,这期间包括了合并BeanDefinition、推断 构造⽅法、实例化、属性填充、初始化前、初始化、初始化后等步骤,其中AOP就是发⽣在初始化 后这⼀步骤中
5. 单例Bean创建完了之后,Spring会发布⼀个容器启动事件
6. Spring启动结束
7. 在源码中会更复杂,⽐如源码中会提供⼀些模板⽅法,让⼦类来实现,⽐如源码中还涉及到⼀些
BeanFactoryPostProcessor和BeanPostProcessor的注册,Spring的扫描就是通过
BenaFactoryPostProcessor来实现的,依赖注⼊就是通过BeanPostProcessor来实现的
8. 在Spring启动过程中还会去处理@Import等注解


52.Spring用到了哪些设计模式

这是一道相对有难度的题目,你不仅要回设计模式,还要知道每个设计模式在 Spring 中是如何使用
的。
简单工厂模式 Spring 中的 BeanFactory 就是简单工厂模式的体现。根据传入一个唯一的标识来获
Bean 对象,但是在传入参数后创建还是传入参数前创建,要根据具体情况来定。
工厂模式 Spring 中的 FactoryBean 就是典型的工厂方法模式,实现了 FactoryBean 接口的 bean
是一类叫做 factory bean 。其特点是, spring 在使用 getBean() 调用获得该 bean 时,会自动调
用该 bean getObject() 方法,所以返回的不是 factory 这个 bean ,而是这个 bean.getOjbect()
方法的返回值。
单例模式 :在 spring 中用到的单例模式有: scope="singleton" ,注册式单例模式, bean 存放于
Map 中。 bean name 当做 key bean 当做 value
原型模式 :在 spring 中用到的原型模式有: scope="prototype" ,每次获取的是通过克隆生成的新
实例,对其进行修改时对原有实例对象不造成任何影响。
迭代器模式 :在 Spring 中有个 CompositeIterator 实现了 Iterator Iterable 接口和 Iterator
口,这两个都是迭代相关的接口。可以这么认为,实现了 Iterable 接口,则表示某个对象是可被迭
代的。 Iterator 接口相当于是一个迭代器,实现了 Iterator 接口,等于具体定义了这个可被迭代的
对象时如何进行迭代的。
代理模式 Spring 中经典的 AOP ,就是使用动态代理实现的,分 JDK CGlib 动态代理。
适配器模式 Spring 中的 AOP AdvisorAdapter 类,它有三个实现:
MethodBeforAdviceAdapter AfterReturnningAdviceAdapter ThrowsAdviceAdapter Spring
会根据不同的 AOP 配置来使用对应的 Advice ,与策略模式不同的是,一个方法可以同时拥有多个
Advice Spring 存在很多以 Adapter 结尾的,大多数都是适配器模式。
观察者模式 Spring 中的 Event Listener spring 事件: ApplicationEvent ,该抽象类继承了
EventObject 类, JDK 建议所有的事件都应该继承自 EventObject spring 事件监听器:
ApplicationListener ,该接口继承了 EventListener 接口, JDK 建议所有的事件监听器都应该继承
EventListener
模板模式 Spring 中的 org.springframework.jdbc.core.JdbcTemplate 就是非常经典的模板模式
的应用,里面的 execute 方法,把整个算法步骤都定义好了。
责任链模式 DispatcherServlet 中的 doDispatch() 方法中获取与请求匹配的处理器
HandlerExecutionChain this.getHandler() 方法的处理使用到了责任链模式。
注意 :这里只是列举了部分设计模式,其实里面用到了还有享元模式、建造者模式等。可选择性的
回答,主要是怕你回答了迭代器模式,然后继续问你,结果你一问三不知,那就尴了尬了。


53. Spring Boot中常用注解及其底层实现


1. @SpringBootApplication注解:这个注解标识了⼀个SpringBoot⼯程,它实际上是另外三个注解的 组合,这三个注解是:
        a. @SpringBootConfiguration:这个注解实际就是⼀个@Configuration,表示启动类也是⼀个 配置类
        b. @EnableAutoConfiguration:向Spring容器中导⼊了⼀个Selector,⽤来加载ClassPath下
SpringFactories中所定义的⾃动配置类,将这些⾃动加载为配置Bean
        c. @ComponentScan:标识扫描路径,因为默认是没有配置实际扫描路径,所以SpringBoot扫描的路径是启动类所在的当前⽬录
2. @Bean注解:⽤来定义Bean,类似于XML中的<bean>标签,Spring在启动时,会对加了@Bean注 解的⽅法进⾏解析,将⽅法的名字做为beanName,并通过执⾏⽅法得到bean对象
3. @Controller、@Service、@ ResponseBody、@Autowired都可以说


54.Spring Boot是如何启动Tomcat的


1. ⾸先,SpringBoot在启动时会先创建⼀个Spring容器

2. 在创建Spring容器过程中,会利⽤@ConditionalOnClass技术来判断当前classpath中是否存在
Tomcat依赖,如果存在则会⽣成⼀个启动Tomcat的Bean
3. Spring容器创建完之后,就会获取启动Tomcat的Bean,并创建Tomcat对象,并绑定端⼝等,然后 启动Tomcat


55.Mybatis的优缺点


优点:
1. 基于 SQL 语句编程,相当灵活,不会对应⽤程序或者数据库的现有设计造成任何影响,SQL 写在 XML ⾥,解除 sql 与程序代码的耦合,便于统⼀管理;提供 XML 标签, ⽀持编写动态 SQL 语
句, 并可重⽤。
2. 与 JDBC 相⽐,减少了 50%以上的代码量,消除了 JDBC ⼤量冗余的代码,不需要⼿动开关连
接;
3. 很好的与各种数据库兼容( 因为 MyBatis 使⽤ JDBC 来连接数据库,所以只要JDBC ⽀持的数据库 MyBatis 都⽀持)。
4. 能够与 Spring 很好的集成;
5. 提供映射标签, ⽀持对象与数据库的 ORM 字段关系映射; 提供对象关系映射标签, ⽀持对象关 系组件维护。
缺点:
27 1. SQL 语句的编写⼯作量较⼤, 尤其当字段多、关联表多时, 对开发⼈员编写SQL 语句的功底有⼀定要求。
     2. SQL语句依赖于数据库, 导致数据库移植性差, 不能随意更换数据库。


56.#{}和${}的区别是什么?


#{}是预编译处理、是占位符, ${}是字符串替换、是拼接符。 Mybatis在处理#{}时,会将sql中的#{}替换为?号,调⽤ PreparedStatement 来赋值; Mybatis在处理${}时,会将sql中的${}替换成变量的值,调⽤ Statement 来赋值; 使⽤#{}可以有效的防⽌ SQL 注⼊, 提⾼系统安全性

 57.索引的基本原理


索引⽤来快速地寻找那些具有特定值的记录。如果没有索引,⼀般来说执⾏查询时遍历整张表。
索引的原理:就是把⽆序的数据变成有序的查询
1. 把创建了索引的列的内容进⾏排序
2. 对排序结果⽣成倒排表
3. 在倒排表内容上拼上数据地址链
4. 在查询的时候,先拿到倒排表内容,再取出数据地址链,从⽽拿到具体数据


 58.索引设计的原则?


查询更快、占⽤空间更⼩
1. 适合索引的列是出现在where⼦句中的列,或者连接⼦句中指定的列
2. 基数较⼩的表,索引效果较差,没有必要在此列建⽴索引
3. 使⽤短索引,如果对⻓字符串列进⾏索引,应该指定⼀个前缀⻓度,这样能够节省⼤量索引空间, 如果搜索词超过索引前缀⻓度,则使⽤索引排除不匹配的⾏,然后检查其余⾏是否可能匹配。
4. 不要过度索引。索引需要额外的磁盘空间,并降低写操作的性能。在修改表内容的时候,索引会进 ⾏更新甚⾄重构,索引列越多,这个时间就会越⻓。所以只保持需要的索引有利于查询即可。
5. 定义有外键的数据列⼀定要建⽴索引。
6. 更新频繁字段不适合创建索引
7. 若是不能有效区分数据的列不适合做索引列(如性别,男⼥未知,最多也就三种,区分度实在太低)
8. 尽量的扩展索引,不要新建索引。⽐如表中已经有a的索引,现在要加(a,b)的索引,那么只需要修 改原来的索引即可。
9. 对于那些查询中很少涉及的列,重复值⽐较多的列不要建⽴索引。
10. 对于定义为text、image和bit的数据类型的列不要建⽴索引。

59.事务的基本特性和隔离级别

事务基本特性ACID分别是:
原⼦性指的是⼀个事务中的操作要么全部成功,要么全部失败。
⼀致性指的是数据库总是从⼀个⼀致性的状态转换到另外⼀个⼀致性的状态。⽐如A转账给B100块钱, 假设A只有90块,⽀付之前我们数据库⾥的数据都是符合约束的,但是如果事务执⾏成功了,我们的数据库 数据就破坏约束了,因此事务不能成功,这⾥我们说事务提供了⼀致性的保证 隔离性指的是⼀个事务的修改在最终提交前,对其他事务是不可⻅的。 持久性指的是⼀旦事务提交,所做的修改就会永久保存到数据库中。 隔离性有4个隔离级别,分别是:

  •  read uncommit 读未提交,可能会读到其他事务未提交的数据,也叫做脏读。⽤户本来应该读取到id=1的⽤户age应该是10,结果读取到了其他事务还没有提交的事务,结果读取 结果age=20,这就是脏读。
  •  read commit 读已提交,两次读取结果不⼀致,叫做不可重复读。不可重复读解决了脏读的问题,他只会读取已经提交的事务。⽤户开启事务读取id=1⽤户,查询到age=10,再次读取发现结果=20,在同⼀个事务⾥同⼀个查询读取到不同的结果叫做不可重复读。
  • repeatable read 可重复复读,这是mysql的默认级别,就是每次读取结果都⼀样,但是有可能产 ⽣幻读。
  • serializable 串⾏,⼀般是不会使⽤的,他会给每⼀⾏读取的数据加锁,会导致⼤量超时和锁竞争 的问题

60.什么是MVCC

多版本并发控制( MVCC=Multi-Version Concurrency Control ),是一种用来解决读 - 写冲突的无
锁并发控制。也就是为事务分配单向增长的时间戳,为每个修改保存一个版本。版本与事务时间戳
关联,读操作只读该事务开始前的数据库的快照(复制了一份数据)。这样在读操作不用阻塞写操
作,写操作不用阻塞读操作的同时,避免了脏读和不可重复读

.
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值