【zs整理】

文章目录

java

java面向对象

面向对象的程序设计方法具有三个基本特征:封装、继承、多态。

  1. 封装指的是将对象的实现细节隐藏起来,然后通过一些公用方法来暴露该对象的功能;
  2. 继承是面向对象实现软件复用的重要手段,当子类继承父类后,子类作为一种特殊的父类,将直接获得父类的属性和方法;
  3. 多态指的是同一个类型的对象在执行同一个方法时,可能表现出多种行为特征。

java和C#有啥区别

1.java是一种面向对象的语言。c语言是一种面向过程的语言。
2.java是一次编译,多处运行,而c语言在window系统上编译的程序在Linux上不能运行。因为Java有java虚拟机,java编译完成后,先生成字节码即.class文件,然后将生成的文件转移到不同平台时,java虚拟机可以把.class文件转换为当前机器平台可以识别的信息,这样就可以在不同平台上运行了。
3.java舍弃了c语言的指针。c语言的指针就是指向可以人为操作的物理地址,所以c语言就有自己去申请物理地址,之后还要手动释放,java垃圾回收机制就很好地解决了这点,我们不用关心申请的物理地址是否释放了,java虚拟机会帮助我们去清理用不到的物理地址,从而减少了出错的原因可能。
4. 主要用途不一样,Java语言主要针对互联网应用开发,c语言主要针对底层开发。

抽象类和接口的区别

相同点
(1)都不能被实例化 (2)接口的实现类或抽象类的子类都只有实现了接口或抽象类中的方法后才能实例化。

  1. 接口只有定义,不能有方法的实现,java 1.8中可以定义default方法体,而抽象类可以有定义与实现,方法可在抽象类中实现。
  2. 接口成员变量默认为public static final,必须赋初值,不能被修改;其所有的成员方法都是public、abstract的。抽象类中成员变量默认default,可在子类中被重新定义,也可被重新赋值;抽象方法被abstract修饰,不能被private、static、synchronized和native等修饰,必须以分号结尾,不带花括号。
  3. 接口里不包含构造方法;抽象类里可以包含构造方法,抽象类里的构造方法并不是用于创建对象,而是让其子类调用这些构造器来完成属于抽象类的初始化操作。
  4. 接口里不能包含初始化块;但抽象类则完全可以包含初始化块。
  5. 实现接口的关键字为implements,继承抽象类的关键字为extends。一个类可以实现多个接口,但一个类只能继承一个抽象类。所以,使用接口可以间接地实现多重继承。

操作系统

创建线程有几种方式

继承 Thread 、实现 Runnable、线程池创建、Callable 创建
事实上创建线程本质只有一种方式,就是构造一个 Thread 类,这是创建线程的唯一方式,不同的只是 run 方法(执行内容)的实现方式。

Thread类和Runable接口区别:

Thread类也是runnable接口子类,但并没有完全实现其中run方法,其run方法也是调用runnable中的run方法,所以如果通过继承thread类实现多线程,必须复写run方法。

进程间通信的方式

匿名管道、命名管道、信号、消息队列、共享内存、信号量、Socket

匿名管道

是一种半双工通信方式,数据只能单向流动,且只能在有亲缘关系的进程之间进行通信。(亲缘关系进程:父子进程)。

命名管道

由于匿名管道只能用于亲缘关系进程之间的通信,为了克服这个缺点,提出了命名管道。
命名管道提供了一个路径名与之关联,以有名管道的文件形式存在于文件系统中,这样只要可以访问该路径,彼此就可以进行通信,因此无亲缘关系的进程之间也能进行通信。
命名管道严格遵守先进先出原则,对有名管道的读是从开始处读,对其写是从末尾开始写,内容放在内存中

信号

信号可以在任何时刻发送给进程,而无序直到进程的状态

  1. 若进程并未开始执行,则将该信号保存起来,直到进程恢复执行,传递给该进程。
  2. 若信号为阻塞信号,则将该信号的传递延迟,直达其阻塞被取消时,才被传递给进程。

消息队列

  1. 消息队列是存放在内核中的消息链表。(无名管道:存在于内存文件中。有名管道:存在于实际的磁盘介质或文件系统)
  2. 每个消息队列由消息队列标识符表示。
  3. 消息队列只有系统重启或者显示地删除消息队列,才会被真正地删除。
  4. 与管道不同的是,在某一个进程往消息队列写入消息之前,不需要另外一个进程在该消息队列上等待消息。并且实现消息的随机读取,可以按照消息的类型读取。
  5. 消息队列允许一个或多个进程向他写入与读取消息。
  6. 消息队列的通信数据遵循先进先出原则
  7. 克服了信号量承载信息少,管道只能承载无格式字节流以及缓冲区大小受限。

