面试大全 持续更新

文章目录


###

八大基本类型

baty、short、int、long,float.double boolean char
1 2 4 8 4 8 1 2
在这里插入图片描述

成员变量和局部变量的区别

1.初始化不同
成员变量有默认值
局部变量没有默认值需要初始化
2.代码位置不同
成员变量在类里方法外
局部变量在方法里
3.生命周期不同
成员变量随着对象的存在而存在
局部变量随着方法的结束而结束
4.内存不同
成员变量在堆内存中
局部变量在栈内存中

怎么在内层循环结束外层循环

可以在外层循环添加标记
在这里插入图片描述

创建对象的四中方式

1.new
2.序列化
3.反射
4.Object.clone

开发过程中用到的集合

主要使用过ArrayList集合、HashMap
使用原因
1.使用ArrayList存储顺序表的数据
2.使用HashMap存储键值对的数据

ArrayList底层存取值怎么实现的,是不是线程安全的,扩容是怎么实现的

扩容:
1.5倍扩容,CopyOf()。
如果扩容一半不够,就将目标size作为扩容后的容量。
采用的是浅拷贝:只拷贝引用。

存值:
首先判断容量够不够,然后通过size自增作为下标,通过数组的方式放进去。如果不够,会层层调用grow方法进行扩容。如果调用的是addall方法,则会把添加的集合转为数组并拿到length,进行容量判断,如果不够,则扩容。并且对比扩容的size和新的size比较,以大的为准。
如果指定下标add,会判断下标是否合法,然后判断容量,并通过arraycopy方法,将后半段元素后移1。
取值:
如果输入下标取值,则会检查下标是否合法,如果OK,则通过数组的方式取值。并通过arrycopy进行迁移元素,并把最后一个空位设为null。
如果传入一个value,则会判断非空后进行遍历,并取出。

  1. ArrayList是一个动态数组,实现了List, RandomAccess, Cloneable, java.io.Serializable,并允许包括null在内的所有元素。

1.1,实现了RandomAccess接口标识着其支持随机快速访问,实际上,我们查看RandomAccess源码可以看到,其实里面什么都没有定义.因为ArrayList底层是数组,那么随机快速访问是理所当然的,访问速度O(1).

1.2,现了Cloneable接口,标识着可以它可以被复制.注意,ArrayList里面的clone()复制其实是浅复制。

  1. 底层使用数组实现,默认初始容量为10.当超出后,会自动扩容为原来的1.5倍,即自动扩容机制。

    数组的扩容是新建一个大容量(原始数组大小+扩充容量)的数组,然后将原始数组数据拷贝到新数组,然后将新数组作为扩容之后的数组。数组扩容的操作代价很高,我们应该尽量减少这种操作。

  2. 该集合是可变长度数组,数组扩容时,会将老数组中的元素重新拷贝一份到新的数组中,每次数组容量增长大约是其容量的1.5倍,如果扩容一半不够,就将目标size作为扩容后的容量.这种操作的代价很高。采用的是 Arrays.copyOf浅复制

  3. 采用了Fail-Fast机制,面对并发的修改时,迭代器很快就会完全失败,报异常concurrentModificationException(并发修改一次),而不是冒着在将来某个不确定时间发生任意不确定行为的风险。

  4. remove方法会让下标到数组末尾的元素向前移动一个单位,并把最后一位的值置空,方便GC

  5. 数组扩容代价是很高的,因此在实际使用时,我们应该尽量避免数组容量的扩张。当我们可预知要保存的元素的多少时,要在构造ArrayList实例时,就指定其容量,以避免数组扩容的发生。或者根据实际需求,通过调用ensureCapacity方法来手动增加ArrayList实例的容量。

  6. ArrayList不是线程安全的,只能用在单线程环境下,多线程环境下可以考虑用Collections.synchronizedList(List l)函数返回一个线程安全的ArrayList类,也可以使用concurrent并发包下的CopyOnWriteArrayList类。

8,add(E e)方法作用: 添加指定元素到末尾

