1.常见的ORM框架有哪些?

1.Mybatis
Mybatis是一种典型的半自动的ORM框架,所谓的半自动,是因为还需要手动的写SQL语句,再由框架根据SQL及传入数据来组装为要执行的SQL。

优点为︰

  • 因为由程序员自己写SQL,相对来说学习门槛更低,更容易入门。
  • 更方便做SQL的性能优化及维护。
  • 对关系型数据库的模型要求不高,这样在做数据库模型调整时,影响不会太大。适合软件需求变更比较频繁的系统,因此国内系统大部分都是使用如Mybatis这样的半自动ORM框架。

缺陷为:

  • 不能跨数据库,因为写的SQL可能存在某数据库特有的语法或关键词

2.Hibernate
Hibernate是一种典型的全自动ORM框架,所谓的全自动,是SQL语句都不用在编写,基于框架的API,可以将对象自动的组装为要执行的SQL语句。
优点为∶

  1. 全自动ORM框架,自动的组装为SQL语句。
  2. 可以跨数据库,框架提供了多套主流数据库的SQL生成规则。

缺点为︰

  1. 学习门槛更高,要学习框架API与SQL之间的转换关系对数据库模型依赖非常大,在软件需求变更频繁的系统中,会导致非常难以调整及维护。可能数据库中随便改一个表或字段的定义,Java代码中要修改几十处。
  2. 很难定位问题,也很难进行性能优化:需要精通框架,对数据库模型设计也非常熟悉。

2.Bean容器/loc容器的理解

Spring容器主要是对loC设计模式的实现,主要是使用容器来统一管理Bean对象,及管理对象之间的依赖关系。
创建容器的API主要是BeanFactory和ApplicationContext两种:

  1. BeanFactory是最底层的容器接口,只提供了最基础的容器功能:Bean的实例化和依赖注入,并且使用懒加载的方式,这意味着beans只有在我们通过getBean()方法直接调用它们时才进行实例化。
  2. ApplicationContext(应用上下文)是BeanFactory的子接口,与BeanFactory懒加载的方式不同,它是预加载,所以,每一个bean 都在ApplicationContext启动之后实例化。
  3. 除了基础功能,还添加了很多增强:
    整合了Bean的生命周期管理

    1. i18n国际化功能(MessageSource)
    2. 载入多个(有继承关系)上下文,使得每一个上下文都专注于一个特定的层次,比如应用的web层
    3. 事件发布响应机制(ApplicationEventPublisher)
    4. AOP

3. loC/DI的理解

概念
loC(Inversion of Control)即控制反转,是面向对象编程中的一种设计原则。主要是通过第三方loC容器,对Bean对象进行统一管理,及组织对象之间的依赖关系。获得依赖对象的过程,由原本程序自己控制,变为了loC容器来主动注入,控制权发生了反转,所以叫做loC,控制反转。

loC又叫做DI︰由于控制反转概念比较含糊(可能只是理解为容器控制对象这一个层面,很难让人想到谁来维护对象关系),相对loC而言,依赖注入实际上给出了实现loC的方法:注入。所谓依赖注入,就是由loC容器在运行期间,动态地将某种依赖关系注入到对象之中。

依赖注入(Dl)和控制反转(loC)是从不同的角度的描述的同一件事情,就是指通过引入loC容器,利用依赖关系注入的方式,实现对象之间的解耦。

实现方式
Dl是loC的实现方式之一。而DI的实现方式主要有两种:构造方法注入和属性Setter注入。

实现原理
主要依赖反射及ASM字节码框架实现(字节码框架操作字节码更为高效,功能更强大)。

4. Spring中的单例bean的线程安全问题

大部分时候我们并没有在系统中使用多线程,所以很少有人会关注这个问题。单例bean存在线程问题,主要是因为当多个线程操作同一个对象的时候,对这个对象的非静态成员变量的写操作会存在线程安全问题。
有两种常见的解决方案:

  1. 在bean对象中尽量避免定义可变的成员变量(不太现实)。
  2. 在类中定义一个ThreadLocal成员变量,将需要的可变成员变量保存在ThreadLocal中(推荐的一种方式)。

5.Spring中的bean的作用域有哪些?

  1. singleton:唯一bean实例,Spring中的bean默认都是单例的。
  2. prototype:每次请求都会创建一个新的bean实例。
  3. request:每一次HTTP请求都会产生一个新的bean,该bean仅在当前HTTP request内有效。
  4. session:每一次HTTP请求都会产生一个新的bean,该bean仅在当前HTTP session内有效。
  5. application:在一个应用的Servlet上下文生命周期中,产生一个新的bean
  6. websocket:在一个WebSocket生命周期中,产生一个新的Bean