共享内存

进程间内存是相互隔离的,而共享内存相当于给两个进程开辟了一块二者都可以访问的空间,这时两个进程就可以共享一些数据。

  • 但是多个进程同时占用资源会带来以外,这时会采用信号量控制。

信号量

解决进程和线程间并发执行时的同步问题。
对信号量操作分别分为p操作和v操作,p操作将信号量-1,v操作将信号量+1.当信号量小于等于0之后,再进行p操作时,当前线程会被阻塞,直到另一个线程或进程进行v操作直到信号量大于0时。

Socket

是应用层和传输层之间的桥梁。可以看作是不同主机之间的进程进行双向通信的端点(套接字=ip地址+端口号)

线程同步的方式

1.同步方法

用synchornized关键字修饰的方法,在java中每个对象都有一个内置锁,当用该关键词修饰方法时,当某个线程要进入该方法前,先要取得内置锁,否则处于阻塞状态。

  • 当该关键词修饰静态方法时,此时如果调用静态方法,锁住的是整个类。

2.同步代码块

用synchornized关键字修饰的代码块,该代码块会被加上内置锁。

  • 同步是一个高开销操作,因此应减少同步的内容,通常没必要同步整个方法,同步代码块即可

3.锁

Synchronized 原理

sychronized使用编程了monitorenter和monitorexit两个指令,每个锁对象都会关联一个monitor(监视器,它才是真正的锁对象),它内部有两个重要的成员变量owner会保存获得锁的线程,recursions会保存线程获得锁的次数,当执行到monitorexit时recursions-1,当计数减到0时,这个线程就会释放锁。每个对象拥有一个计数器,当线程获取该对象锁后,计数器就会加一,释放锁后就会将计数器减一,所以只要这个锁的计数器大于0,其它线程访问就只能等待。

执行同步代码块,首先会执行monitorenter指令,此时,线程会尝试获取该对象的monitor所有权,若monitor计数为0,则当前线程可以获得,并将monitor计数加一,若计数大于0,则等到计数等于0再去获取。然后执行同步代码块中的代码,退出同步代码块的时候会执行monitorexit指令 ,此时monitor计数减一,当计数减到0时,这个线程就会释放锁。

4.volatile

为域变量提供了一种免锁机制,使用volatile修饰域相当于告诉虚拟机,该域可能被其他线程更新,每次使用该域都要重新计算,而不是使用寄存器中的值,volatile不提供任何原子操作,也不能修饰final类型的变量。

5.信号量

同上

死锁的四个条件

1.互斥条件:一个资源只能被一个线程拥有
2.请求与保持条件:一个线程在阻塞时,对已有的资源保持不放
3.不可剥夺条件:一个进程已有的资源在未使用完之前,不能被剥夺。
4.循环等待

线程执行过程

线程生命周期:新建,可运行,运行,阻塞,死亡。

  1. 新建
    当new了一个线程后,该线程处于新建状态
  2. 可运行
    当线程对象调用了start方法之后,线程就处于可运行状态
  3. 运行
    当线程获得cpu时间片,才开始真正执行run方法的线程执行体
  4. 阻塞状态
    当线程在运行状态时,让出cpu并暂停自己的运行
  5. 死亡
  • run方法执行完成,线程正常结束
  • 线程抛出一个未捕获的exception或error。
  • 直接调用stop方法

cpu调度算法

先来先服务
最短作业优先
最高优先级
时间片轮转

线程sleep和wait方法作用和区别

1.sleep是thread中的静态方法,wait是object类中的成员方法;
2.sleep可以在任何地方使用,二wait只能在同步方法或同步代码块中使用
3.sleep不会释放锁,wait会释放锁。并需要通过notify或notifyAll来重新获得锁。

页面置换算法

先进先出置换算法
最近最久未使用置换算法

先进先出置换算法

每次选择淘汰的页面是最早进入内存的页面

最近最久未使用置换算法

每次淘汰的页面是最近最久未使用的页面

LRU的底层实现(哈希表和双向链表)

主线程消亡分支线程会如何

孤儿进程将被init进程(进程号为1)所收养,并由内核init进程对它们完成状态收集工作,而init进程会循环地wait()它的已经退出的子进程。因此孤儿进程并不会有什么危害。

僵尸进程