如果要增加的数据量很大,应该使用ensureCapacity()方法,该方法的作用是预先设置Arraylist的大小,这样可以大大提高初始化速度.

9,如果是添加到数组的指定位置,那么可能会挪动大量的数组元素,并且可能会触发扩容机制;如果是添加到末尾的话,那么只可能触发扩容机制.

10,如果是删除数组指定位置的元素,那么可能会挪动大量的数组元素;如果是删除末尾元素的话,那么代价是最小的. ArrayList里面的删除元素,其实是将该元素置为null.

11,Collection是最顶层的集合,Collection.toArray()在Collection各个子类的源码中使用频繁

12,Arrays.copyOf(U[] original, int newLength, Class<? extends T[]> newType),就是根据class的类型来决定是new还是反射去构造一个泛型数组,同时利用native函数,批量赋值元素至新数组中.

13, System.arraycopy()复制数组,也是一个高频使用的函数.

1.java语言最基本的单位就是类,相当于类型
2.类是一类十五抽取共同属性与功能形成的
3.可以理解为模板或者设计图纸。
注意:类在现实世界并不存在,它只是一种对象的数据类型

对象
访问控制符

在这里插入图片描述

多态的优点

1.忽略某个对象的类型,就可以调用它的某些方法
2.提高了程序的可扩展性,和可维护性
3.统一了调用的标准又可以叫做动态绑定实现了类型之间的解耦

HashMap的底层原理,ConcurrentHashMap的实现原理,存取值的时候是怎么实现的。

1、map.put(k,v)实现原理
(1)首先将k,v封装到Node对象当中(节点)。
(2)然后它的底层会调用K的hashCode()方法得出hash值。
(3)通过哈希表函数/哈希算法,将hash值转换成数组的下标,下标位置上如果没有任何元素,就把Node添加到这个位置上。如果说下标对应的位置上有链表。此时,就会拿着k和链表上每个节点的k进行equal。如果所有的equals方法返回都是false,那么这个新的节点将被添加到链表的末尾。如其中有一个equals返回了true,那么这个节点的value将会被覆盖。

2、map.get(k)实现原理
(1)先调用k的hashCode()方法得出哈希值,并通过哈希算法转换成数组的下标。
(2)通过上一步哈希算法转换成数组的下标之后,在通过数组下标快速定位到某个位置上。如果这个位置上什么都没有,则返回null。如果这个位置上有单向链表,那么它就会拿着K和单向链表上的每一个节点的K进行equals,如果所有equals方法都返回false,则get方法返回null。如果其中一个节点的K和参数K进行equals返回true,那么此时该节点的value就是我们要找的value了,get方法最终返回这个要找的value。

ConcurrentHashMap
sync——cas

重载和重写的区别

重载:
发生在同一个类中
方法名相同但是参数列表不同

异常

在这里插入图片描述

Java创建对象的方式

使用构造方法:new,反射
不使用构造方法:反序列化 (深拷贝),clone(浅拷贝–深拷贝序列化,深拷贝变量也clone)

Object的默认方法

1个本地注册方法
1个getClass()
4个,hash,toString,Equals,clone
2个notify
3个wait
1个finalize()

包装类的Cache

在这里插入图片描述

多态中静态方法的执行

静态方法不同于静态代码块,是由开发者调用。
只能通过类名点处理。子类可以继承父类的静态方法。
如果同名,不算重写,子类只能调用到子类的方法。

反转字符串程序

0.reverse
1.倒序拼接
2.切割递归
3.二分递归

Java异常处理机制

在这里插入图片描述

常用的IO类
代码规范的理解

命名规范,
注释规范,
代码结构化,模块化
开发文档的习惯

项目中用到final的地方

静态常量
参数:基本类型为常量,引用类型不能被重新赋值

深拷贝和浅拷贝的区别

从字面上理解更好。
浅拷贝—拷贝的级别浅。

深拷贝—拷贝级别更深。

具体呢?

浅拷贝—能复制变量,如果对象内还有对象,则只能复制对象的地址

深拷贝—能复制变量,也能复制当前对象的 内部对象

对集合有二次加工的处理吗
线程池的创建