6. FactoryBean和BeanFactory

BeanFactory是Spring容器的顶级接口,所有Bean对象都是通过BeanFactory也就是Bean容器来进行管理

FactoryBean是实例化一个Bean对象的工厂类,实现了FactoryBean接口的Bean,根据该Bean的ID从BeanFactory中获取的实际上是FactoryBean中 get0bject()方法返回的对象,而不是FactoryBean本身,如果要获取FactoryBean对象,请在id前面加一个&符号来获取。

7. Bean的生命周期

  1. 实例化Bean:通过反射调用构造方法实例化对象。
  2. 依赖注入:装配Bean的属性
  3. 实现了Aware接口的Bean,执行接口方法︰如顺序执行BeanNameAware、BeanFactoryAware、ApplicationContextAware的接口方法。
  4. Bean对象初始化前,循环调用实现了BeanPostProcessor接口的预初始化方法(postProcessBeforelnitialization)
  5. 执行Bean对象初始化方法
  6. Bean对象初始化后,循环调用实现了BeanPostProcessor接口的后初始化方法(postProcessAfterlnitialization)
  7. 容器关闭时,执行Bean对象的销毁方法

8. Spring三级缓存的理解

这个问题或者换个问法:Spring是如何解决循环依赖的?答案即是Spring的三级缓存
什么是循环依赖

简单说,就是A对象依赖B对象,B对象又依赖A对象,类似的代码如下:

@Component
public class A{@Autowiredprivate B b;
}
@Component
public class B{@Autowiredprivate A a;
}

其他还有很多种方式,如A依赖B,B依赖C,C依赖A,或是A依赖A自己,只要产生了依赖关系的闭环,即造成了循环依赖。
那么,循环依赖会引发什么问题呢?理解这个问题先得理解Bean的生命周期,以下先回顾下
Bean的生命周期回顾

  1. 启动容器:加载Bean
  2. 实例化Bean对象
  3. 依赖注入:装配Bean的属性
  4. 初始化Bean:执行aware接口方法、预初始化方法、初始化方法、后初始化方法
  5. 关闭容器:销毁Bean

在以上第四个步骤执行完毕,才算一个初始化完成的Bean,也即Spring容器中完整的Bean对象。