当前进程运行结束后,其父进程仍在运行,并且父进程没有调用wait来清理已结束的子进程,
或者一个进程使用fork创建子进程,如果子进程退出,而父进程并没有调用wait或waitpid获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中。这种进程称之为僵死进程。

如果进程不调用wait / waitpid的话, 那么保留的那段信息就不会释放,其进程号就会一直被占用,但是系统所能使用的进程号是有限的,如果大量的产生僵死进程,将因为没有可用进程号而导致系统不能产生新的进程. 此即为僵尸进程的危害,应当避免。
孤儿进程和僵尸进程都可能使系统不能产生新的进程,都应该避免

介绍一下线程池的工作流程

  1. 判断核心线程池是否已满,没满则创建一个新的工作线程来执行任务。
  2. 判断任务队列是否已满,没满则将新提交的任务添加在工作队列。
  3. 判断整个线程池是否已满,没满则创建一个新的工作线程来执行任务,已满则执行饱和(拒绝)策
    略。
    在这里插入图片描述

线程池的拒绝策略

当线程池的任务缓存队列已满并且线程池中的线程数目达到maximumPoolSize,如果还有任务到来就
会采取任务拒绝策略,通常有以下四种策略:

  1. AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。
  2. DiscardPolicy:也是丢弃任务,但是不抛出异常。
  3. DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复该过程)。
  4. CallerRunsPolicy:由调用线程处理该任务。

计算机网络

TCP三次握手

刚开始客户端处于closed状态,服务端处于listen状态

  1. 客户端向服务端发送一个syn请求报文,其中syn=1,并初始化客户端序列号seq=x,此时客户端处于syn_send状态。
  2. 服务端收到客户端发送的syn请求报文后,服务端需要对这个报文进行确认,设置ack=x+1,表示希望下一次收到的报文序列号为x+1。同时服务端也要发送一个syn请求报文,并初始化服务端序列号seq=y,服务端将上述报文封装到一个(ACK+SYN)报文段中,一并发送给客户端,此时服务端处于syn_recv状态。
  3. 客户端收到服务端发送的报文段后,会向服务端发送一个ACK报文,并设置ack=y+1,表示已经收到报文,并希望下一次收到的报文序列号为y+1,此时客户端处于established状态。
    当服务端收到ACK报文后也处于established状态。此时双方建起了连接。

TCP四次挥手

开始的时候客户端和服务端都处于连接状态

  1. 客户端向服务端发送一个FIN报文请求断开连接,并初始化序列号seq=x,此时客户端处于FIN_WAIT状态。
  2. 服务端收到FIN报文后,以一个ACK报文回复,并将ack number设置为x+1,表示已经收到报文,希望下次收到的报文序列号为x+1,此时服务端处于close_wait状态。
  3. 服务端发送一个FIN请求断开连接,并初始化序列号seq=y,并将ack number设置为x+1,表示已经收到报文,希望下次收到的报文序列号为x+1,此时服务端处于LAST_ACK状态。
  4. 客户端收到FIN报文后,以一个ACK报文回复,并将设置自身的seq=x+1,设置ack number=y+1,此时客户端处于close_wait状态,得过一段时间确保服务端收到ACK回复后才处于closed状态
    服务端收到ACK报文后,就关闭连接,处于closed状态

TCP和UDP的区别

  1. 连接:tcp面向连接,在传输数据之前先要建立好连接,udp面向无连接。
  2. 服务对象:tcp点对点的两点间服务,即一条tcp连接只有两个端点。udp可以支持一对一,一对多,多对一,多对多连接。
  3. 可靠性:tcp提供可靠交付服务,无差错,不丢包,不乱序,不重复。udp尽最大努力交付,不保证可靠性交付。
  4. 拥塞控制、流量控制:tcp有拥塞控制,流量控制来保证数据传输的安全性。udp没有拥塞控制。
  5. 报文长度:tcp面向字节流,报文长度是根据接收方的窗口大小和当前拥塞情况决定。udp面向报文,不合并,不拆分,保留上面传下来报文的边界。
  6. 首部开销:tcp首部开销大,20个字节。udp首部开销小,8个字节。
  7. 适用场景:tcp适用于要求数据完整的场景,udp使用于实时性场景。
  8. 优点:tcp可靠稳定,udp快,安全
  9. 缺点:tcp慢,效率低,占用资源高,易被攻击。udp不可靠,不稳定。

http的几种请求方式的区别