自定义创建:

ThreadPoolExecutor
ScheduledThreadPoolExecutor
ForkJoinPool
【ForkJoinPool线程池思想:将大任务分解成若干个小任务,当小任务均执行结束后,将任务做一个整合
使用接口:
RecursiveAction:没有返回值,只是执行任务
RecursiveTask:有返回值,小任务结束后,返回结果。大任务可将小任务返回结果进行整合】
Executors工具类创建:

Fixed:定长的线程池
Executors:定时任务
Single:单线程的
Cache:缓存

多线程的使用场景

定时类:
定期采集信息,定期备份日志

异步类:
记录日志

耗时类:
耗时类任务

双亲委派

JVM类加载器从下往上是自定义类加载器,系统类加载器,扩展类加载器,起始类加载器。

起始类加载器:由c语言编写,加载Java最核心的类jre/lib下的
扩展类加载器:由java编写,加载Java扩展类的下的类,jre/lib/ext
系统类加载器:加载自己定义的类即用户路径上的类。
自定义类加载器:可以用于源码加密,可以用于类的隔离。

双亲委派机制:
当一个类需要加载的时候,首先需要找到这个类加载器的父亲加载器,一直往上找,直到起始类加载器,如果起始类加载器不能加载,那就向下委派直到能加载为止。
利用此机制可以避免类的重复加载。
沙箱保护机制:利用双亲委派机制来保护java的核心类。
在这里插入图片描述
类加载器(Classloader):
类加载阶段中的“通过一个类的全限定名来获取此类的二进制字节流”这个动作放到 Java 虚拟机外部去实现。
作用:加载class文件进入JVM,审查类由谁加载(双亲委派机制),将class重新解析成JVM要求的对象格式
一阶段:加载阶段——字节码加载到内存
1:通过全限定名来获取类的字节流
2:将字节流转为方法区的运行时数据
3:在堆中生成一个Class对象,作为访问入口
二阶段:验证阶段——确保Class文件的字节流中包含的信息符合当前虚拟机的要求
1:格式验证:Class文件格式规范
2:元数据验证:是否符合JAVA语法
3:字节码验证:数据流和控制流分析,确保不危害虚拟机
4:符号引用验证:符合引用转直接引用
三阶段:
1:类资源的内存分配
2:解析引用
3:初始化,执行静态代码

一言概之,双亲委派模型,其实就是一种类加载器的层次关系。
BootStrap——完全由JVM控制,加载JVM需要的类
Extension——服务目标在ext目录下的,依赖等
Application

破坏双亲委派三大情况:
jdk1.2之前
缺陷导致,——通过线程上下文类加载器解决,例如SPI的JDBC
热部署

加载Class的两种方式:
隐式:JVM在解析引用的时候发现内存没有,会申请加载。
显式:
this.getClass().getClassLoader().loadClass()
Class.forName()

流程:
收到加载类的请求。
从底向上检查类是否已加载。
如果没有加载,自顶向下尝试加载该类。

优点:
1,防止底层类被篡改。
2,避免重复加载类信息。

JVM结构,运行顺序

JVM的基本组成:

JVM指令集
类加载器
执行引擎:jvm的核心,解析JVM字节码指令,每个java线程就是一个执行引擎的实例。
运行时数据区:将内存分为若干个区
本地方法区:调用C方法返回的结果
在这里插入图片描述

线程私有的:

程序计数器:线程私有的,行号指示器。
虚拟机栈:栈帧,执行完方法清楚栈帧。调用其他方法推到栈顶(活动栈帧)。
本地方法栈
公共的:

堆():堆区放对象,堆栈放引用。
方法区(永久区):常量池,域,方法数据,方法体,构造函数,类中的专有方法,实例初始化,接口初始化。【运行时常量池】

类加载知识点

答:1.类加载的含义:
类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个 java.lang.Class对象,用来封装类在方法区内的数据结构。
2.类加载的过程
它的整个生命周期包括:加载、验证、准备、解析、初始化、使用和卸载七个阶段。

HashMap的遍历方式