循环依赖的问题
Spring容器保存Bean的方式,是采取缓存的方式:使用Map<String,0bject>的结构,key为Bean的名称, value为Bean对象。需要使用时直接从缓存获取。
假如A、B互相依赖((循环依赖)∶

  1. 容器中没有A对象,实例化A对象
  2. 装配A中的B对象,发现B在容器中没有,需要先实例化B
  3. 实例化B对象
  4. 装配B中的A对象,发现A在容器中没有,需要先实例化A
  5. 重复第一个步骤

这就套娃了,你猜是先Stack0verflow还是OutOfMemory?
Spring怕你不好猜,就先抛出了BeanCurrentlyInCreationException

[Ps]

  • Bean会依赖某些注入的Bean来完成初始化工作
  • 由于Spring支持构造方法注入,属性/Setter注入的方式,所以不能简单的先把所有对象全部实例化,放到缓存中,再全部执行初始化。原因很简单,此时所有对象的引用都可以获取到,但属性都是null,执行初始化甚至构造方法都可能出现空指针异常。

那么我们说Spring能解决循环依赖,也不是所有的情况都可以解决,只有以下情况才支持。

Spring支持的循环依赖
在Spring容器中注册循环依赖的Bean,必须是单例模式,且依赖注入的方式为属性注入。原型模式及构造方法注入的方式,不支持循环依赖。以下为说明︰

  • 原型模式(prototype)的Bean:原因很好理解,创建新的A时,发现要注入原型字段B,又创建新的B发现要注入原型字段A…
    还是典型的套娃行为…
  • 基于构造器的循环依赖,就更不用说了,官方文档都摊牌了,你想让构造器注入支持循环依赖,是不存在的,不如把代码改了。

那么默认单例的属性注入场景,Spring是如何支持循环依赖的?

Spring解决循环依赖
Spring是使用三级缓存的机制来解决循环依赖问题,以下为三级缓存的定义︰


为什么要使用三级缓存
依照以上三级缓存的流程,其实使用二级缓存也能满足循环依赖的注入∶

  • 普通的loC容器使用一级缓存即可,但无法解决循环依赖问题。

  • 解决循环依赖问题:使用二级缓存即可。一级缓存保存完整Bean,二级缓存保存提前曝光的不完整的Bean。

  • 需要AOP代理Bean时,有两种实现思路:
    (1)再加一级缓存
    (2)只使用二级缓存,其中二级缓存保存Bean的代理对象,代理对象中引用不完整的原始对象即可。

  • Spring使用三级缓存保存ObjectFactory即Bean工厂,在代码的层次设计及扩展性上都会更好
    ps:ObjectFactory内部可以根据SmartInstantiationAwareBeanPostProcessor这样的后置处理器获取提前曝光的对象。

9. AOP的理解

AOP (Aspect-Oriented Programming)︰面向切面编程。对多个业务代码横切来实现统一的业务管理,而不用侵入业务代码本身。这样面向切面的编程思想就是AOP。
使用场景:日志记录,事务管理,性能统计,安全控制,异常处理等
优点∶代码解耦,统一业务功能对具体业务无侵入性,这样可扩展性更好,灵活性更高SpringAOP是采取动态代理的方式,具体是基于JDK和CGLIB两种:

  • JDK动态代理:需要被代理类实现接口,使用InvocationHandlerProxy动态的生成代理类
  • CGLIB动态代理:需要被代理类能被继承,不能被final修饰。使用MethodInterceptor来对方法拦截。CGLIB底层是基于ASM字节码框架,在运行时动态生成代理类

SpringAOP如何使用︰@Aspect定义切面,并注册到容器中,使用@Pointcut定义好切点方法后对目标方法进行拦截:

  • 前置通知
    使用@Before:通知方法会在目标方法调用之前执行。

  • 后置通知
    使用@After:通知方法会在目标方法返回或者抛出异常后调用。

  • 返回之后通知

使用@AfterReturning:通知方法会在目标方法返回后调用。

  • 抛异常后通知
    使用@AfterThrowing:通知方法会在目标方法抛出异常后调用。

  • 环绕通知
    使用@Around︰通知包裹了被通知的方法,在被通知的方法通知之前和调用之后执行自定义的行为。

10. Spring事务中的隔离级别有哪几种?

在TransactionDefinition接口中定义了五个表示隔离级别的常量:

  • ISOLATION_DEFAULT:使用后端数据库默认的隔离级别,Mysql默认采用的REPEATABLE_READ隔离级别;Oracle默认采用的READ_COMMITTED隔离级别。
  • ISOLATION_READ_UNCOMMITTED:最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读。
  • ISOLATION_READ_COMMITTED:允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生
  • ISOLATION_REPEATABLE_READ:对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。
  • ISOLATION_SERIALIZABLE︰最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。

11. Spring事务中有哪几种事务传播行为?

在TransactionDefinition接口中定义了七个表示事务传播行为的常量。

支持当前事务的情况

  • PROPAGATION_REQUIRED:如果当前存在事务,则加入该事务﹔如果当前没有事务,则创建一个新的事务。
  • PROPAGATION_SUPPORTS: 如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
  • PROPAGATION_MANDATORY:
    如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。(mandatory:强制性)。

不支持当前事务的情况

  • PROPAGATION_REQUIRES_NEW:创建一个新的事务,如果当前存在事务,则把当前事务挂起。
  • PROPAGATION_NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则把当前事务挂起。
  • PROPAGATION_NEVER:以非事务方式运行,如果当前存在事务,则抛出异常。

其他情况:

  • PROPAGATION_NESTED:如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行﹔如果当前没有事务,则该取值等价于PROPAGATION_REQUIRED。

12. SpringMVC的流程

13. Mybatis中,#{}和${}的区别

#{变量名} 是预处理替换的方式,本质是jdbc中占位符的替换。如传入字符串,会替换为带单引号的值。可以安全性更好,
$ {变量名} 是字符串的替换,只是对sql字符串进行拼接。如传入字符串,会直接替换为字符串的值,不加单引号。
#{}的方式可以很大程度的防止 sql注入,相对来说更安全。而${}的方式不能。

14. Mybatis中如何一对一、一对多关联

15. SpringBoot自动配置原理


具体详情参考:https://juejin.cn/post/7046554366068654094

JavaEE常见面试问题相关推荐

  1. js 计算任意凸多边形内最大矩形_题库 | 计算机视觉常见面试题型介绍及解答 第 7 期...

    - 计算机视觉 -为什么说 Dropout 可以解决过拟合?(1)取平均的作用: 先回到标准的模型即没有 dropout,我们用相同的训练数据去训练 5 个不同的神经网络,一般会得到 5 个不同的结果 ...

  2. Hive常见面试问题(持续更新)

    Hive常见面试问题 目录 Hive 内部表和外部表的区别,以及各自使用于哪种环境?Hive和传统数据库的区别? HiveRc 文件? Hive 分区? Hive 分区过多有何坏处以及分区时的注意事项 ...

  3. 面经——C/C++常见面试知识点总结附面试真题

    参考:C/C++ 面试题 作者:zhaouc 发布时间: 2015-02-15 15:51:00 网址:https://blog.csdn.net/zhaouc/article/details/438 ...

  4. java面试常见面试问题_Java面试准备:15个Java面试问题

    java面试常见面试问题 并非所有的访谈都将重点放在算法和数据结构上-通常,访谈通常只侧重于您声称是专家的语言或技术.在此类访谈中,通常没有任何"陷阱"问题,而是它们要求您利用内存 ...

  5. spring常见面试问题_Spring面试问题

    spring常见面试问题 另外,请查看我们最新的文章69Spring面试问题与解答–最终清单 . 1)什么是春天? 回答: Spring是控件和面向方面的容器框架的轻量级反转. 2)解释春天? 回答: ...

  6. 【C++基础】常见面试问题(二)

    1. 指针和引用的区别 指针保存的是所指对象的地址,引用是所指对象的别名,指针需要通过解引用间接访问,而引用是直接访问 指针可以改变地址,从而改变所指的对象,而引用必须从一而终: 引用在定义的时候必须 ...

  7. Java常见面试知识点:继承、接口、多态、代码块

    问题:Java常见面试知识点:继承.接口.多态.代码块 答案: 1.继承 继承中构造方法的访问特点 子类中所有的构造方法默认都会访问父类中无参的构造方法 为什么? • 子类在初始化的时候,有可能会使用 ...

  8. 视频教程:Java常见面试题目深度解析!

    视频教程:Java常见面试题目深度解析! Java作为目前比较火的计算机语言之一,连续几年蝉联最受程序员欢迎的计算机语言榜首,因此每年新入职Java程序员也数不胜数.很多java程序员在学成之后,会面 ...

  9. Linux底层IIC 总线的理解、调用函数以及常见面试问题

    对 IIC 总线的理解.调用函数以及常见面试问题 一.IIC 总线概述: IIC 即Inter-Integrated Circuit(集成电路总线) I2C总线是PHLIPS公司推出的一种串行总线, ...