Get请求和Post请求的区别

  1. get一般用来获取数据,post一般用来发送数据后台。
  2. get请求也可以传参到后台,但是参数显示在地址栏,安全度低,且参数长度也有闲置。post请求一般将传递的参数放在request body里面,不会显示在地址栏,安全性高,参数长度也没有要求。
  3. get请求可以缓存,也会被保留在浏览器的历史记录中。post请求不能。
  4. get请求刷新浏览器或者回退没有影响,post请求则会重新请求一遍。
  5. get请求通过url请求,post通过表单请求。
  6. get产生一个数据包,post产生两个。对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。

PUT和POST的区别

PUT和POS都有更改指定URI的语义.但PUT被定义为idempotent的方法,POST则不是.idempotent的方法:如果一个方法重复执行多次,产生的效果是一样的,那就是idempotent的。也就是说:

  • PUT请求:如果两个请求相同,后一个请求会把第一个请求覆盖掉。(所以PUT用来改资源)
  • Post请求:后一个请求不会把第一个请求覆盖掉。(所以Post用来增资源)

HTTPS和HTTP的区别:

  1. https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。
  2. http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。
  3. http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
  4. http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。

浏览器发一个pos大致流程说一下

计算机网络中有

拥塞控制和流量控制

  • 流量控制是为了解决发送方和接收方速度不同而导致的数据丢失问题,当发送方发送的太快,接收方来不及接受就会导致数据丢失,流量控制用滑动窗口的形式解决问题
  • 拥塞控制是为了解决过多的数据注入到网络,导致网络奔溃,超过负荷.当发送方发送数据大量的数据会注入到网络,如果没有限制,网络就会超负荷变卡,拥塞控制的用的是拥塞窗口解决的问题的

流量控制

流量控制协议通过滑动窗口来实现.

简单来说就是发送窗口的大小,取接受方ACK提供的大小和发送方的拥塞窗口大小的最小值,来确定大小,发送窗口的大小不能超过滑动窗口的大小.为什么称为滑动窗口,因为当发送方接收到数据的确认信息,滑动窗口会更具返回的序号动态的改变窗口的位置.滑动的窗口大小得到了重置,同时滑动窗口会根据网络状况动态变化.

拥塞控制

拥塞控制是为了解决过多的数据注入到网络,导致网络奔溃,超过负荷,拥塞控制包含四个策略

慢开始
慢开始的含义就是讲窗口先设置为1,每个传输轮次大小增长一倍,直到大道慢开始的门限(ssthresh),这时候慢开始阶段结束

拥塞避免
慢开始结束后,接下来就是拥塞避免,这个阶段拥塞窗口在每个传输轮次数量加1,直到触发了网络拥塞,窗口大小和门限都变为拥塞时最大的值得一半,然后重新开始慢开始阶段

快重传
快重传指的是当接受方收到顺序错误得数据时不接收数据,同时重复发起对于之前数据的确认,发动到第三次,发送方得知自己的一部分数据再发送中丢失,立即发起重传,不需要等待下一次发送信息时一起发送过去.,且重传时触发和拥塞一样得情况,进入快恢复阶段

快恢复
快恢复就是再发生拥塞和重传时,窗口经历了拥塞避免阶段,然后进入快恢复阶段,和拥塞避免一样都是每次加一,这样能提高恢复速度,像老版本(Tahoe)中需要重新经历慢开始

数据结构

二叉树,平衡二叉树区别

二叉树:除了叶子节点外每一个节点都有两个子节点
平衡二叉树:非叶子结点最多只能有两个子结点,且左边子结点点小于当前结点值,右边子结点大于当前结点树,并且为保证查询性能增增删结点时要保证左右两边结点层级相差不大于1

堆、栈和队列有哪些适用场景

栈可以用于字符匹配,数据反转等场景

队列可以用于顺序处理数据,广度优先搜索,任务队列,等场景

堆可以用于优先队列,堆排序等场景

构造最大堆

首先找到最后一个结点的父结点,我们找到的结点是16,然后找出该结点的最大子节点与自己比较,若该子节点比自身大,则将两个结点交换.

堆排序

取下最后一个元素,与堆顶元素比较,小于堆顶元素则交换,其它元素继续调整为最大堆。

Hashmap结构

JDK1.7:数组+链表
JDK1.8:数组+链表/红黑树。当链表长度超过8时就转换为红黑树

红黑树

红黑树是一种自平衡二叉搜索树(BST),且红黑树节点遵循以下规则:

每个节点只能是红色或黑色
根节点总是黑色的
红色节点的父或子节点都必然是黑色的(两个红色的节点不会相连)
任一节点到其所有后代叶子节点的每条路径都具有相同数量的黑色节点
每个叶子节点都是黑色的

MySQL