1:转EntrySet用迭代器
2:转KeySet用迭代器
3:foreach
4:map.forEach()——lamdba
5:map.entrySet().Stream().forEach
6:map.entrySet().parallelStream().forEach

HashSet怎么保证元素唯一

答:HashSet的底层是HashMap的key,所以Hashset可以通过hashcode转换成key来保证元素唯一性

lock锁

答:主要用来解决互斥问题。

void lock()—— 获取锁对象,优先考虑是锁的获取,而非中断。

void lockInterruptibly()—— 获取锁,但优先响应中断而非锁的获取。

boolean tryLock() ——试图获取锁,如果返回true,则获取成功,直接使用。不需要继续lock()

boolean tryLock(long timeout, TimeUnit timeUnit) ——试图获取锁,并设置等待时长。

void unlock()——释放锁对象
lock锁的详细信息

锁升级
sync的实现原理

答:synchronized可以保证方法或者代码块在运行时,同一时刻只有一个方法可以进入到临界区,同时它还可以保证共享变量的内存可见性。
Java中每一个对象都可以作为锁,这是synchronized实现同步的基础:
• 普通同步方法,锁是当前实例对象
• 静态同步方法,锁是当前类的class对象
• 同步方法块,锁是括号里面的对象

sync和volatile

答:1,volatile无法锁定当前变量,sync可以锁定当前变量
2,volatile作用于变量上,sync作用于方法,类,变量
3,volatile只有变量的可见性,sync不仅有变量的可见性,还有变量的原子性
4,volatile不会线程阻塞,sync会导致线程阻塞
5,volatile标记的变量不会被编译器优化,sync标记的变量会被编译器优化
6,在代码中,volatile加在属性上,sync的可以用于任何地方

怎么理解资源独立分配

答:ThreadLocal:
每个Thread内部都有一个Map(ThreadLocalMap),是Thread的一个属性。
key是当前ThreadLocal对象——弱引用,value却是强引用。

内存泄漏问题:
造成内存泄露——解决:手动remove,静态私有。

线程复用问题:前后remove

使用场景:
1:存储用户Session
2:数据库连接,处理数据库事务
3:数据跨层传递
4:spring解决线程安全问题

有状态:有属性——比如pojo
无状态:无属性——controller

线程的状态的转换关系,主动阻塞和被动阻塞

答:等待阻塞,同步阻塞,其他阻塞。

join():并行变串行
interrupt():更改标识,抛异常,中断阻塞
在这里插入图片描述

BIN和NIO的区别,怎么实现多路复用

答:BIO是同步阻塞,就是我们平常使用的传统 IO,它的特点是模式简单使用方便,并发处理能力低。
NIO是同步非阻塞,

多路复用的含义:
可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。
答:1)Non-blocking IO(非阻塞IO)

IO流是阻塞的,NIO流是不阻塞的。

Java NIO使我们可以进行非阻塞IO操作。比如说,单线程中从通道读取数据到buffer,同时可以继续做别的事情,当数据读取到buffer中后,线程再继续处理数据。写数据也是一样的。另外,非阻塞写也是如此。一个线程请求写入一些数据到某通道,但不需要等待它完全写入,这个线程同时可以去做别的事情。
2)Buffer(缓冲区)

IO 面向流(Stream oriented),而 NIO 面向缓冲区(Buffer oriented)。

Buffer是一个对象,它包含一些要写入或者要读出的数据。在NIO类库中加入Buffer对象,体现了新库与原I/O的一个重要区别。在面向流的I/O中·可以将数据直接写入或者将数据直接读到 Stream 对象中。虽然 Stream 中也有 Buffer 开头的扩展类,但只是流的包装类,还是从流读到缓冲区,而 NIO 却是直接读到 Buffer 中进行操作。

3)Channel (通道)

NIO 通过Channel(通道) 进行读写。

通道是双向的,可读也可写,而流的读写是单向的。无论读写,通道只能和Buffer交互。因为 Buffer,通道可以异步地读写。

4)Selectors(选择器)

NIO有选择器,而IO没有。