最新文章

  1. linux与python客户端,《使用python进行unix和linux管理》§5网络 §5.1 网络客户端
  2. 数据湖 多维数据集_按汇总分组/多维数据集
  3. vim ctags java源码_如何使用vim的插件Ctags查看Linux源码
  4. 数据结构(十)二叉排序树
  5. jenkins手把手教你从入门到放弃02-jenkins在Windows系统安装与配置
  6. HTTP协议请求类型响应简介
  7. 动态规划解决分割问题
  8. SmartDrv的前世今生——PrimoCache_2.2.0汉化
  9. .NET 云原生架构师训练营(模块一 架构师与云原生)--学习笔记
  10. Python课程入门之Pycharm创建PY文件的使用步骤与模板创建
  11. PE头解析(仅限于PE头)
  12. 帝国国王科技大学上机题解(二)
  13. php银行卡号校验算法(16、19位)
  14. 高中计算机基础知识课件,5.1.2 信息资源管理的方式方法
  15. 【记录】oracle异常ORA-00205:????
  16. 高中计算机专业班主任工作总结,大学班主任工作总结5篇
  17. 转JavaScript的语法解析与抽象语法树
  18. 一寸照片的尺寸是多少?快速制作教程介绍
  19. Vtalk局域网聊天室 基于Python
  20. 专访杨强:从 0 到 1,迁移学习如何登上今日高峰?

热门文章

  1. 哪些东西买了之后,会让人因生活质量和幸福感提升而感觉相见恨晚?
  2. Startup is Ready,Geek to Startup!
  3. C语言中变量的作用域和生存期的区别
  4. Briefings in bioinformatics2022 | 基于神经网络的分子性质预测通用优化策略
  5. 极路由php插件,极路由SDK
  6. oracle 9i alert log,Oracle 9i,10g,11g各自alert日志的位置
  7. Android JNI --函数调用大全
  8. create Golang project with interface #1
  9. 如何修复无法打开的Excel文件,三大原因三大方法为你解决
  10. 全网稀缺的生产级大型DDD项目实战!来了!