事务ACID四个特性

  1. 原子性:是指整个事务是不可分割的工作单位,一个事务要么都执行成功,要么都失败,那么已经执行的sql语句也必须撤销,数据库应该退回到事务执行之前的状态。
  2. 一致性:是指事务将数据库从一种状态转换为另一种一致的状态。在事务开始之前和结束之后,数据库的完整性约束没有收到破坏。
  3. 隔离性:每个读写事务的对象与其他事务的对象能分离,即该事务提交之前对其他事务不可见。这通常用锁实现。
  4. 持久性:事务一旦提交,其结果就是永久的,即使发送宕机等事故,数据库也能将数据恢复,保证了数据库的高可靠性。

事务的隔离级别

四种隔离级别

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

事务的隔离级别是为了解决脏读、不可重复读、幻读等问题

  1. 脏读:当前事务读到其他事务未提交的数据。
  2. 不可重复读:事务先后两次读取同一个数据,两次读取的结果不同。
  3. 幻读:在事务中,先后两次查询数据库,第二次查询的条数增多。

上述四种隔离级别MySQL都支持,并且innodb存储引擎默认的支持隔离级别是可重复读,但是他使用next-key Lock的锁技术,避免了幻读的产生,所以innodb存储引擎在默认隔离级别下已经能完全保证事务的隔离性要求,即达到串行化隔离级别。

怎么解决不可重复读问题

采用了mvcc多版本并发控制,mvcc是利用在每条数据后面加了隐藏的两列,即创建版本号和删除版本号,每个事务在开始的时候都会有一个递增的版本号。

MVCC

InnoDB默认的隔离级别是REPEATABLE READ,RR解决脏读、不可重复读、幻读等问题,使用的是MVCC。MVCC全称Multi-Version Concurrency Control,即多版本的并发控制协议。它最大的优点是读不加锁,因此读写不冲突,并发性能好。InnoDB实现MVCC,多个版本的数据可以共存,主要基于以下技术及数据结构:

  1. 隐藏列:InnoDB中每行数据都有隐藏列,隐藏列中包含了本行数据的事务id、指向undo log的指针等。
  2. 基于undo log的版本链:每行数据的隐藏列中包含了指向undo log的指针,而每条undo log也会指向更早版本的undo log,从而形成一条版本链。
  3. ReadView:通过隐藏列和版本链,MySQL可以将数据恢复到指定版本。但是具体要恢复到哪个版本,则需要根据ReadView来确定。所谓ReadView,是指事务(记做事务A)在某一时刻给整个事务系统(trx_sys)打快照,之后再进行读操作时,会将读取到的数据中的事务id与trx_sys快照比较,从而判断数据对该ReadView是否可见,即对事务A是否可见。

间隙锁

InnoDB存储引擎有3种行锁的算法,间隙锁(Gap Lock)是其中之一。间隙锁用于锁定一个范围,但不包含记录本身。它的作用是为了阻止多个事务将记录插入到同一范围内,而这会导致幻读问题的产生。

什么情况下触发行锁?什么时候触发表锁?

如果走索引的话触发行锁,没走索引就变表锁,当然行锁也不是说就一定只锁了这一行,得看情况
行级锁并不是直接锁记录,而是锁索引。索引分为主键索引和非主键索引两种,如果一条sql语句操作了主键索引,MySQL就会锁定这条主键索引;如果一条语句操作了非主键索引,MySQL会先锁定该非主键索引,再锁定相关的主键索引。

有时有索引也会导致表锁的情况

  1. 导致这个的原因第一是sql语句写法问题,没有合理构建和使用索引。
  2. 第二个原因是mysql的优化器,有时优化器发现:即使使用了索引,还是要做全表扫描,故而放弃了索引,也就没有使用行锁,却使用了表锁

文件系统的索引用的什么数据结构

B+树

当索引数据太大的时候,一般不能全部加载到内存,相对于内存存取,磁盘I/O存取的消耗要高好几个数量级,索引的结构组织要尽量减少查找过程I/O次数。
磁盘往往会预读,即读完数据会向后读取一定长度的数据放入内存。由于磁盘顺序读取效率高,对于具有局部性的程序,预读可以提高I/O效率。预读大小一般为页的整数倍,对于文件系统索引中的树实现,每次新建一个节点会直接申请一个页的空间,这样保证了一个节点物理上存储在一个页里,就实现了一个节点只需一次I/O,在此基础上只有减少节点遍历次数——控制树的高度,既可以减少I/O次数。