选择器用于使用单个线程处理多个通道。因此,它需要较少的线程来处理这些通道。线程之间的切换对于操作系统来说是昂贵的。 因此,为了提高系统效率选择器是有用的。

fork()函数
答:用于创建一个进程,所创建的进程复制父进程的代码段/数据段/BSS段/堆/栈等所有用户空间信息;在内核中操作系统重新为其申请了一个PCB,并使用父进程的PCB进行初始化;
子进程执行的位置是fork()函数执行后的代码处,猜想是复制了父进程的PC指针给子进程。

http的缺点

答:1.通信使用明文不加密,内容可能被窃听
2.不验证通信身份,有可能遭遇伪装
3.无法验证报文的完整性,有可能被篡改

HTTPS怎么实现的网络安全性

答: 用工具(OpenSSL)来生成一个私钥,然后用刚生成的私钥,在提供你自己的域名、公司名称、部门、省份、城市等信息来生成一个待签名证书(即CSR文件,也叫公钥),然后我们拿着这个代签名证书,去CA机构申请证书,CA会根据你提交的信息进行审核,审核通过(就相当于让别人签个名,防伪造)后会下发证书给你(CRT文件,里面包含了公钥,CA的签名,过期时间,申请人提交的信息),当你拿到签名好的证书以后,把它和刚开始的私钥一起部署在服务器里面,这样网站就是HTTPS的了。

设计模式是用来干嘛的,为什么看设计模式

答:设计模式是用来是解决软件开发某些特定问题而提出的一些解决方案也可以理解成解决问题的一些思路。

Map自定义一个实例作为Map的Key,需要满足什么条件。自定义类作为Key,有什么要求。
List用什么方式遍历

1:collection迭代器
2:list迭代器
3:foreach或for
4:点foreach+lamdba
5:转成流,点foreach
6:转成并发流,点foreach

Remove删除元素做过什么其他操作

1:检查下标是否合法。
2:检查modCount。
3:根据下标+偏移量删除。
4:size-1
5:返回

进程和线程在地址空间上有什么区别

答:进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。

进程是分配资源的基本单位,怎么理解

答:一个进程在其执行的过程中可以产生多个线程。与进程不同的是同类的多个线程共享进程的堆和方法区资源,但每个线程有自己的程序计数器、虚拟机栈和本地方法栈

线程与进程的关系

通常在一个进程中可以包含若干个线程,它们可以利用进程所拥有的资源。但是,一个线程只属于一个进程。进程间相互独立,同一进程的各线程间共享。某进程内的线程在其它进程不可见。而且需要注意的是,线程不是一个可执行的实体。

线程和资源有什么关系

线程问题

gitee代码冲突怎么解决

1:拉取代码,发现冲突,解决再上传。
2:通过WebIDE在线手动解决

Gitee常用命令有哪些

1.add
2.commit
3.push
4.clone
5.stash
6.stash pop

工作中用到哪些数据库
mysql 中的函数

lower(username)
1
upper(username)
1
length(username)
1
substr(username,1,3) --含头含尾
1
caoncat(username,“123”) --拼接123
1
replace(username,‘1’,‘100’) --1换100
1
ifnull(sex,0) --nul换10
1
round(money,1) ceil(money) floor(money)
1
select now() – 年与日 时分秒
select curdate() --年与日
select curtime() --时分秒
select now(),hour(now()),minute(now()),second(now()) from emp ;
select now(),year(now()),month(now()),day(now()) from emp ;

事务是在哪里应用的

转账 打款

数据库中sql优化

答:
1.索引不宜太多,一般在五个以内
2.用vachar代替char
3.查询时尽量不要使用select *,而是具体的字段
4.避免在where子句上使用!=或<>操作符
5.尽量用数值代替字符串类型
6.避免在where语句上使用表达式操作

索引的数据结构

hash btree

事务的隔离级别

1.读已提交
2.读未提交
3.可重复读
4.串行化

事务的传播方式

传播行为分为两种:分为支持事物的传播和不支持事物的传播

1、PROPAGATION_REQUIRED:(支持事物)如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务,该设置是最常用的设置。

2、PROPAGATION_SUPPORTS:(支持事物)支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就以非事务执行。‘

3、PROPAGATION_MANDATORY:(支持事物)支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就抛出异常。

4、PROPAGATION_REQUIRES_NEW:(支持事物)创建新事务,无论当前存不存在事务,都创建新事务。

5、PROPAGATION_NOT_SUPPORTED:(不支持事物)以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。

6、PROPAGATION_NEVER:(不支持事物)以非事务方式执行,如果当前存在事务,则抛出异常。

7、PROPAGATION_NESTED:(不支持事物)如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。

分页是怎么做的

mybatis
mybatis-plus page对象

#和$的区别,分别什么情况下使用

答:
#{}:编译预处理,在mysql执行过程中,可以用?代替,#{} 适合 在表结构 确定的情况下使用 。可以有效防止sql注入
: 拼 接 字 符 串 , {}:拼接字符串,:拼接字符串,{} 适合 在表结构不确定的情况下使用。

Mysql数据库悲观锁和乐观锁

悲观锁 乐观锁

SQL:删除重复的记录

select [标志字段id],count() into temp1 from [表名]group by [标志字段id]having count()>1

怎么创建索引
#create index 索引名字 on 表名(字段名); #创建索引
 
create index loc_index on dept(loc); #创建索引
#创建唯一索引--索引列的值必须唯一
CREATE UNIQUE INDEX 索引名 ON 表名(字段名)
CREATE UNIQUE INDEX bindex ON dept(loc)
#如果您希望索引不止一个列,您可以在括号中列出这些列的名称,用逗号隔开:
CREATE INDEX 索引名 ON 表名 (字段1, 字段2)
CREATE INDEX PIndex ON Persons (LastName, FirstName)
alter table dept drop index fuhe_index
Get和Post的区别

答:
1.Get的请求参数都显示在地址栏中,不安全;Post的请求参数对于用户是不可见的,安全
2.Get的传输的大小只有2k-4k,Post的传输大小不做限制
3.Get要求form表单提交时采用ACSII字符;Post则采用ISO-10646字符集
4.从执行效率来看,Get的执行效率高于Post的执行效率

Get传参的长度限制
HTTP状态码

添加链接描述

POST上传有限制,上传文件过大怎么办。
union和union all的区别

答:
Union:对两个结果集进行并集操作,不包括重复行,同时进行默认规则的排序;

Union All:对两个结果集进行并集操作,包括重复行,不进行排序;

mysql 中float和double的区别
联合索引中,最左的字段放在右边会命中吗?为什么?

会 因为mysql会优化两个字段的顺序

mysql中的几个器

在这里插入图片描述
详细信息

过滤器拦截器

1.过滤器:
依赖于servlet容器。在实现上基于函数回调,可以对几乎所有请求进行过滤,但是缺点是一个过滤器实例只能在容器初始化时调用一次。使用过滤器的目的是用来做一些过滤操作,获取我们想要获取的数据,比如:在过滤器中修改字符编码;在过滤器中修改HttpServletRequest的一些参数,包括:过滤低俗文字、危险字符等
2.拦截器:
依赖于web框架,在SpringMVC中就是依赖于SpringMVC框架。在实现上基于Java的反射机制,属于面向切面编程(AOP)的一种运用。由于拦截器是基于web框架的调用,因此可以使用Spring的依赖注入(DI)进行一些业务操作,同时一个拦截器实例在一个controller生命周期之内可以多次调用。但是缺点是只能对controller请求进行拦截,对其他的一些比如直接访问静态资源的请求则没办法进行拦截处理
3.过滤器和拦截器的区别:
①拦截器是基于java的反射机制的,而过滤器是基于函数回调。
②拦截器不依赖与servlet容器,过滤器依赖与servlet容器。
③拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。
④拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。
⑤在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。
⑥拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑。

前端传参时,是怎么和对象映射的。