二叉树不适合:无法控制高度
红黑树不适合:无法利用局部性
B+树适合:

  1. 每个节点对应很多叶子节点,插入节点时增加叶子节点个数而不是树的高度。
  2. B+树内部节点没有指向关键字的具体信息,因此内部节点更小。如果把所有同一关键词放在同一块磁盘,这样一次性需要查找的关键字越多I/O次数更低了。
  3. B+树查询效率更加稳定,B树可能在非叶子节点结束,而在B+树,顺序索引比较明显,任何关键字查找必须走一条从根节点到叶子节点的路径,所有关键字查找长度相同,效率相当。
  4. 范围查找优势更明显:通过二分查找找到范围的下限,置换通过叶子节点的链表顺序遍历,就可以找到上限,操作简单,效率高。

为什么mysql索引用B+树而不用哈希表

  1. 如果是等值查询,那么哈希索引明显有绝对优势,因为只需要经过一次算法即可找到相应的键值;当然了,这个前提是,键值都是唯一的。如果键值不是唯一的,就需要先找到该键所在位置,然后再根据链表往后扫描,直到找到相应的数据;
  2. 如果是范围查询检索,这时候哈希索引就毫无用武之地了,因为原先是有序的键值,经过哈希算法后,有可能变成不连续的了,就没办法再利用索引完成范围查询检索;
  3. 同理,哈希索引也没办法利用索引完成排序,以及like ‘xxx%’ 这样的部分模糊查询(这种部分模糊查询,其实本质上也是范围查询);
  4. 哈希索引也不支持多列联合索引的最左匹配规则;
  5. B+树索引的关键字检索效率比较平均,不像B树那样波动幅度大,在有大量重复键值情况下,哈希索引的效率也是极低的,因为存在所谓的哈希碰撞问题。

spring

怎么理解spring

1.spring是一个轻量级的、开源的J2EE框架
轻量级:扎包数量少,体积小,可独立提供使用。
开源:免费提供源代码。
框架:开发更方便,代码更简洁。

2.解决企业应用开发的复杂性

3.两个核心部分:IOC,AOP。
IOC : 控制反转,把创建对象的过程交给spring管理。
AOP : 面向切面,不修改源代码进行功能增强。

4.特点
方便解耦,简化开发
AOP编程支持
方便程序测试
方便和其他框架集成
方便进行事务操作
降低API使用难度

理解springMVC

Spring MVC是一个基于Java的实现了MVC设计模式的请求驱动类型的轻量级Web框架,通过把模型-视图-控制器分离,将web层进行职责解耦,把复杂的web应用分成逻辑清晰的几部分,简化开发,减少出错,方便组内开发人员之间的配合。

理解springBoot

Spring Boot 是 Spring 开源组织下的子项目,是 Spring 组件一站式解决方案,主要是简化了使用 Spring 的难度,简省了繁重的配置,提供了各种启动器,开发者能快速上手。

自动注入时定义的接口有两个实现类,怎么注入

可以通过 byName 注入的方式。可以使用 @Resource 或 @Qualifier 注解

Spring 框架中用到了哪些设计模式:

  1. 工厂设计模式 : Spring使用工厂模式通过 BeanFactory、ApplicationContext 创建 bean 对象。
  2. 代理设计模式 : Spring AOP 功能的实现。
  3. 单例设计模式 : Spring 中的 Bean 默认都是单例的。
  4. 模板方法模式 : Spring 中 jdbcTemplate、hibernateTemplate 等以 Template 结尾的对数据库操作的类,它们就使用到了模板模式。
  5. 包装器设计模式 : 我们的项目需要连接多个数据库,而且不同的客户在每次访问中根据需要会去访问不同的数据库。这种模式让我们可以根据客户的需求能够动态切换不同的数据源。
  6. 观察者模式: Spring 事件驱动模型就是观察者模式很经典的一个应用。
  7. 适配器模式 :Spring AOP 的增强或通知(Advice)使用到了适配器模式、spring MVC 中也是用到了适配器模式适配Controller。

Spring有哪些核心技术

spring框架包含众多模块,其中有core,test,data access等模块,其中core是spring的核心模块,core中有ioc容器,aop功能,数据绑定等一系列基础功能,而这些功能以及其他模块的功能,又是建立在ioc,aop之上的,所以IOC,AOP是spring框架的核心。

  1. IOC:控制反转,是一种面向对象编程的设计思想,在不采用这种思想的情况下,我们需要自己维护对象和对象之间的依赖关系,很容易造成对象之间耦合度过高,不利于代码的维护。由IOC维护对象和对象之间的关系可以解决这种问题。 控制反转 在 Spring 里的实现是 Dependency Injection ( 依赖注入),就是说对象之间的依赖关系在后期通过注解或配置文件(典型为 XML 文件)生成。注解注入:@Component,@Service,@Controller,@Repository。配置文件:构造函数注入、 Setter 方法注入,p名称空间注入。我们可以这样理解这种技术带来的好处,前期我们只需要关注单个对象(组件)的功能实现,具体的业务实现是通过后期配置出来的,不同的配置可以产生不同的业务功能。
  2. AOP:面向切面编程,利用AOP可以对业务逻辑进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。不通过修改源代码方式添加新功能。