@RequestBady
当前端传递json数据时候 controller 参数是对象 那么需要在参数里面添加注解RequestBody 来解析成对应的对象
@RequestParam
接受前端传来的单参数
@PathVariable
Restful风格 接受路径上的参数
@RequestHeader
接受请求头里的参数
会有一系列的解析器
1)@RequestBody 注解的参数使用RequestResponseBodyMethodProcessor

2)@RequestParam 注解的参数使用 RequestParamMethodArgumentResolver

IOC和AOP
  1. IOC的意思是控制反转,是指创建对象的控制权的转移,以前创建对象的主动权和时机是由自己把控的,而现在这种权力转移到Spring容器中,并由容器根据配置文件去创建实例和管理各个实例之间的依赖关系,对象与对象之间松散耦合,也利于功能的复用。最直观的表达就是,IOC让对象的创建不用去new了,可以由spring根据我们提供的配置文件自动生产,我们需要对象的时候,直接从Spring容器中获取即可.
  2. Spring的配置文件中配置了类的字节码位置及信息, 容器生成的时候加载配置文件识别字节码信息, 通过反射创建类的对象.
    Spring的IOC有三种注入方式 :构造器注入, setter方法注入, 根据注解注入
  3. AOP,一般称为面向切面编程,作为面向对象的一种补充,用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取并封装为一个可复用的模块,这个模块被命名为“切面”(Aspect). SpringAOP使用的动态代理,所谓的动态代理就是说AOP框架不会去修改字节码,而是每次运行时在内存中临时为方法生成一个AOP对象,这个AOP对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法。
  4. Spring AOP 中的动态代理主要有两种方式,JDK 动态代理和 CGLIB 动态代理:
    (1)JDK 动态代理只提供接口代理,不支持类代理,核心 InvocationHandler 接口和 Proxy 类,InvocationHandler 通过 invoke()方法反射来调用目标类中的代码,动态地将横切逻辑和业务编织在一起,Proxy 利用 InvocationHandler 动态创建一个符合某一接口的实例, 生成目标类的代理对象。
    (2) 如果代理类没有实现 InvocationHandler 接口,那么 Spring AOP会选择使用 CGLIB 来动态代理目标类。CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成指定类的一个子类对象,并覆盖其中特定方法并添加增强代码,从而实现 AOP。CGLIB 是通过继承的方式做的动态代理,因此如果某个类被标记为 final,那么它是无法使用 CGLIB 做动态代理的。
AOP是怎么调用的,静态代理和动态代理的区别

静态代理:
AspectJ 的底层技术是 静态代理 ,即用一种 AspectJ 支持的特定语言编写切面,通过一个命令来编译,生成一个新的 代理类,该代理类增强了业务类,这是在编译时增强,相对于下面说的运行时增强,编译时增强的性能更好

AOP
Spring AOP使用的动态代理,动态代理就是说AOP框架不会去修改字节码,而是在内存中临时为方法生成一个AOP对象,这个AOP对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法。

Spring AOP中的动态代理主要有两种方式:JDK动态代理 和 CGLIB动态代理。
GDK
JDK动态代理通过反射来接收被代理的类,
并且要求被代理的类必须实现一个接口。
核心类
InvocationHandler 接口
Proxy.newProxyInstance()

CGLIB
如果目标类没有实现接口,那么Spring AOP会选择使用 CGLIB 来动态代理目标类。

CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成某个类的子类。
CGLIB是通过继承 的方式做 动态代理,因此如果某个类被标记为 final,那么它是无法使用CGLIB做动态代理的。
核心类
MethodInterceptor 接口
Enhancer 类

Mybatis的优缺点

一、什么是Mybatis?

Mybatis是一个半自动的ORM持久层框架,内部封装了JDBC。作为开发者只需要关注sql语句本身。Mybatis是通过xml或注解的方式将需要执行的各种statement配置起来。通过Java对象和statement中的sql动态参数映射生成最终执行的sql语句,最终由Mabtais框架执行sql并将结果映射为Java对象并返回。MyBatis 支持定制化 SQL、存储过程以及高级映射。MyBatis 是可以双向映射的,可以将数据集映射为Java对象,也可以将Java对象映射为数据库中的记录。

二、Mybait的优点:

(1)简单易学,容易上手(相比于Hibernate) 基于SQL编程;
(2)JDBC相比,减少了50%以上的代码量,消除了JDBC大量冗余的代码,不需要手动开关连接;
(3)很好的与各种数据库兼容(因为MyBatis使用JDBC来连接数据库,所以只要JDBC支持的数据库MyBatis都支持,而JDBC提供了可扩展性,所以只要这个数据库有针对Java的jar包就可以就可以与MyBatis兼容),开发人员不需要考虑数据库的差异性。
(4)提供了很多第三方插件(分页插件 / 逆向工程);
(5)能够与Spring很好的集成;
(6)MyBatis相当灵活,不会对应用程序或者数据库的现有设计强加任何影响,SQL写在XML里,从程序代码中彻底分离,解除sql与程序代码的耦合,便于统一管理和优化,并可重用。
(7)提供XML标签,支持编写动态SQL语句。
(8)提供映射标签,支持对象与数据库的ORM字段关系映射。
(9)提供对象关系映射标签,支持对象关系组建维护。
三、MyBatis框架的缺点:

(1)SQL语句的编写工作量较大,尤其是字段多、关联表多时,更是如此,对开发人员编写SQL语句的功底有一定要求。
(2)SQL语句依赖于数据库,导致数据库移植性差,不能随意更换数据库。

Mybatis的BIO接口支持重载吗
SpringMVC的请求原理
SoringMVC组件
SpringBoot读取配置文件的配置项,怎么读取。如果读取不到怎么办,除了@Value还有什么。
SpringBoot中的异常拦截怎么做的
SpringBoot依赖是怎么导入的
SpringBoot是怎么读取参数的
SpringBoot常用注解
SpringBoot的核心配置文件,什么格式,什么区别
SpringBoot读取配置文件中的类,接口
Spring中的路由,怎么凭借路径前后的无意义参数
Bean生命周期
Bean的作用域
读取XML的几种方式
如何解决循环依赖
Spring的食物
介绍一下SpringBoot
单例有线程安全问题吗?原型呢?
HandlerMapping是什么时候工作的,程序启动的时候还是第一次请求的时候
Spring中的local有没有用过
Nginx有什么作用,怎么应用的
有没有参与过项目部署,怎么实现的
异常处理
SoringBoot是怎么运行的
Mybatis常用标签
Mybatis分页实现
SpringMVC的注解
SpringBoot如何解决跨域问题
Spring容器的启动问题
BeanFactroy怎么理解
反向代理的过程
负载均衡怎么理解

流控模式有哪些?
项目中有没有用分布式架构
项目中有缓存吗,存在哪里的?
redis数据类型
redis中存储了哪些数据
redis常见命令
redis设置密码怎么登录
redis常用数据类型,有什么特点
redis的持久化机制

RDB
AOF

缓存崩坏三问,怎么解决
认证和权限是怎么实现的
MQ的用途

SpringCloud了解的多不多,尝试搭建微服务项目吗?
SpringCloud的组件
怎么实现分布式锁
Redis的分布式锁是怎么实现的
项目中涉及到高并发的问题了吗
Linux的权限
RPC什么原理,怎么调用远端服务像本地服务

其他

项目模块描述
项目使用了哪些技术
项目的日志
怎么用一个11L,7L的杯子,量出2L水
4L水,用1.5L的瓶子和2.5L的瓶子,怎么平均分
项目中遇到报错如何定位解决
理解老代码会遇见什么问题
更改代码影响别人的模块,怎么解决
项目里解决过什么有意义的东西
出现过哪些异常,什么原因造成的
测试时数据量小,发布后数据量大,怎么确保跑的起来
改老代码看不懂代码怎么解决
服务按领域拆分,按功能拆分,不同模块怎么办
改动影响了其他模块,导致出现问题,解决思路是怎么样的。
项目的表结构
介绍一下近期的项目,技术关键点,有挑战的地方。
项目中常用的数据结构,什么场景下使用
交互岗位沟通流程
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值