IOC

依赖注入怎么实现

  1. 构造方法注入
    就是被注入对象可以在它的构造方法中声明依赖对象的参数列表,让外部知道它需要哪些依赖对象。然后,IoC Service Provider会检查被注入的对象的构造方法,取得它所需要的依赖对象列表,进而为其注入相应的对象。构造方法注入方式比较直观,对象被构造完成后,即进入就绪状态,可以马上使用。
  2. setter方法注入
    通过setter方法,可以更改相应的对象属性。所以,当前对象只要为其依赖对象所对应的属性添加setter方法,就可以通过setter方法将相应的依赖对象设置到被注入对象中。setter方法注入虽不像构造方法注入那样,让对象构造完成后即可使用,但相对来说更宽松一些,可以在对象构造完成后再注入。
  3. 接口注入
    相对于前两种注入方式来说,接口注入没有那么简单明了。被注入对象如果想要IoC ServiceProvider为其注入依赖对象,就必须实现某个接口。这个接口提供一个方法,用来为其注入依赖对象。IoC Service Provider最终通过这些接口来了解应该为被注入对象注入什么依赖对象。相对于前两种依赖注入方式,接口注入比较死板和烦琐。

总体来说,构造方法注入和setter方法注入因为其侵入性较弱,且易于理解和使用,所以是现在使用最多的注入方式。而接口注入因为侵入性较强,近年来已经不流行了。

Spring是如何管理Bean的?

Spring通过IoC容器来管理Bean,我们可以通过XML配置或者注解配置,来指导IoC容器对Bean的管理。因为注解配置比XML配置方便很多,所以现在大多时候会使用注解配置的方式。
以下是管理Bean时常用的一些注解:

  1. @ComponentScan用于声明扫描策略,通过它的声明,容器就知道要扫描哪些包下带有声明的类,也可以知道哪些特定的类是被排除在外的。
  2. @Component、@Repository、@Service、@Controller用于声明Bean,它们的作用一样,但是语义不同。@Component用于声明通用的Bean,@Repository用于声明DAO层的Bean,@Service用于声明业务层的Bean,@Controller用于声明视图层的控制器Bean,被这些注解声明的类就可以被容器扫描并创建。
  3. @Autowired、@Qualifier、@Resource用于注入Bean,即告诉容器应该为当前属性注入哪个Bean。其中,@Autowired是按照Bean的类型进行匹配的。如果这个属性的类型具有多个Bean,就可以通过@Qualifier指定Bean的名称,以消除歧义。@Resource等同于@Autowired+@Qualifier,该注解是Java原生的注解,既可以根据类型,又可以根据名称进行依赖注入。
  4. @Scope用于声明Bean的作用域,默认情况下Bean是单例的,即在整个容器中这个类型只有一个实例。可以通过@Scope注解指定prototype值将其声明为多例的,也可以将Bean声明为session级作用域、request级作用域等等,但最常用的还是默认的单例模式。
  5. @PostConstruct、@PreDestroy用于声明Bean的生命周期。其中,被@PostConstruct修饰的方法将在Bean实例化后被调用,@PreDestroy修饰的方法将在容器销毁前被调用。

AOP

  1. 面向切面编程,利用AOP可以对业务逻辑进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
  2. 不通过修改源代码方式添加新功能

术语

  • 连接点(join point):对应的是具体被拦截的对象,因为Spring只能支持方法,所以被拦截的对象往往就是指特定的方法,AOP将通过动态代理技术把它织入对应的流程中。
  • 切点(point cut):有时候,我们的切面不单单应用于单个方法,也可能是多个类的不同方法,这时,可以通过正则式和指示器的规则去定义,从而适配连接点。切点就是提供这样一个功能的概念。
  • 通知(advice):就是按照约定的流程下的方法,分为前置通知、后置通知、环绕通知、事后返回
    通知和异常通知,它会根据约定织入流程中。
  • 切面:是动作,把通知应用到切入点

AOP具体实现

  • JDK动态代理:这是Java提供的动态代理技术,可以在运行时创建接口的代理实例。Spring AOP默认采用这种方式,在接口的代理实例中织入代码。
  • CGLib动态代理:采用底层的字节码技术,在运行时创建子类代理的实例。当目标对象不存在接口时,Spring AOP就会采用这种方式,在子类实例中织入代码。

springMVC

什么是Spring MVC

Spring MVC是一个基于Java的实现了MVC设计模式的请求驱动类型的轻量级Web框架,通过把模型-视图-控制器分离,将web层进行职责解耦,把复杂的web应用分成逻辑清晰的几部分,简化开发,减少出错,方便组内开发人员之间的配合。

什么是MVC

MVC是一种设计模式,在这种模式下软件被分为三层,即Model(模型)、View(视图)、Controller(控制器)。Model代表的是数据,View代表的是用户界面,Controller代表的是数据的处理逻辑,它是Model和View这两层的桥梁。将软件分层的好处是,可以将对象之间的耦合度降低,便于代码的维护。

请描述Spring MVC的工作流程?

(1)用户发送请求至前端控制器DispatcherServlet;
(2) DispatcherServlet收到请求后,调用HandlerMapping处理器映射器,请求获取Handle;
(3)处理器映射器根据请求url找到具体的处理器Handler,生成Handler对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet;
(4)DispatcherServlet 调用 HandlerAdapter处理器适配器,执行Handler;
(5)HandlerAdapter 经过适配调用 具体处理器(Handler,也叫后端控制器);
(6)Handler执行完成返回ModelAndView;
(7)HandlerAdapter将Handler执行结果ModelAndView返回给DispatcherServlet;
(8)DispatcherServlet将ModelAndView传给ViewResolver视图解析器进行解析;
(9)ViewResolver解析后返回具体View;
(10)DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)
(11)DispatcherServlet响应用户。
在这里插入图片描述

Spring MVC注解

@RequestMapping:
作用:该注解的作用就是用来处理请求地址映射的,也就是说将其中的处理器方法映射到url路径上。
属性:
method:是让你指定请求的method的类型,比如常用的有get和post。
value:是指请求的实际地址,如果是多个地址就用{}来指定就可以啦。
produces:指定返回的内容类型,当request请求头中的Accept类型中包含指定的类型才可以返
回的。
consumes:指定处理请求的提交内容类型,比如一些json、html、text等的类型。
headers:指定request中必须包含那些的headed值时,它才会用该方法处理请求的。
params:指定request中一定要有的参数值,它才会使用该方法处理请求。
@RequestParam:
作用:是将请求参数绑定到你的控制器的方法参数上,是Spring MVC中的接收普通参数的注解。
属性:
value是请求参数中的名称。
required是请求参数是否必须提供参数,它的默认是true,意思是表示必须提供。
@RequestBody:
作用:如果作用在方法上,就表示该方法的返回结果是直接按写入的Http responsebody中(一般在异
步获取数据时使用的注解)。
属性:required,是否必须有请求体。它的默认值是true,在使用该注解时,值得注意的当为true时
get的请求方式是报错的,如果你取值为false的话,get的请求是null。
@PathVaribale:
作用:该注解是用于绑定url中的占位符,但是注意,spring3.0以后,url才开始支持占位符的,它是
Spring MVC支持的rest风格url的一个重要的标志。

未解决

你了解设计模式吗,适配器模式和装饰器模式是什么

7.其他问题
我说到了springmvc404的问题
8.学spring学了什么
我说主要就是如何应用,还有它的ioc思想
9.ioc思想是什么
控制反转,把我们要做的事委托给spring框架,以前需要new,现在只需要依赖注入
10.怎么注入
通过构造方法,静态工厂,实例工厂,注解等(我答错了 这是创建bean。。)
11.注入遇到过什么问题
讲了一下autowired,qualifier、resourse注解咋用的
12.了解aop吗
简单说了下就是面向切面编程,然后有before、afterthrowing、afterreturning、after、around
13.aop具体咋实现的
如果实现了接口就是jdk自动代理,主要是invocationhandler,如果没有实现接口就是cglib,创建某个类的子类,不能是final修饰的

长连接的保活机制、心跳包
怎么处理已经失效的连接

开放题:12306为什么不买很多服务器,但是抢票的时候还是不卡?(扯CAP,最后面试官说其实不买很多服务器的原因是一年抢票也就那么几次,考虑投入使用比)
高可用性的秒杀系统是怎么样的、使用情景(CAP舍弃C)
还投了哪些公司?拿到了哪些offer?怎么看互联网和银行、怎么选择?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值