1、什么是面向对象?

对比面向过程,是两种不同的处理问题的角度

面向过程更注重事情的每一个步骤及 顺序,面向对象更注重事情有哪些参与者(对象)、及各自需要做什么

比如:洗衣机洗衣服

面向过程会将任务拆解成一系列的步骤 (函数),1. 打开洗衣机—>2. 放衣服---->3、放洗衣粉---->4清洗----->5、烘干

面向对象会拆出人和洗衣机两个对象:

​ 人:打开洗衣机放衣服放洗衣粉

​ 洗衣机:清洗烘干

从以上例子能看出,面向过程比较直接高效,而面向对象更易于复用、扩展和维护

  • 封装:封装的意义,在于明确标识出允许外部使用的所有成员函数和数据项,内部细节对外部调用透明,外部调用无需修改或者关心内部实现

    1、javabean的属性私有,提供get、set对外访问,因为属性的赋值或者获取逻辑只能由javabean本身决定。而不能由外部胡乱修改

    private String name ;
    public void setName (String name){this .name = "tuling. _"+name;
    }
    //该name有自己的命名规则,明显不能由外部直接赋值
    

    2、orm框架

    操作数据库,我们不需要关心链接是如何建立的、sql是如何执行的,只需要引入mybatis, 调方法即可

  • 继承:继承基类的方法,并做出自己的改变或扩展

    子类共性的方法或者属性直接使用父类的,而不需要自己再定义,只需扩展自己个性化的

  • 多态:基于对象所属类的不同,外部对同一个方法的调用,实际执行的逻辑不同。

    继承、方法重写、父类引用指向子类对象

    父类类型 变量名 = new 子类类型();
    变量名.方法名();
    

    无法调用子类特有的功能(重写的方法)

2、JDK、JRE、JVM 三者关系和区别

JDK: java develpment kit java 开发工具

包括JRE、java 工具(javac、java、jconsole等)。

JRE: java runtime environment java运行时环境

包括bin(包含jvm) 、lib(类库)。

JVM: java virtual Machine java 虚拟机

java对不同的操作系统提供了不同的JVM,JVM 屏蔽系统的差异,从而实现,一次编译到处运行。

#mermaid-svg-ad59vw97x2ViG8al .label{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);fill:#333;color:#333}#mermaid-svg-ad59vw97x2ViG8al .label text{fill:#333}#mermaid-svg-ad59vw97x2ViG8al .node rect,#mermaid-svg-ad59vw97x2ViG8al .node circle,#mermaid-svg-ad59vw97x2ViG8al .node ellipse,#mermaid-svg-ad59vw97x2ViG8al .node polygon,#mermaid-svg-ad59vw97x2ViG8al .node path{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-ad59vw97x2ViG8al .node .label{text-align:center;fill:#333}#mermaid-svg-ad59vw97x2ViG8al .node.clickable{cursor:pointer}#mermaid-svg-ad59vw97x2ViG8al .arrowheadPath{fill:#333}#mermaid-svg-ad59vw97x2ViG8al .edgePath .path{stroke:#333;stroke-width:1.5px}#mermaid-svg-ad59vw97x2ViG8al .flowchart-link{stroke:#333;fill:none}#mermaid-svg-ad59vw97x2ViG8al .edgeLabel{background-color:#e8e8e8;text-align:center}#mermaid-svg-ad59vw97x2ViG8al .edgeLabel rect{opacity:0.9}#mermaid-svg-ad59vw97x2ViG8al .edgeLabel span{color:#333}#mermaid-svg-ad59vw97x2ViG8al .cluster rect{fill:#ffffde;stroke:#aa3;stroke-width:1px}#mermaid-svg-ad59vw97x2ViG8al .cluster text{fill:#333}#mermaid-svg-ad59vw97x2ViG8al div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:12px;background:#ffffde;border:1px solid #aa3;border-radius:2px;pointer-events:none;z-index:100}#mermaid-svg-ad59vw97x2ViG8al .actor{stroke:#ccf;fill:#ECECFF}#mermaid-svg-ad59vw97x2ViG8al text.actor>tspan{fill:#000;stroke:none}#mermaid-svg-ad59vw97x2ViG8al .actor-line{stroke:grey}#mermaid-svg-ad59vw97x2ViG8al .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333}#mermaid-svg-ad59vw97x2ViG8al .messageLine1{stroke-width:1.5;stroke-dasharray:2, 2;stroke:#333}#mermaid-svg-ad59vw97x2ViG8al #arrowhead path{fill:#333;stroke:#333}#mermaid-svg-ad59vw97x2ViG8al .sequenceNumber{fill:#fff}#mermaid-svg-ad59vw97x2ViG8al #sequencenumber{fill:#333}#mermaid-svg-ad59vw97x2ViG8al #crosshead path{fill:#333;stroke:#333}#mermaid-svg-ad59vw97x2ViG8al .messageText{fill:#333;stroke:#333}#mermaid-svg-ad59vw97x2ViG8al .labelBox{stroke:#ccf;fill:#ECECFF}#mermaid-svg-ad59vw97x2ViG8al .labelText,#mermaid-svg-ad59vw97x2ViG8al .labelText>tspan{fill:#000;stroke:none}#mermaid-svg-ad59vw97x2ViG8al .loopText,#mermaid-svg-ad59vw97x2ViG8al .loopText>tspan{fill:#000;stroke:none}#mermaid-svg-ad59vw97x2ViG8al .loopLine{stroke-width:2px;stroke-dasharray:2, 2;stroke:#ccf;fill:#ccf}#mermaid-svg-ad59vw97x2ViG8al .note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-ad59vw97x2ViG8al .noteText,#mermaid-svg-ad59vw97x2ViG8al .noteText>tspan{fill:#000;stroke:none}#mermaid-svg-ad59vw97x2ViG8al .activation0{fill:#f4f4f4;stroke:#666}#mermaid-svg-ad59vw97x2ViG8al .activation1{fill:#f4f4f4;stroke:#666}#mermaid-svg-ad59vw97x2ViG8al .activation2{fill:#f4f4f4;stroke:#666}#mermaid-svg-ad59vw97x2ViG8al .mermaid-main-font{font-family:"trebuchet ms", verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-ad59vw97x2ViG8al .section{stroke:none;opacity:0.2}#mermaid-svg-ad59vw97x2ViG8al .section0{fill:rgba(102,102,255,0.49)}#mermaid-svg-ad59vw97x2ViG8al .section2{fill:#fff400}#mermaid-svg-ad59vw97x2ViG8al .section1,#mermaid-svg-ad59vw97x2ViG8al .section3{fill:#fff;opacity:0.2}#mermaid-svg-ad59vw97x2ViG8al .sectionTitle0{fill:#333}#mermaid-svg-ad59vw97x2ViG8al .sectionTitle1{fill:#333}#mermaid-svg-ad59vw97x2ViG8al .sectionTitle2{fill:#333}#mermaid-svg-ad59vw97x2ViG8al .sectionTitle3{fill:#333}#mermaid-svg-ad59vw97x2ViG8al .sectionTitle{text-anchor:start;font-size:11px;text-height:14px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-ad59vw97x2ViG8al .grid .tick{stroke:#d3d3d3;opacity:0.8;shape-rendering:crispEdges}#mermaid-svg-ad59vw97x2ViG8al .grid .tick text{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-ad59vw97x2ViG8al .grid path{stroke-width:0}#mermaid-svg-ad59vw97x2ViG8al .today{fill:none;stroke:red;stroke-width:2px}#mermaid-svg-ad59vw97x2ViG8al .task{stroke-width:2}#mermaid-svg-ad59vw97x2ViG8al .taskText{text-anchor:middle;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-ad59vw97x2ViG8al .taskText:not([font-size]){font-size:11px}#mermaid-svg-ad59vw97x2ViG8al .taskTextOutsideRight{fill:#000;text-anchor:start;font-size:11px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-ad59vw97x2ViG8al .taskTextOutsideLeft{fill:#000;text-anchor:end;font-size:11px}#mermaid-svg-ad59vw97x2ViG8al .task.clickable{cursor:pointer}#mermaid-svg-ad59vw97x2ViG8al .taskText.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-ad59vw97x2ViG8al .taskTextOutsideLeft.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-ad59vw97x2ViG8al .taskTextOutsideRight.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-ad59vw97x2ViG8al .taskText0,#mermaid-svg-ad59vw97x2ViG8al .taskText1,#mermaid-svg-ad59vw97x2ViG8al .taskText2,#mermaid-svg-ad59vw97x2ViG8al .taskText3{fill:#fff}#mermaid-svg-ad59vw97x2ViG8al .task0,#mermaid-svg-ad59vw97x2ViG8al .task1,#mermaid-svg-ad59vw97x2ViG8al .task2,#mermaid-svg-ad59vw97x2ViG8al .task3{fill:#8a90dd;stroke:#534fbc}#mermaid-svg-ad59vw97x2ViG8al .taskTextOutside0,#mermaid-svg-ad59vw97x2ViG8al .taskTextOutside2{fill:#000}#mermaid-svg-ad59vw97x2ViG8al .taskTextOutside1,#mermaid-svg-ad59vw97x2ViG8al .taskTextOutside3{fill:#000}#mermaid-svg-ad59vw97x2ViG8al .active0,#mermaid-svg-ad59vw97x2ViG8al .active1,#mermaid-svg-ad59vw97x2ViG8al .active2,#mermaid-svg-ad59vw97x2ViG8al .active3{fill:#bfc7ff;stroke:#534fbc}#mermaid-svg-ad59vw97x2ViG8al .activeText0,#mermaid-svg-ad59vw97x2ViG8al .activeText1,#mermaid-svg-ad59vw97x2ViG8al .activeText2,#mermaid-svg-ad59vw97x2ViG8al .activeText3{fill:#000 !important}#mermaid-svg-ad59vw97x2ViG8al .done0,#mermaid-svg-ad59vw97x2ViG8al .done1,#mermaid-svg-ad59vw97x2ViG8al .done2,#mermaid-svg-ad59vw97x2ViG8al .done3{stroke:grey;fill:#d3d3d3;stroke-width:2}#mermaid-svg-ad59vw97x2ViG8al .doneText0,#mermaid-svg-ad59vw97x2ViG8al .doneText1,#mermaid-svg-ad59vw97x2ViG8al .doneText2,#mermaid-svg-ad59vw97x2ViG8al .doneText3{fill:#000 !important}#mermaid-svg-ad59vw97x2ViG8al .crit0,#mermaid-svg-ad59vw97x2ViG8al .crit1,#mermaid-svg-ad59vw97x2ViG8al .crit2,#mermaid-svg-ad59vw97x2ViG8al .crit3{stroke:#f88;fill:red;stroke-width:2}#mermaid-svg-ad59vw97x2ViG8al .activeCrit0,#mermaid-svg-ad59vw97x2ViG8al .activeCrit1,#mermaid-svg-ad59vw97x2ViG8al .activeCrit2,#mermaid-svg-ad59vw97x2ViG8al .activeCrit3{stroke:#f88;fill:#bfc7ff;stroke-width:2}#mermaid-svg-ad59vw97x2ViG8al .doneCrit0,#mermaid-svg-ad59vw97x2ViG8al .doneCrit1,#mermaid-svg-ad59vw97x2ViG8al .doneCrit2,#mermaid-svg-ad59vw97x2ViG8al .doneCrit3{stroke:#f88;fill:#d3d3d3;stroke-width:2;cursor:pointer;shape-rendering:crispEdges}#mermaid-svg-ad59vw97x2ViG8al .milestone{transform:rotate(45deg) scale(0.8, 0.8)}#mermaid-svg-ad59vw97x2ViG8al .milestoneText{font-style:italic}#mermaid-svg-ad59vw97x2ViG8al .doneCritText0,#mermaid-svg-ad59vw97x2ViG8al .doneCritText1,#mermaid-svg-ad59vw97x2ViG8al .doneCritText2,#mermaid-svg-ad59vw97x2ViG8al .doneCritText3{fill:#000 !important}#mermaid-svg-ad59vw97x2ViG8al .activeCritText0,#mermaid-svg-ad59vw97x2ViG8al .activeCritText1,#mermaid-svg-ad59vw97x2ViG8al .activeCritText2,#mermaid-svg-ad59vw97x2ViG8al .activeCritText3{fill:#000 !important}#mermaid-svg-ad59vw97x2ViG8al .titleText{text-anchor:middle;font-size:18px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-ad59vw97x2ViG8al g.classGroup text{fill:#9370db;stroke:none;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:10px}#mermaid-svg-ad59vw97x2ViG8al g.classGroup text .title{font-weight:bolder}#mermaid-svg-ad59vw97x2ViG8al g.clickable{cursor:pointer}#mermaid-svg-ad59vw97x2ViG8al g.classGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-ad59vw97x2ViG8al g.classGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-ad59vw97x2ViG8al .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5}#mermaid-svg-ad59vw97x2ViG8al .classLabel .label{fill:#9370db;font-size:10px}#mermaid-svg-ad59vw97x2ViG8al .relation{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-ad59vw97x2ViG8al .dashed-line{stroke-dasharray:3}#mermaid-svg-ad59vw97x2ViG8al #compositionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-ad59vw97x2ViG8al #compositionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-ad59vw97x2ViG8al #aggregationStart{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-ad59vw97x2ViG8al #aggregationEnd{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-ad59vw97x2ViG8al #dependencyStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-ad59vw97x2ViG8al #dependencyEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-ad59vw97x2ViG8al #extensionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-ad59vw97x2ViG8al #extensionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-ad59vw97x2ViG8al .commit-id,#mermaid-svg-ad59vw97x2ViG8al .commit-msg,#mermaid-svg-ad59vw97x2ViG8al .branch-label{fill:lightgrey;color:lightgrey;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-ad59vw97x2ViG8al .pieTitleText{text-anchor:middle;font-size:25px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-ad59vw97x2ViG8al .slice{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-ad59vw97x2ViG8al g.stateGroup text{fill:#9370db;stroke:none;font-size:10px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-ad59vw97x2ViG8al g.stateGroup text{fill:#9370db;fill:#333;stroke:none;font-size:10px}#mermaid-svg-ad59vw97x2ViG8al g.statediagram-cluster .cluster-label text{fill:#333}#mermaid-svg-ad59vw97x2ViG8al g.stateGroup .state-title{font-weight:bolder;fill:#000}#mermaid-svg-ad59vw97x2ViG8al g.stateGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-ad59vw97x2ViG8al g.stateGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-ad59vw97x2ViG8al .transition{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-ad59vw97x2ViG8al .stateGroup .composit{fill:white;border-bottom:1px}#mermaid-svg-ad59vw97x2ViG8al .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px}#mermaid-svg-ad59vw97x2ViG8al .state-note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-ad59vw97x2ViG8al .state-note text{fill:black;stroke:none;font-size:10px}#mermaid-svg-ad59vw97x2ViG8al .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.7}#mermaid-svg-ad59vw97x2ViG8al .edgeLabel text{fill:#333}#mermaid-svg-ad59vw97x2ViG8al .stateLabel text{fill:#000;font-size:10px;font-weight:bold;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-ad59vw97x2ViG8al .node circle.state-start{fill:black;stroke:black}#mermaid-svg-ad59vw97x2ViG8al .node circle.state-end{fill:black;stroke:white;stroke-width:1.5}#mermaid-svg-ad59vw97x2ViG8al #statediagram-barbEnd{fill:#9370db}#mermaid-svg-ad59vw97x2ViG8al .statediagram-cluster rect{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-ad59vw97x2ViG8al .statediagram-cluster rect.outer{rx:5px;ry:5px}#mermaid-svg-ad59vw97x2ViG8al .statediagram-state .divider{stroke:#9370db}#mermaid-svg-ad59vw97x2ViG8al .statediagram-state .title-state{rx:5px;ry:5px}#mermaid-svg-ad59vw97x2ViG8al .statediagram-cluster.statediagram-cluster .inner{fill:white}#mermaid-svg-ad59vw97x2ViG8al .statediagram-cluster.statediagram-cluster-alt .inner{fill:#e0e0e0}#mermaid-svg-ad59vw97x2ViG8al .statediagram-cluster .inner{rx:0;ry:0}#mermaid-svg-ad59vw97x2ViG8al .statediagram-state rect.basic{rx:5px;ry:5px}#mermaid-svg-ad59vw97x2ViG8al .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#efefef}#mermaid-svg-ad59vw97x2ViG8al .note-edge{stroke-dasharray:5}#mermaid-svg-ad59vw97x2ViG8al .statediagram-note rect{fill:#fff5ad;stroke:#aa3;stroke-width:1px;rx:0;ry:0}:root{--mermaid-font-family: '"trebuchet ms", verdana, arial';--mermaid-font-family: "Comic Sans MS", "Comic Sans", cursive}#mermaid-svg-ad59vw97x2ViG8al .error-icon{fill:#522}#mermaid-svg-ad59vw97x2ViG8al .error-text{fill:#522;stroke:#522}#mermaid-svg-ad59vw97x2ViG8al .edge-thickness-normal{stroke-width:2px}#mermaid-svg-ad59vw97x2ViG8al .edge-thickness-thick{stroke-width:3.5px}#mermaid-svg-ad59vw97x2ViG8al .edge-pattern-solid{stroke-dasharray:0}#mermaid-svg-ad59vw97x2ViG8al .edge-pattern-dashed{stroke-dasharray:3}#mermaid-svg-ad59vw97x2ViG8al .edge-pattern-dotted{stroke-dasharray:2}#mermaid-svg-ad59vw97x2ViG8al .marker{fill:#333}#mermaid-svg-ad59vw97x2ViG8al .marker.cross{stroke:#333}:root { --mermaid-font-family: "trebuchet ms", verdana, arial;} #mermaid-svg-ad59vw97x2ViG8al {color: rgba(0, 0, 0, 0.75);font: ;}

JDK
JRE
Java 工具
javac编译
映射到系统调用
映射到系统调用
javac、java、jconsole
bin(jvm)
lib(类库)
.java文件
.class文件
windows jvm
windows
linux jvm
linux

3、== 和 equals

== : 比较的是栈中的值,基本数据类型因为是栈中分配值所以比较的是变量值,引用类型因为是堆中分配,对象存在堆中,栈中存的只是引用地址,所以比较的是引用地址。

equals :object中默认equals方法也是采用==比较,通常会重写。

public boolean equals(Object obj){return (this == obj);
}

String

public boolean equals(Object anObject) {if (this == anObject) {return true;}if (anObject instanceof String) {String anotherString = (String)anObject;int n = value.length;if (n == anotherString.value.length) {char v1[] = value;char v2[] = anotherString.value;int i = 0;while (n-- != 0) {if (v1[i] != v2[i])return false;i++;}return true;}}return false;}

4、final 作用

最终的

  • 修饰类:表示类不可被继承

  • 修饰方法:表示方法不可被子类覆盖,但是可以重载

  • 修饰变量:表示变量一旦被赋值就不可以更改它的值。

(1)修饰成员变量

  • 如果final修饰的是类变量,只能在静态初始化块中指定初始值或者声明该类变量时指定初始值。

  • 如果final修饰的是成员变量,可以在非静态初始化块、声明该变量或者构造器中执行初始值。

(2)修饰局部变量

系统不会为局部变量进行初始化,局部变量必须由程序员显示初始化。因此使用fina|修饰局部变量时, 即可以在

public class FinalVar{final static int a=0;//类变量在声明的时候就需要赋值,或者在静态代码块中赋值/*static{a= 0;//静态代码块中赋值}*/final int b=0;//普通成员变量在声明的时候就需要赋值,或者在非静态代码块中赋值,或者构造器中赋值/*{b=0; //代码块赋值}*//*public FinalVar(){b=0;//构造器赋值}*/public static void main(String[] args){final int c;//局部变量只声明没赋值,不会报错,与final无关c=0;//使用前必须赋值,且只能赋值一次System.out.println(c);}
}

(3)修饰基本类型数据和引用类型数据

  • 如果是基本数据类型的变量,则其数值- -旦在初始化之后便不能更改;

  • 如果是引用类型的变量,则在对其初始化之后便不能再让其指向另一个对象。但是引用的值是可变的。

  public class FinalReferenceDemo{public static void main(String[] args){final int[] iarr={1,2,3,4};iarr[2]=-3;//合法// iarr=null;//非法,不能重复赋值final User user=new User("wangwu");user.setName("lisi");//合法// user=null;//非法,不能重复赋值} }

5、为什么局部内部类、匿名内部类和lambda 表达式

编译之后会生成两个class文件,Test.class 和 Test1.class

public class Test{public t(final int a){//参数也是局部变量final int b=2;//局部变量必须final修饰才能被内部类使用int c=2;//局部变量只赋值一次,被局部内部类使用,编译时会加上finalint d=5;d=6;//被再次赋值,编译时不会加上final,所以不能被局部内部类使用new Thread(new Runnable(){public void run(){System.out.println(a);System.out.println(b);System.out.println(c);//System.out.println(d); }}).start();}
}//Variable 'a' is accessed from within inner class, needs to be final or effectively final

注: 局部内部类中使用外部类对象 外部类名.this 即可。

首先需要知道的一点是:内部类和外部类是处于同一个级别的,内部类不会因为定义在方法中就会随着方法的执行完毕就被销毁。

这里就会产生问题:当外部类的方法结束时,局部变量就会被销毁了,但是内部类对象可能还存在(只有没有人再引用它时,才会死亡)。这里就出现了一个矛盾:内部类对象访问了一个不存在的变量。为了解决这个问题,就将局部变量复制了-份作为内部类的成员变量,这样当局部变量死亡后,内部类仍可以访问它,实际访问的是局部变量的"copy"。这样就好像延长了局部变量的生命周期

将局部变量复制为内部类的成员变量时,必须保证这两个变量是一样的, 也就是如果我们在内部类中修改了成员变量,方法中的局部变量也得跟着改变,怎么解决问题呢?

就将局部变量设置为final,对它初始化后,我就不让你再去修改这个变量,就保证了内部类的成员变量和方法的局部变量的一致性。这实际上也是一种妥协。使得局部变量与内部类内建立的拷贝保持一致。

6、String、StringBuffer、StringBuilder 区别及使用场景

  • String是final修饰的,不可变,每次操作都会产生新的String对象

  • StringBuffer和StringBuilder都是在原对象上操作

  • StringBuffer是线程安全的,StringBuilder线程不安全的

//StringBuilder 类
@Override
public StringBuilder append(CharSequence s) {    super.append(s);    return this;
}
@Override
public AbstractStringBuilder append(CharSequence s) {    if (s == null)        return appendNull();    if (s instanceof String)        return this.append((String)s);    if (s instanceof AbstractStringBuilder)        return this.append((AbstractStringBuilder)s);    return this.append(s, 0, s.length());
}
  • StringBuffer方法都是synchronized修饰的
//  StringBuffer 类
@Override
public synchronized StringBuffer append(Object obj) {               toStringCache = null;        super.append(String.valueOf(obj));        return this;
}
  • 性能: StringBuilder > StringBuffer > String
  • 场景:经常需要改变字符串内容时使用后面两个
  • 优先使用StringBuilder,多线程使用共享变量时使用StringBuffer

7、重载和重写

  • 重载:发生在同一 个类中,方法名必须相同,参数类型不同、个数不同、顺序不同,方法返回值和访问修饰符可
    以不同,发生在编译时。
  • 重写:发生在父子类中,方法名参数列表必须相同,返回值范围小于等于父类,抛出的异常范围小于等于父
    类,访问修饰符范围大于等于父类;如果父类方法访问修饰符为private则子类就不能重写该方法
public int add(int a,String b)
public String add(int a,String b)//编译报错

8、接口和抽象类区别

  1. 抽象类可以存在普通成员函数,而接口中只能存在public abstract方法。
  2. 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型的。
  3. 抽象类只能继承一个,接口可以实现多个。
  • 接口的设计目的,是对类的行为进行约束(更准确的说是一种"有“约束, 因为接口不能规定类不可以有什么行为), 也就是提供一种机制,可以强制要求不同的类具有相同的行为。它只约束了行为的有无,但不对如何实现行为进行限制。
  • 而抽象类的设计目的,是代码复用。当不同的类具有某些相同的行为(记为行为集合A),且其中一部分行为的实现方式一致时(A的非真子集,记为B),可以让这些类都派生于一个抽象类。 在这个抽象类中实现了B,避免让所有的子类来实现B,这就达到了代码复用的目的。而A减B的部分,留给各个子类自己实现。正是因为A-B在这里没有实现,所以抽象类不允许实例化出来(否则当调用到A-B时,无法执行)。
  • 抽象类是对类本质的抽象,表达的是is a的关系,比如: BMW is a Car。抽象类包含并实现子类的通用特性,将子类存在差异化的特性进行抽象,交由子类去实现。
  • 而接口是对行为的抽象,表达的是like a的关系。比如: Bird like a Aircraft (像飞行器一样可以飞) ,但其本质上is a Bird。接口的核心是定义行为,即实现类可以做什么,至于实现类主体是谁、是如何实现的,接口并不关心。

使用场景:当你关注一个事物的本质的时候, 用抽象类;当你关注一个操作的时候,用接口。

抽象类的功能要远超过接口,但是,定义抽象类的代价高。因为高级语言来说(从实际设计上来说也是)每个类只能继承一个类。在这个类中,你必须继承或编写出其所有子类的所有共性。虽然接口在功能上会弱化许多,但是它只是针对一个动作的描述。而且你可以在一个类中同时实现多个接口。在设计阶段会降低难度

9、List 和Set

  • List:有序,按对象进入的顺序保存对象,可重复,允许多个Null元素对象,可以使用Iterator取出所有元素,在逐一遍历,还可以使用get(int index)获取指定下表的元素
  • Set:无序,不可重复,最多允许有一个Null元索对象, 取元索时只能用lterator接口取得所有元素,在逐一遍历各个元素

10、HashCode 与 equals

hashCode()的作用是获取哈希码,也称为散列码,它实际上是返回的一个int整数。这个哈希码的作用是确定该对象在哈希表中的索引位置。hashCode( 定义在JDK的Object.java中,Java中的任何类都包含有hashCode()函数。散列表存储的是键值对(key-value),它的特点是:能根据”键“快速的检索出对应的”值”。这其中就利用到了散列码! (可以快速找到所需要的对象)

为什么要有hashCode?

以"HashSet如何检查重复”为例子来说明为什么要有hashCode:

对象加入HashSet时,HashSet会先计算对象的hashcode值来判断对象加入的位置, 看该位置是否有值,如果没有、HashSet会假设对象没有重复出现。但是如果发现有值,这时会调用equals ()方法来检查两个对象是否真的相同。如果两者相同,HashSet就不会让其加入操作成功。如果不同的话,就会重新散列到其他位置。这样就大大减少了equals的次数,相应就大大提高了执行速度。

  • 如果两个对象相等,则hashcode一定也是相同的
  • 两个对象相等对两个对象分别调用equals方法都返回true
  • 两个对象有相同的hashcode值,它们也不一定是相等的
  • 因此,equals方法被覆盖过, 则hashCode方法也必须被覆盖
  • hashCode()的默认行为是对堆上的对象产生独特值。如果没有重写hashCode(),则该class的两个对象无论如何都不会相等(即使这两个对象指向相同的数据)

11、ArrayList和LinkedList区别

  • ArrayList:基于动态数组,连续内存存储,适合下标访问(随机访问),扩容机制:因为数组长度固定,超出长度存数据时需要新建数组,然后将老数组的数据拷贝到新数组,如果不是尾部插入数据还会涉及到元素的移动(往后复制一份,插入新元素),使用尾插法并指定初始容量可以极大提升性能、甚至超过linkedList (需要创建大量的node对象)

  • LinkedList:基于链表,可以存储在分散的内存中,适合做数据插入及删除操作,不适合查询:需要逐一遍历。

    遍历LinkedList必须使用iterator不能使用for循环,因为每次for循环体内通过get()取得某-元素时都需要对list重新进行遍历,性能消耗极大。

    另外不要试图使用indexOf等返回元素索引,并利用其进行遍历,使用indexIOf对list进行 了遍历,当结果为空时会遍历整个列表。

12、HashMap和HashTable的区别?底层实现是什么?

1.区别:

  • (1) HashMap方法没有synchronized修饰, 线程非安全,HashTable线程安全;
  • (2) HashMap允许key和value为null,而HashTable不允许

2.底层实现:数组+链表实现

jdk8开始链表高度到8、数组长度超过64,链表转变为红黑树,元素以内部类Node节点存在

  • 计算key的hash值,二次hash然后对数组长度取模,对应到数组下标,

  • 如果没有产生hash冲突(下标位置没有元素),则直接创建Node存入数组,

  • 如果产生hash冲突,先进行equal比较,相同则取代该元素,不同,则判断链表高度插入链表,链表高度达到8,并且数组长度到64则转变为红黑树,长度低于6则将红黑树转回链表

  • key为null, 存在下标0的位置

3.数组扩容

当底层数组长度部够时,数组会根据扩容因子,进行扩容。

13、ConcurrentHashMap 原理,JDK7 和JDK8 区别

jdk7:

数据结构: ReentrantLock+Segment+HashEntry,一个Segment(分段)中包含一个HashEntry数组, 每个HashEntry又是一个链表结构

元素查询:二次hash,第一次Hash定位到Segment, 第二次Hash定位到元素所在的链表的头部

锁: Segment分段锁Segment继承了ReentrantLock,锁定操作的Segment,其他的Segment不受影响, 并发度为segment个数,可以通过构造函数指定,数组扩容不会影响其他的segment

get方法无需加锁,volatile保证

jdk8:

数据结构: synchronized+CAS+Node+红黑树, Node的val和next都用volatile修饰, 保证可见性

查找,替换,赋值操作都使用CAS

锁:锁链表的head节点,不影响其他元素的读写,锁粒度更细,效率更高,扩容时,阻塞所有的读写操作、并发扩容

读操作无锁:

Node的val和next使用volatile修饰,读写线程对该变量互相可见

数组用volatile修饰,保证扩容时被读线程感知

14、如何实现一个IOC容器

  1. 配置文件配置包扫描路径
  2. 递归包扫描获取.class文件
  3. 反射、确定需要交给I0C管理的类
  4. 对需要注入的类进行依赖注入
  • 配置文件中指定需要扫描的包路径
  • 定义一些注解,分别表示访问控制层、业务服务层、数据持久层、依赖注入注解、获取配置文件注解
  • 从配置文件中获取需要扫描的包路径,获取到当前路径下的文件信息及文件夹信息,我们将当前路径下所有以.class结尾的文件添加到一个Set集合中进行存储
  • 遍历这个set集合,获取在类上有指定注解的类,并将其交给IOC容器,定义一个安全的Map用来存储这些对象
  • 遍历这个IOC容器,获取到每一 个类的实例,判断里面是有有依赖其他的类的实例,然后进行递归注入

15、什么是字节码?采用字节码的好处是什么?

java中的编译器和解释器:

Java中引入了虚拟机的概念,即在机器和编译程序之间加入了一层抽象的虚拟的机器。这台虚拟的机器在任何平台上都提供给编译程序一个的共同的接口。

编译程序只需要面向虚拟机,生成虚拟机能够理解的代码,然后由解释器来将虚拟机代码转换为特定系统的机器码执行。在Java中,这种供虚拟机理解的代码叫做字节码(即扩展名为.class的文件),它不面向任何特定的处理器,只面向虚拟机。

每一种平台的解释器是不同的,但是实现的虚拟机是相同的。Java源程序经过编译器编译后变成字节码,字节码由虛拟机解释执行,虚拟机将每一条要执行的字节码送给解释器, 解释器将其翻译成特定机器上的机器码,然后在特定的机器上运行。这也就是解释了Java的编译与解释并存的特点。

Java源代码—>编译—>jvm可执行的Java字节码(即虚拟机指令)---->jvm中解释器---->机器可执行的二进制机器码—>程序运行。

采用字节码的好处:

Java语言通过字节码的方式,在一定程度上解决了传统解释型语言执行效率低的问题,同时又保留了解释型语言可移植的特点。所以ava程序运行时比较高效,而且,由于字节码并不专对一种特定的机器,因此,Java程序无须重新编译便可在多种不同的计算机上运行。

16、Java 类加载器有哪些?

JDK 自带三个类加载器:

  1. Bootstrap class loader (BootstrapClassLoader) 引导类加载器

    BootstrapClassLoader 是ExtClassLoader的父 类加载器(非继承关系),负责加载jre\lib路径下的jar包和class文件。

  2. extension class loader(ExtClassLoader)扩展类加载器

    ExtClassLoader是AppClassLoader的父 类加载器(非继承关系),负责加载jre\lib\ext路径下的jar包和class文件。

  3. application class loader (AppClassLoader) 系统类加载器

    AppClassLoader 负责加载classpath 下的jar和class文件

BootstrapClassLoader是用C/C++编写的;而ExtClassLoader和AppClassLoader都继承自ClassLoader类,属于自定义类加载器。

17、双亲委派(托)模型

  1. 如果一个类加载器收到了类加载请求,它并不会自己先去加载,而是把这个请求委托给父类加载器去执行。
  2. 如果父类加载器还存在父类加载器,则进一步向上委托给父类加载器,一次递归,请求最终到达顶层引导类加载器。
  3. 如果父类加载器可以完成类加载任务,就成功返回;如果父类加载器无法完成此加载任务,则交由子类加载器自己去加载。

双亲委派的好处:

  • 主要是为了安全性,避免用户自己编写的类动态替换java的一些核心类,比如String。
  • 同时也避免了类的重复加载,因为JVM中区分不同类,不仅仅是根据类名,相同的class文件被不同的ClassLoader加载就是不同的两个类。

18、java 中的异常体系

java中的所有异常都来自顶级父类Throwable。

Throwable下有两个子类Exception和Error。

Error是程序无法处理的错误,一旦出现这个错误,则程序将被迫停止运行。

Exception不会导致程序停止,又分为两个部分RuntimeException运行时异常和CheckException检查异常。

RuntimeException常常发生在程序运行过程中,会导致程序当前线程执行失败。

CheckedException常常发生在程序编译过程中,会导致程序编译不通过。

19、GC 如何判断对象可以被回收?

  • 引用计数法:每一个对象有一个引用计数属性,当新增一个引用时计数加1,引用释放时计数减1,计数为0时可以回收。
  • 可达性分析法:从GC Roots 开始向下搜索,搜索所走过的路径称为引用链。当一个对象到GC Roots 没有任何引用链相连时,则此对象时不可用的,那么虚拟机就判断此对象是可回收对象。

引用计数法,可能会出现A引用B,B又引用A,这个时候就算他们不再被使用,但因为他们相互引用着,计数器的值=1,所以他们将永远无法被回收。

GC Roots的对象有:

  • 虚拟机栈(栈帧中的局部变量表)中引用的对象
  • 方法区中类静态属性引用的对象
  • 方法区中常量引用的对象
  • 本地方法栈中JNI(即一般说的Native方法)引用的对象
  • 所以被同步锁Synchronized持有的对象
  • Java虚拟机内部的引用(基本数据类型对应的Class对象、常驻异常对象、系统类加载器)
  • 反映虚拟机内部情况的JMXBean、JVMTI中注册的回调、本地代码缓存等。

可达性分析法中的不可达对象并不是立即死亡的,对象拥有一次自我拯救的机会。对象被系统回收至少要经历两次标记过程:第一是经过可达性分析发现没有与GC Roots 相连接的引用链,第二次是在虚拟机自动建立的Finalizer 队列中判断是否需要执行finalize()方法。

当对象变成(GC Roots)不可达时,GC 判断对象是否覆盖了finalize()方法,若未覆盖,则直接回收;否则,若对象未执行过finalize()方法,将其放入F-Queue队列,由一个低优先级线程执行该队列中的对象的finalize()方法。执行finalize()方法完毕后,GC 会再次判断该对象是否可达,若不可达,则进行回收,否则,对象复活。(对象在finalize()方法中可以通过与存活对象建立引用链接,来自我拯救一次)

每个对象的finalize()方法只能触发一次。

由于finalize()方法运行代价高昂,不确定性大,无法保证各个对象的调用顺序,不推荐大家使用。

20、线程的生命周期,线程有哪些状态?

public enum State {       /**         * Thread state for a thread which has not yet started.         * */        NEW,        /**         * Thread state for a runnable thread.  A thread in the runnable          * state is executing in the Java virtual machine but it may         * be waiting for other resources from the operating system         * such as processor.         */        RUNNABLE,       /**         * Thread state for a thread blocked waiting for a monitor lock.         *  A thread in the blocked state is waiting for a monitor lock         *  to enter a synchronized block/method or         *  reenter a synchronized block/method after calling         *  {@link Object#wait() Object.wait}.         */        BLOCKED,        /**         *   Thread state for a waiting thread.         * * A thread is in the waiting state due to calling one of the         * * following methods:         * * <ul>         * *   <li>{@link Object#wait() Object.wait} with no timeout</li>         * *   <li>{@link #join() Thread.join} with no timeout</li>         * *   <li>{@link LockSupport#park() LockSupport.park}</li>         * * </ul>         * *         * * <p>A thread in the waiting state is waiting for another thread to         * * perform a particular action.         * *         * * For example, a thread that has called <tt>Object.wait()</tt>         * * on an object is waiting for another thread to call         * * <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on         * * that object. A thread that has called <tt>Thread.join()</tt>         * * is waiting for a specified thread to terminate.         */        WAITING,        /**         * Thread state for a waiting thread with a specified waiting time.         * * A thread is in the timed waiting state due to calling one of         * * the following methods with a specified positive waiting time:         * * <ul>         * *   <li>{@link #sleep Thread.sleep}</li>         * *   <li>{@link Object#wait(long) Object.wait} with timeout</li>         * *   <li>{@link #join(long) Thread.join} with timeout</li>         * *   <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>         * *   <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>         * * </ul>         */        TIMED_WAITING,        /**         * Thread state for a terminated thread.         * * The thread has completed execution.         */        TERMINATED;    }
  1. 线程通常有五种状态,创建,就绪,运行、阻塞和死亡状态。

  2. 阻塞的情况又分为三种:

    (1)、等待阻塞:运行的线程执行wait方法,该线程会释放占用的所有资源,JVM会把该线程放入“等待池”中。进入这个状态后,是不能自动唤醒的,必须依靠其他线程调用notify或notifyAll方法才能被唤醒,wait是object类的方法。

    (2)、同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则VM会把该线程放入“锁池”中。

    (3)、其他阻塞:运行的线程执行sleep或join方法,或者发出了I/0请求时,JVM会把该线程置为阻塞状态。当sleep状态超时、join等待线程终 止或者超时、或者I/O处理完毕时, 线程重新转入就绪状态。sleep是Thread类的方法。

  • 1.新建状态(New) :新创建了一个线程对象。
  • 2.就绪状态(Runnable) :线程对象创建后,其他线程调用了该对象的start方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。
  • 3.运行状态(Running) :就绪状态的线程获取了CPU,执行程序代码。
  • 4.阻塞状态(Blocked) :阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。
  • 5.死亡状态(Dead) :线程执行完了或者因异常退出了run方法,该线程结束生命周期。

21、sleep()、wait()、join()、yield()的区别

  1. 锁池

    所有需要竞争同步锁的线程都会放在锁池当中,比如当前对象的锁已经被其中一个线程得到,则其他线程需要在这个锁池进行等待,当前面的线程释放同步锁后锁池中的线程会去竞争同步锁,当某个线程得到后会进入就绪队列进行等待CPU资源分配。

  2. 等待池

    当我们调用wait()方法后,线程会放到等待池当中,等待池的线程是不会去竞争同步锁。只有调用了notify()或notifyall()后等待池的线程才会开始去竞争锁,notify()是随机从等待池选出一个线程放到锁池,而notifyall()是将等待池的所有线程放到锁池当中。

  • sleep是Thread类的静态本地方法,wait是Object类的本地方法。

  • sleep方法不会释放锁;wait 会释放锁,而且会加入到等待队列中。

    sleep 就是把CPU的执行资格和执行权释放出去,不再运行此线程,当定时时间结束再取回CPU资源,参与CPU的调度,获取到CPU资源后就可以继续运行了。而如果sleep时该线程有锁,那么sleep不会释放锁,而是把锁带着进入冻结状态,也就是锁其他需要这个锁的线程根本不可能获取到这个锁。如果在睡眠期间其他线程调用了这个线程的interrupt方法,那么这个线程也会抛出interruptexception异常返回。这点和wait是一样的。

  • sleep方法不依赖于同步器synchronized,但是wait需要依赖synchronized 关键字。

  • sleep不需要被唤醒(休眠之后推出阻塞),但是wait需要(不指定时间需要被别人中断)。

  • sleep一般用于当前线程休眠,或者轮询暂停操作,wait则多用于多线程之间的通信。

  • sleep会让出CPU执行时间且强制上下文切换,而wait则不一定,wait后可能还是有机会重新竞争到锁继续执行的。

yield()执行后线程直接进入就绪状态,马上释放了CPU的执行权,但是依然保留了CPU的执行资格,所以有可能CPU下次进行线程调度还会让这个线程获取到执行权继续执行。

join()执行后线程进入阻塞状态,例如在线程B中调用线程A的join,那线程B 会进入到阻塞队列,直到线程A结束或中断线程。

public static void main(String[] args) throws InterruptedException { Thread a = new Thread(() -> {            System.out.println("A开始");            try {                Thread.sleep(1000);           } catch (InterruptedException e) {                  e.printStackTrace();           }            System.out.println("A结束");        }, "A");        a.start();        a.join();//main线程阻塞等待A线程执行结束或中断 System.out.println("main结束");    }//输出结果A开始A结束main结束

22、说说你多线程安全的理解

不是线程安全、应该是内存安全,堆是共享内存,可以被所有线程访问

当多个线程访问一个对象时,如果不用进行额外的同步控制或其他的协调操作,调用这个对象的行为都可以获得正确的结果,我们就说这个对象是线程安全的

是进程和线程共有的空间,分全局堆和局部堆。全局堆就是所有没有分配的空间,局部堆就是用户分配的空间。堆在操作系统对进程初始化的时候分配,运行过程中也可以向系统要额外的堆,但是用完了要还给操作系统,要不然就是内存泄漏。

在Java中,堆是Java虚拟机所管理的内存中最大的一块,是所有线程共享的一块内存区域,在虚拟机启动时创建。堆所存在的内存区域的唯一目的就是存放对象实例, 几乎所有的对象实例以及数组都在这里分配内存。

是每个线程独有的,保存其运行状态和局部自动变量的。栈在线程开始的时候初始化,每个线程的栈互相独立,因此,栈是线程安全的。操作系统在切换线程的时候会自动切换栈。栈空间不需要在高级语言里面显式的分配和释放。

目前主流操作系统都是多任务的,即多个进程同时运行。为了保证安全,每个进程只能访问分配给自己的内存空间,而不能访问别的进程的,这是由操作系统保障的。

在每个进程的内存空间中都会有一块特殊的公共区域,通常称为堆(内存)。进程内的所有线程都可以访问到该区域,这就是造成问题的潜在原因。

23、Thread 和Runnable的区别

Runnable 是一个接口,Thread是一个实现了Runnable接口的类,他们的实质是继承关系。使用上类只能继承一个,接口可以实现多个。

无论使用Runnable还是Thread,都要new Thread,然后执行run方法。用法上,如果有复杂的线程操作需求,那就选择继承Thread,如果只是简单的执行一个任务, 那就实现runnable。

24、说说你对守护线程的理解

守护线程:为所有非守护线程提供服务的线程;任何一个守护线程都是整个VM中所有非守护线程的保姆;

守护线程类似于整个进程的一个默默无闻的小喽喽; 它的生死无关重要,它却依赖整个进程而运行;哪天其他线程结束了,没有要执行的了,程序就结束了,理都没理守护线程,就把它中断了;

注意:由于守护线程的终止 是自身无法控制的,因此千万不要把I0、File等重要操作逻辑分配给它;因为它不靠谱;

守护线程的作用是什么?

举例,GC垃圾回收线程: 就是一个经典的守护线程,当我们的程序中不再有任何运行的Thread,程序就不会再产生垃圾,垃圾回收器也就无事可做,所以当垃圾回收线程是JVM.上仅剩的线程时,垃圾回收线程会自动离开。它始终在低级别的状态中运行,用于实时监控和管理系统中的可回收资源。

应用场景: (1) 来为其它线程提供服务支持的情况; (2) 或者在任何情况下, 程序结束时,这个线程必须正常且立刻关闭,就可以作为守护线程来使用;反之,如果一个正在执行某个操作的线程必须要正确地关闭掉否则就会出现不好的后果的话,那么这个线程就不能是守护线程,而是用户线程。通常都是些关键的事务,比方说,数据库录入或者更新,这些操作都是不能中断的。

thread.setDaemon(true)必须在thread.start()之前设置,否则会跑出一个llegalThreadStateException异常。 你不能把正在运行的常规线程设置为守护线程。

在Daemon线程中产生的新线程也是Daemon的。

守护线程不能用于去访问固有资源,比如读写操作或者计算逻辑。因为它会在任何时候甚至在一个操作的中间发生中断。

Java自带的多线程框架,比如ExecutorService, 会将守护线程转换为用户线程,所以如果要使用后台线程就不能java 的线程池。

25、Threadlocal 的原理和使用场景

每一个Thread对象均含有一个ThreadLocalMap类型的成员变量threadLocals,它存储本线程中所有ThreadLocal对象及其对应的值

ThreadLocalMap由一个个Entry对象构成

Entry继承自WeakReference<ThreadLoca1<?>>,一个Entry由ThreadLocal对象和object构成。由此可见,Entry 的key是ThreadLocal对象,并且是一个弱引用。 当没指向key的强引用后, 该key就会被垃圾收集器回收

当执行set方法时,ThreadLocal首先会获取当前线程对象,然后获取当前线程的ThreadLocalMap对象。再以当前ThreadLocal对象为key,将值存储进ThreadLocalMap对象中。

get方法执行过程类似。ThreadLocal首先会获取当前线程对象, 然后获取当前线程的ThreadLocalMap对象。再以当前ThreadLocalI对象为key,获取对应的value。

由于每一条线程均含有各 自私有的ThreadLocalMap容器,这些容器相互独立互不影响,因此不会存在线程安全性问题,从而也无需使用同步机制来保证多条线程访问容器的互斥性。

使用场景:

1、在进行对象跨层传递的时候,使用ThreadLocal可以避免多次传递,打破层次间的约束。

2、线程间数据隔离

3、进行事务操作,用于存储线程事务信息。

4、数据库连接,Session会话管理。

Spring框架在事务开始时会给当前线程绑定-个JdbcConnection,在整个事务过程都是使用该线程绑定的connection来执行数据库操作,实现了事务的隔离性。Spring框架里面就是用的ThreadLocal来实现这种隔离

26、ThreadLocal 内存泄漏的原因及如何避免

内存泄露为程序在申请内存后,无法释放已申请的内存空间,- -次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。

不再会被使用的对象或者变量占用的内存不能被回收,就是内存泄露。

**强引用:**使用最普遍的引用(new), -个对象具有强引用,不会被垃圾回收器回收。当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不回收这种对象。

如果想取消强引|用和某个对象之间的关联,可以显式地将引用赋值为null,这样可以使JVM在合适的时间就会回收该对象。

弱引用: JVM进行垃圾回收时,无论内存是否充足,都会回收被弱引用关联的对象。在java中, 用java.lang.re.WeakReference类来表示。可以在缓存中使用弱引用。

ThreadLocal 的实现原理,每一个Thread维护一个ThreadlocalMap ,key为使用弱引用的ThreadLocal实例,value为线程变量的副本。

ThreadLocalMap使用ThreadLocal的弱引用作为key,如果一个ThreadLocal不存在外部强引用时,Key(ThreadLocal)势必会被GC回收,这样就会导致ThreadLocalMap中key为null,而value还存在着强引用, 只有thead线程退出以后,value的强引用链条才会断掉,但如果当前线程再迟迟不结束的话,这些key为nul的Entry的value就会一直存在一 条强引用链(红色链条)

key使用强引用

当hreadLocalMap的key为强弓l用回收ThreadLocal时,因为ThreadLocalMap还持有 ThreadLocal的强引用,如果没有手动删除,ThreadLocal不会被回收, 导致Entry内存泄漏。

key使用弱引用

当ThreadLocalMap的key为弱弓l用回收ThreadLocal时,由于ThreadLocalMap持有 ThreadLocal的弱引用,即使没有手动删除,ThreadLocal也会被回收。 当key为null, 在下一-次ThreadLocalMap调用set),get(), remove(方法的时候会被清除value值。

因此,ThreadLocal内存泄漏的根源是:由于ThreadLocalMap的生命周期跟Thread-样长,如果没有手动删除对应key就会导致内存泄漏,而不是因为弱引用。

ThreadLocal正确的使用方法

  • 每次使用完ThreadLocal都调用它的remove()方法清除数据
  • 将ThreadLocal变量定义成private static,这样就一直存在ThreadLocal的强引用, 也就能保证任何时候都能通过ThreadLocal的弱引|用访问到Entry的value值,进而清除掉。

27、并发、并行、串行的区别

串行在时间.上不可能发生重叠,前一个任务没搞定,下一 个任务就只能等着

并行在时间上是重叠的,两个任务在同一时刻互不干扰的同时执行。

并发允许两个任务彼此干扰。统-时间点、只有一个任务运行, 交替执行

28、并发的三大特性

  • 原子性

    原子性是指在一个操作中cpu不可以在中途暂停然后再调度, 即不被中断操作,要不全部执行完成,要不都不执行。就好比转账,从账户A向账户B转1000元,那么必然包括2个操作:从账户A减去1000元,往账户B加上1000元。2个操作必须全部完成。

    private 1ong count = 0;pub1ic void ca1c() {count++;}
    
    • 1:将count从主存读到工作内存中的副本中

    • 2: +1的运算

    • 3:将结果写入工作内存

    • 4:将工作内存的值刷回主存(什么时候刷入由操作系统决定,不确定的)

    那程序中原子性指的是最小的操作单元,比如自增操作,它本身其实并不是原子性操作,分了3步的,包括读取变量的原始值、进行加1操作、写入工作内存。所以在多线程中,有可能一个线程还没自增完, 可能才执行到第二部,另一个线程就已经读取了值,导致结果错误。那如果我们能保证自增操作是一个原子性的操作, 那么就能保证其他线程读取到的一定是自增后的数据。

    关键字:synchronized

  • 可见性

    当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值。

    若两个线程在不同的cpu,那么线程1改变了i的值还没刷新到主存,线程2又使用了i,那么这个i值肯定还是之前的,线程1对变量的修改线程没看到这就是可见性问题。

    //线程1boolean stop=false;while(!stop){    doSomething();}//线程2stop=true;
    

    如果线程2改变了stop的值,线程1-定会停止吗?不一定。当线程2更改了stop变量的值之后,但是还没来得及写入主存当中,线程2转去做其他事情了.那么线程1由于不知道线程2对stop变量的更改,因此还会一直循环下去。

    关键字:volatile、synchronized、final

  • 有序性

    虚拟机在进行代码编译时,对于那些改变顺序之后不会对最终结果造成影响的代码,虛拟机不一定会按照我们写的代码的顺序来执行,有可能将他们重排序。实际上,对于有些代码进行重排序之后,虽然对变量的值没有造成影响,但有可能会出现线程安全问题。

    int a = 0;
    boolean flag = false;
    pub1ic void write() {   a = 2; //1 flag = true;   //2
    }
    pub1ic void mu1tip1y() {    if (f1ag) {//3      int ret = a*a;//4    }
    }
    

    write方法里的1和2做了重排序,线程1先对flag赋值为true,随后执行到线程2,ret直接计算出结果,再到线程write方法里的1和2做了重排序,线程1先对flag赋值为true, 随后执行到线程2,ret直接计算出结果,再到线程
    1,这时候a才赋值为2,很明显迟了一步

    关键字: volatile、 synchronized

    volatile本身就包含了禁止指令重排序的语义.而svnchronized关 键字是由“一个变量在同一-时刻只允许一条线程对其进行lock操作"这条规则明确的。

    synchronized关键字同时满足以上三种特性,但是volatile关键字不满足原子性。

    在某些情况下,volatile的同步机制的性能确实要优于锁(使用synchronized关键字或java.util.concurrent包里面的锁)因为volatile总的开销要比锁低

29、为什么用线程池?解释一下线程池参数?

public ThreadPoolExecutor(int corePoolSize, //线程池核心线程数                              int maximumPoolSize,//线程池最大线程数                              long keepAliveTime,//超出核心线程数外空闲线程存活时间  TimeUnit unit,//空闲线程存活时间单位 BlockingQueue<Runnable> workQueue, //等待任务队列 ThreadFactory threadFactory,//线程工厂RejectedExecutionHandler handler//任务拒绝策略
)
  1. 降低资源消耗;提高线程利用率,降低创建和销毁线程的消耗。

  2. 提高响应速度;任务来了,直接有线程可用可执行,而不是先创建线程,再执行。

  3. 提高线程的可管理性;线程是稀缺资源,使用线程池可以统一分配调优监控。

  • corePoolsize代表核心线程数,也就是正常情况下创建工作的线程数,这些线程创建后并不会消除,而是一种常驻线程
  • maxinumPoo1size 代表的是最大线程数,它与核心线程数相对应,表示最大允许被创建的线程数,比如当前任务较多,将核心线程数都用完了,还无法满足需求时,此时就会创建新的线程,但是线程池内线程总数不会超过最大线程数
  • keepAliveTime、 unit表示超出核心线程数之外的线程的空闲存活时间,也就是核心线程不会消除,但是超出核心线程数的部分线程如果空闲一定的时间则会被消除,我们可以通过setKeepAliveTime 来设置空闲时间
  • workQueue 用来存放待执行的任务,假设我们现在核心线程都已被使用,还有任务进来则全部放入队列,直到整个队列被放满但任务还再持续进入则会开始创建新的线程
  • ThreadFactory实际上是一个线程工厂,用来生产线程执行任务。我们可以选择使用默认的创建工厂,产生的线程都在同一个组内,拥有相同的优先级,且都不是守护线程。当然我们也可以选择自定义线程工厂,一般我们会根据业务来制定不同的线程工厂
  • Handler任务拒绝策略,有两种情况,第一种是当我们调用shutdown等方法关闭线程池后,这时候即使线程池内部还有没执行完的任务正在执行,但是由于线程池已经关闭,我们再继续想线程池提交任务就会遭到拒绝。另一种情况就是当达到最大线程数,线程池已经没有能力继续处理新提交的任务时,这是也就拒绝
//四种拒绝策略
new ThreadPoolExecutor.AbortPolicy();//默认,池满了(包括等待队列也满了),直接拒绝任务,并抛异常
new ThreadPoolExecutor.DiscardPolicy();//池满了(包括等待队列也满了),直接拒绝任务,不抛异常
new ThreadPoolExecutor.DiscardOldestPolicy();//池满了(包括等待队列也满了),新任务尝试和最未执行的最老的任务竞争,不抛异常
new ThreadPoolExecutor.CallerRunsPolicy();//池满了(包括等待队列也满了),拒绝并交给任务提交线程执行任务

30、简述线程池处理流程

Created with Raphaël 2.3.0 接收提交的任务 核心数是否已满(是or否?) 任务队列是否已满(是or否?) 最大线程数是否到达(是or否?) 拒绝策略处理 创建临时线程执行任务 将任务放入任务队列 核心线程执行任务 yes no yes no yes no

31、线程池中阻塞队列的作用?为什么是先添加列队而不是先创建最大线程?

1、-般的队列只能保证作为-个有限长度的缓冲区,如果超出了缓冲长度,就无法保留当前的任务了,阻塞队列通过阻塞可以保留住当前想要继续入队的任务。

阻塞队列可以保证任务队列中没有任务时阻塞获取任务的线程,使得线程进入wait状态,释放cpu资源。

阻塞队列自带阻塞和唤醒的功能,不需要额外处理,无任务执行时,线程池利用阻塞队列的take方法挂起,从而维持核心线程的存活、不至于-直 占用cpu资源

2、在创建新线程的时候,是要获取全局锁的,这个时候其它的就得阻塞,影响了整体效率。

就好比一个企业里面有10个(core) 正式工的名额,最多招10个正式工,要是任务超过正式工人数(task>core)的情况下,厂领导(线程池)不是首先扩招工人,还是这10人,但是任务可以稍微积压一下, 即先放到队列去(代价低)。10个正式工慢慢干,迟早会干完的,要是任务还在继续增加,超过正式工的加班忍耐极限了(队列满了),就的招外包帮忙了(注意是临时工)要是正式工加,上外包还是不能完成任务,那新来的任务就会被领导拒绝了(线程池的拒绝策略)。

32、线程池中线程复用的原理

线程池将线程和任务进行解耦,线程是线程,任务是任务,摆脱了之前通过Thread创建线程时的一个线程必须对应-一个任务的限制。

在线程池中,同一个线程可以从阻塞队列中不断获取新任务来执行,其核心原理在于线程池对Thread进行了封装,并不是每次执行任务都会调用Thread.start()来创建新线程,而是让每个线程去执行一个“循环任务”, 在这个“循环任务”中不停检查是否有任务需要被执行,如果有则直接执行,也就是调用任务中的run方法,将run方法当成一个普通的方法执行,通过这种方式只使用固定的线程就将所有任务的run方法串联起来。

33、spring是什么?

轻量级的开源的J2EE框架。它是一个容器框架, 用来装javabean (java对象) ,中间层框架(万能胶)可以起一个连接作用,比如说把Struts和hibernate粘合在一 起运用, 可以让我们的企业开发更快、更简洁

Spring是一个轻量级的控制反转(IoC)和面向切面(AOP) 的容器框架

  • 从大小与开销两方面而言Spring都是轻量级的。
  • 通过控制反转(loC)的技术达到松耦合的目的
  • 提供了面向切面编程的丰富支持,允许通过分离应用的业务逻辑与系统级服务进行内聚性的开发
  • 包含并管理应用对象(Bean)的配置和生命周期,这个意义上是一个容器。
  • 将简单的组件配置、组合成为复杂的应用,这个意义上是一个框架。

34、AOP

系统是由许多不同的组件所组成的,每一个组件各负责一块特定功能。除了实现自身核心功能之外,这些组件还经常承担着额外的职责。例如日志、事务管理和安全这样的核心服务经常融入到自身具有核心业务逻辑的组件中去。这些系统服务经常被称为横切关注点,因为它们会跨越系统的多个组件。

当我们需要为分散的对象引入公共行为的时候,OOP则显得无能为力。也就是说,OOP允许你定义从上到下的关系,但并不适合定义从左到右的关系。例如日志功能。

日志代码往往水平地散布在所有对象层次中,而与它所散布到的对象的核心功能毫无关系。

在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。

AOP: 将程序中的交叉业务逻辑(比如安全,日志,事务等),封装成一个切面,然后注入到目标对象(具体业务逻辑)中去。AOP可以对某个对象或某些对象的功能进行增强,比如对象中的方法进行增强,可以在执行某个方法之前额外的做一些事情,在某个方法执行之后额外的做一 些事情

35、谈谈你对IOC的理解

容器概念、控制反转、依赖注入

IOC容器:

实际上就是个map (kev, value) , 里面存的是各种对象(在xml里配置的bean节点、@repository、@service、@controller、@component), 在项目启动的时候会读取配置文件里面的bean节点,根据全限定类名使用反射创建对象放到map里、扫描到加了上述注解的类还是通过反射创建对象放到map里。

这个时候map里就有各种对象了,接下来我们在代码里需要用到里面的对象时,再通过DI注入(autowired.resource等注解,xml里bean节 点内的ref属性,项目启动的时候会读取xml|节点ref属性根据id注入,也会扫描这些注解,根据类型或id注入; id就是对象名)。

控制反转:

没有引入IOC容器之前,对象A依赖于对象B,那么对象A在初始化或者运行到某一点的时候, 自己必须主动去创建对象B或者使用已经创建的对象B。无论是创建还是使用对象B,控制权都在自己手上。

引入IOC容器之后,对象A与对象B之间失去了直接联系,当对象A运行到需要对象B的时候, IOC容器会主动创建一个对象B注入到对象A需要的地方。

通过前后的对比,不难看出来:对象A获得依赖对象B的过程,由主动行为变为了被动行为,控制权颠倒过来了,这就是"控制反转”这个名称的由来。

全部对象的控制权全部上缴给“第三方"IOC容器,所以,IOC容器成了整个系统的关键核心,它起到了一种类似“粘合剂”的作用,把系统中的所有对象粘合在一起发挥作用, 如果没有这个粘合剂”,对象与对象之间会彼此失去联系,这就是有人把IOC容器比喻成"粘合剂"的由来。

依赖注入:

“获得依赖对象的过程被反转了”。控制被反转之后,获得依赖对象的过程由自身管理变为由IOC容器主动注入。依赖注入是实现IOC的方法,就是由IOC容器在运行期间,动态地将某种依赖关系注入到对象中。

36、BeanFactory和ApplicationContext有什么区别

ApplicationContext 继承了BeanFactory,两者都是接口。

ApplicationContext 提供了更完整的功能:

  1. 继承MessageSource,支持国际化
  2. 统一的资源文件访问方式
  3. 提供在监听器中注册bean的事件
  4. 同时加载多个配置文件
  5. 载入多个(有继承关系)上下文,使得每一个上下文都专注于一个特定的层次,比如应用的web层。
  • BeanFactory采用的是延迟加载形式来注入Bean的,即只有在使用到某个Bean时(调用getBean()),才对该Bean进行加载实例化。这样,我们就不能发现一些存在的Spring的配置问题。如果Bean的某一个属性没有注入,BeanFactory加载后,直至第一次使用调用getBean()方法才会抛出异常。
  • ApplicationContext是在容器启动时,一次性创建所有的Bean。这样,在容器启动时,我们就可以发现spring 中存在的配置错误,这样有利于检查所依赖的属性是否已注入。ApplicationContext启动后预载入所有的单实例Bean,通过预载入单实例Bean,确保当你需要的时候,你就不用等待,因为他们已经被创建好了。
  • 相对于基本的BeanFactory,ApplicationContext唯一的不足时占用内存空间。当应用程序配置Bean较多时,程序启动较慢。
  • BeanFactory通常以编程的方式被创建,ApplicationContext 还能以声明的方法创建,如使用ContextLoader。
  • BeanFactory和ApplicationContext都支持BeanPostProcessor、BeanFactoryPostProcessor的使用,但两者之间的区别是:BeanFactory需要手动注册,而ApplicationContext则是自动注册。

37、Spring Bean的生命周期

  1. 解析类得到BeanDefinition
  2. 如果有多个构造方法,则要推断构造方法
  3. 确定好构造方法后,进行实例化得到一个对象
  4. 对对象中加了@Autowired注解的属性进行属性填充
  5. 回调Aware方法,比如BeanNameAware、BeanFactoryAware
  6. 调用BeanPostProcessor的初始化前的方法
  7. 调用初始化方法
  8. 调用BeanPostProcessor的初始化后的方法,在这里会进行AOP
  9. 如果当前创建的bean是单例的则会把bean放入单例池
  10. 使用bean
  11. spring容器关闭时调用DisposableBean中destroy()方法
#mermaid-svg-F4Y4w4pYfpPakI8b .label{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);fill:#333;color:#333}#mermaid-svg-F4Y4w4pYfpPakI8b .label text{fill:#333}#mermaid-svg-F4Y4w4pYfpPakI8b .node rect,#mermaid-svg-F4Y4w4pYfpPakI8b .node circle,#mermaid-svg-F4Y4w4pYfpPakI8b .node ellipse,#mermaid-svg-F4Y4w4pYfpPakI8b .node polygon,#mermaid-svg-F4Y4w4pYfpPakI8b .node path{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-F4Y4w4pYfpPakI8b .node .label{text-align:center;fill:#333}#mermaid-svg-F4Y4w4pYfpPakI8b .node.clickable{cursor:pointer}#mermaid-svg-F4Y4w4pYfpPakI8b .arrowheadPath{fill:#333}#mermaid-svg-F4Y4w4pYfpPakI8b .edgePath .path{stroke:#333;stroke-width:1.5px}#mermaid-svg-F4Y4w4pYfpPakI8b .flowchart-link{stroke:#333;fill:none}#mermaid-svg-F4Y4w4pYfpPakI8b .edgeLabel{background-color:#e8e8e8;text-align:center}#mermaid-svg-F4Y4w4pYfpPakI8b .edgeLabel rect{opacity:0.9}#mermaid-svg-F4Y4w4pYfpPakI8b .edgeLabel span{color:#333}#mermaid-svg-F4Y4w4pYfpPakI8b .cluster rect{fill:#ffffde;stroke:#aa3;stroke-width:1px}#mermaid-svg-F4Y4w4pYfpPakI8b .cluster text{fill:#333}#mermaid-svg-F4Y4w4pYfpPakI8b div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:12px;background:#ffffde;border:1px solid #aa3;border-radius:2px;pointer-events:none;z-index:100}#mermaid-svg-F4Y4w4pYfpPakI8b .actor{stroke:#ccf;fill:#ECECFF}#mermaid-svg-F4Y4w4pYfpPakI8b text.actor>tspan{fill:#000;stroke:none}#mermaid-svg-F4Y4w4pYfpPakI8b .actor-line{stroke:grey}#mermaid-svg-F4Y4w4pYfpPakI8b .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333}#mermaid-svg-F4Y4w4pYfpPakI8b .messageLine1{stroke-width:1.5;stroke-dasharray:2, 2;stroke:#333}#mermaid-svg-F4Y4w4pYfpPakI8b #arrowhead path{fill:#333;stroke:#333}#mermaid-svg-F4Y4w4pYfpPakI8b .sequenceNumber{fill:#fff}#mermaid-svg-F4Y4w4pYfpPakI8b #sequencenumber{fill:#333}#mermaid-svg-F4Y4w4pYfpPakI8b #crosshead path{fill:#333;stroke:#333}#mermaid-svg-F4Y4w4pYfpPakI8b .messageText{fill:#333;stroke:#333}#mermaid-svg-F4Y4w4pYfpPakI8b .labelBox{stroke:#ccf;fill:#ECECFF}#mermaid-svg-F4Y4w4pYfpPakI8b .labelText,#mermaid-svg-F4Y4w4pYfpPakI8b .labelText>tspan{fill:#000;stroke:none}#mermaid-svg-F4Y4w4pYfpPakI8b .loopText,#mermaid-svg-F4Y4w4pYfpPakI8b .loopText>tspan{fill:#000;stroke:none}#mermaid-svg-F4Y4w4pYfpPakI8b .loopLine{stroke-width:2px;stroke-dasharray:2, 2;stroke:#ccf;fill:#ccf}#mermaid-svg-F4Y4w4pYfpPakI8b .note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-F4Y4w4pYfpPakI8b .noteText,#mermaid-svg-F4Y4w4pYfpPakI8b .noteText>tspan{fill:#000;stroke:none}#mermaid-svg-F4Y4w4pYfpPakI8b .activation0{fill:#f4f4f4;stroke:#666}#mermaid-svg-F4Y4w4pYfpPakI8b .activation1{fill:#f4f4f4;stroke:#666}#mermaid-svg-F4Y4w4pYfpPakI8b .activation2{fill:#f4f4f4;stroke:#666}#mermaid-svg-F4Y4w4pYfpPakI8b .mermaid-main-font{font-family:"trebuchet ms", verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-F4Y4w4pYfpPakI8b .section{stroke:none;opacity:0.2}#mermaid-svg-F4Y4w4pYfpPakI8b .section0{fill:rgba(102,102,255,0.49)}#mermaid-svg-F4Y4w4pYfpPakI8b .section2{fill:#fff400}#mermaid-svg-F4Y4w4pYfpPakI8b .section1,#mermaid-svg-F4Y4w4pYfpPakI8b .section3{fill:#fff;opacity:0.2}#mermaid-svg-F4Y4w4pYfpPakI8b .sectionTitle0{fill:#333}#mermaid-svg-F4Y4w4pYfpPakI8b .sectionTitle1{fill:#333}#mermaid-svg-F4Y4w4pYfpPakI8b .sectionTitle2{fill:#333}#mermaid-svg-F4Y4w4pYfpPakI8b .sectionTitle3{fill:#333}#mermaid-svg-F4Y4w4pYfpPakI8b .sectionTitle{text-anchor:start;font-size:11px;text-height:14px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-F4Y4w4pYfpPakI8b .grid .tick{stroke:#d3d3d3;opacity:0.8;shape-rendering:crispEdges}#mermaid-svg-F4Y4w4pYfpPakI8b .grid .tick text{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-F4Y4w4pYfpPakI8b .grid path{stroke-width:0}#mermaid-svg-F4Y4w4pYfpPakI8b .today{fill:none;stroke:red;stroke-width:2px}#mermaid-svg-F4Y4w4pYfpPakI8b .task{stroke-width:2}#mermaid-svg-F4Y4w4pYfpPakI8b .taskText{text-anchor:middle;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-F4Y4w4pYfpPakI8b .taskText:not([font-size]){font-size:11px}#mermaid-svg-F4Y4w4pYfpPakI8b .taskTextOutsideRight{fill:#000;text-anchor:start;font-size:11px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-F4Y4w4pYfpPakI8b .taskTextOutsideLeft{fill:#000;text-anchor:end;font-size:11px}#mermaid-svg-F4Y4w4pYfpPakI8b .task.clickable{cursor:pointer}#mermaid-svg-F4Y4w4pYfpPakI8b .taskText.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-F4Y4w4pYfpPakI8b .taskTextOutsideLeft.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-F4Y4w4pYfpPakI8b .taskTextOutsideRight.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-F4Y4w4pYfpPakI8b .taskText0,#mermaid-svg-F4Y4w4pYfpPakI8b .taskText1,#mermaid-svg-F4Y4w4pYfpPakI8b .taskText2,#mermaid-svg-F4Y4w4pYfpPakI8b .taskText3{fill:#fff}#mermaid-svg-F4Y4w4pYfpPakI8b .task0,#mermaid-svg-F4Y4w4pYfpPakI8b .task1,#mermaid-svg-F4Y4w4pYfpPakI8b .task2,#mermaid-svg-F4Y4w4pYfpPakI8b .task3{fill:#8a90dd;stroke:#534fbc}#mermaid-svg-F4Y4w4pYfpPakI8b .taskTextOutside0,#mermaid-svg-F4Y4w4pYfpPakI8b .taskTextOutside2{fill:#000}#mermaid-svg-F4Y4w4pYfpPakI8b .taskTextOutside1,#mermaid-svg-F4Y4w4pYfpPakI8b .taskTextOutside3{fill:#000}#mermaid-svg-F4Y4w4pYfpPakI8b .active0,#mermaid-svg-F4Y4w4pYfpPakI8b .active1,#mermaid-svg-F4Y4w4pYfpPakI8b .active2,#mermaid-svg-F4Y4w4pYfpPakI8b .active3{fill:#bfc7ff;stroke:#534fbc}#mermaid-svg-F4Y4w4pYfpPakI8b .activeText0,#mermaid-svg-F4Y4w4pYfpPakI8b .activeText1,#mermaid-svg-F4Y4w4pYfpPakI8b .activeText2,#mermaid-svg-F4Y4w4pYfpPakI8b .activeText3{fill:#000 !important}#mermaid-svg-F4Y4w4pYfpPakI8b .done0,#mermaid-svg-F4Y4w4pYfpPakI8b .done1,#mermaid-svg-F4Y4w4pYfpPakI8b .done2,#mermaid-svg-F4Y4w4pYfpPakI8b .done3{stroke:grey;fill:#d3d3d3;stroke-width:2}#mermaid-svg-F4Y4w4pYfpPakI8b .doneText0,#mermaid-svg-F4Y4w4pYfpPakI8b .doneText1,#mermaid-svg-F4Y4w4pYfpPakI8b .doneText2,#mermaid-svg-F4Y4w4pYfpPakI8b .doneText3{fill:#000 !important}#mermaid-svg-F4Y4w4pYfpPakI8b .crit0,#mermaid-svg-F4Y4w4pYfpPakI8b .crit1,#mermaid-svg-F4Y4w4pYfpPakI8b .crit2,#mermaid-svg-F4Y4w4pYfpPakI8b .crit3{stroke:#f88;fill:red;stroke-width:2}#mermaid-svg-F4Y4w4pYfpPakI8b .activeCrit0,#mermaid-svg-F4Y4w4pYfpPakI8b .activeCrit1,#mermaid-svg-F4Y4w4pYfpPakI8b .activeCrit2,#mermaid-svg-F4Y4w4pYfpPakI8b .activeCrit3{stroke:#f88;fill:#bfc7ff;stroke-width:2}#mermaid-svg-F4Y4w4pYfpPakI8b .doneCrit0,#mermaid-svg-F4Y4w4pYfpPakI8b .doneCrit1,#mermaid-svg-F4Y4w4pYfpPakI8b .doneCrit2,#mermaid-svg-F4Y4w4pYfpPakI8b .doneCrit3{stroke:#f88;fill:#d3d3d3;stroke-width:2;cursor:pointer;shape-rendering:crispEdges}#mermaid-svg-F4Y4w4pYfpPakI8b .milestone{transform:rotate(45deg) scale(0.8, 0.8)}#mermaid-svg-F4Y4w4pYfpPakI8b .milestoneText{font-style:italic}#mermaid-svg-F4Y4w4pYfpPakI8b .doneCritText0,#mermaid-svg-F4Y4w4pYfpPakI8b .doneCritText1,#mermaid-svg-F4Y4w4pYfpPakI8b .doneCritText2,#mermaid-svg-F4Y4w4pYfpPakI8b .doneCritText3{fill:#000 !important}#mermaid-svg-F4Y4w4pYfpPakI8b .activeCritText0,#mermaid-svg-F4Y4w4pYfpPakI8b .activeCritText1,#mermaid-svg-F4Y4w4pYfpPakI8b .activeCritText2,#mermaid-svg-F4Y4w4pYfpPakI8b .activeCritText3{fill:#000 !important}#mermaid-svg-F4Y4w4pYfpPakI8b .titleText{text-anchor:middle;font-size:18px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-F4Y4w4pYfpPakI8b g.classGroup text{fill:#9370db;stroke:none;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:10px}#mermaid-svg-F4Y4w4pYfpPakI8b g.classGroup text .title{font-weight:bolder}#mermaid-svg-F4Y4w4pYfpPakI8b g.clickable{cursor:pointer}#mermaid-svg-F4Y4w4pYfpPakI8b g.classGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-F4Y4w4pYfpPakI8b g.classGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-F4Y4w4pYfpPakI8b .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5}#mermaid-svg-F4Y4w4pYfpPakI8b .classLabel .label{fill:#9370db;font-size:10px}#mermaid-svg-F4Y4w4pYfpPakI8b .relation{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-F4Y4w4pYfpPakI8b .dashed-line{stroke-dasharray:3}#mermaid-svg-F4Y4w4pYfpPakI8b #compositionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-F4Y4w4pYfpPakI8b #compositionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-F4Y4w4pYfpPakI8b #aggregationStart{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-F4Y4w4pYfpPakI8b #aggregationEnd{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-F4Y4w4pYfpPakI8b #dependencyStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-F4Y4w4pYfpPakI8b #dependencyEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-F4Y4w4pYfpPakI8b #extensionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-F4Y4w4pYfpPakI8b #extensionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-F4Y4w4pYfpPakI8b .commit-id,#mermaid-svg-F4Y4w4pYfpPakI8b .commit-msg,#mermaid-svg-F4Y4w4pYfpPakI8b .branch-label{fill:lightgrey;color:lightgrey;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-F4Y4w4pYfpPakI8b .pieTitleText{text-anchor:middle;font-size:25px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-F4Y4w4pYfpPakI8b .slice{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-F4Y4w4pYfpPakI8b g.stateGroup text{fill:#9370db;stroke:none;font-size:10px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-F4Y4w4pYfpPakI8b g.stateGroup text{fill:#9370db;fill:#333;stroke:none;font-size:10px}#mermaid-svg-F4Y4w4pYfpPakI8b g.statediagram-cluster .cluster-label text{fill:#333}#mermaid-svg-F4Y4w4pYfpPakI8b g.stateGroup .state-title{font-weight:bolder;fill:#000}#mermaid-svg-F4Y4w4pYfpPakI8b g.stateGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-F4Y4w4pYfpPakI8b g.stateGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-F4Y4w4pYfpPakI8b .transition{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-F4Y4w4pYfpPakI8b .stateGroup .composit{fill:white;border-bottom:1px}#mermaid-svg-F4Y4w4pYfpPakI8b .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px}#mermaid-svg-F4Y4w4pYfpPakI8b .state-note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-F4Y4w4pYfpPakI8b .state-note text{fill:black;stroke:none;font-size:10px}#mermaid-svg-F4Y4w4pYfpPakI8b .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.7}#mermaid-svg-F4Y4w4pYfpPakI8b .edgeLabel text{fill:#333}#mermaid-svg-F4Y4w4pYfpPakI8b .stateLabel text{fill:#000;font-size:10px;font-weight:bold;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-F4Y4w4pYfpPakI8b .node circle.state-start{fill:black;stroke:black}#mermaid-svg-F4Y4w4pYfpPakI8b .node circle.state-end{fill:black;stroke:white;stroke-width:1.5}#mermaid-svg-F4Y4w4pYfpPakI8b #statediagram-barbEnd{fill:#9370db}#mermaid-svg-F4Y4w4pYfpPakI8b .statediagram-cluster rect{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-F4Y4w4pYfpPakI8b .statediagram-cluster rect.outer{rx:5px;ry:5px}#mermaid-svg-F4Y4w4pYfpPakI8b .statediagram-state .divider{stroke:#9370db}#mermaid-svg-F4Y4w4pYfpPakI8b .statediagram-state .title-state{rx:5px;ry:5px}#mermaid-svg-F4Y4w4pYfpPakI8b .statediagram-cluster.statediagram-cluster .inner{fill:white}#mermaid-svg-F4Y4w4pYfpPakI8b .statediagram-cluster.statediagram-cluster-alt .inner{fill:#e0e0e0}#mermaid-svg-F4Y4w4pYfpPakI8b .statediagram-cluster .inner{rx:0;ry:0}#mermaid-svg-F4Y4w4pYfpPakI8b .statediagram-state rect.basic{rx:5px;ry:5px}#mermaid-svg-F4Y4w4pYfpPakI8b .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#efefef}#mermaid-svg-F4Y4w4pYfpPakI8b .note-edge{stroke-dasharray:5}#mermaid-svg-F4Y4w4pYfpPakI8b .statediagram-note rect{fill:#fff5ad;stroke:#aa3;stroke-width:1px;rx:0;ry:0}:root{--mermaid-font-family: '"trebuchet ms", verdana, arial';--mermaid-font-family: "Comic Sans MS", "Comic Sans", cursive}#mermaid-svg-F4Y4w4pYfpPakI8b .error-icon{fill:#522}#mermaid-svg-F4Y4w4pYfpPakI8b .error-text{fill:#522;stroke:#522}#mermaid-svg-F4Y4w4pYfpPakI8b .edge-thickness-normal{stroke-width:2px}#mermaid-svg-F4Y4w4pYfpPakI8b .edge-thickness-thick{stroke-width:3.5px}#mermaid-svg-F4Y4w4pYfpPakI8b .edge-pattern-solid{stroke-dasharray:0}#mermaid-svg-F4Y4w4pYfpPakI8b .edge-pattern-dashed{stroke-dasharray:3}#mermaid-svg-F4Y4w4pYfpPakI8b .edge-pattern-dotted{stroke-dasharray:2}#mermaid-svg-F4Y4w4pYfpPakI8b .marker{fill:#333}#mermaid-svg-F4Y4w4pYfpPakI8b .marker.cross{stroke:#333}:root { --mermaid-font-family: "trebuchet ms", verdana, arial;} #mermaid-svg-F4Y4w4pYfpPakI8b {color: rgba(0, 0, 0, 0.75);font: ;}

构造函数
依赖注入
BeanNameAware
BeanFactoryAwre
ApplicationContextAware
BeanPostProcessor 前置方法
InitializingBean
自定义init方法
BeanPostProcessor 后置方法
DisposableBean
自定义destroy方法

38、Spring支持的几种Bean的作用域

  • singleton:默认,每个容器中只有一个bean的实例,单例的模式由BeanFactory自身来维护。该对象的生命周期是与Spring IOC容器一致的(但在第一次被注入时才会创建)。
  • prototype:为每一个bean请求提供一个实例。 在每次注入时都会创建一个新的对象
  • request: bean被定义为在每个HTTP请求中创建一个单例对象, 也就是说在单个请求中都会复用这一-个单例对象。
  • session:与request范围类似, 确保每个session中有一个bean的实例,在session过期后, bean会随之失效。
  • application: bean被定义为在ServletContext的生 命周期中复用一个单例对象。
  • websocket: bean被定义为在websocket的生命周期中复用一个单例对象。

global-session:全局作用域,global-session和Portlet应用相关。 当你的应用部署在Portlet容器中工作时,它包含很多portlet。如果你想要声明让所有的portlet共用全局的存储变量的话,那么这全局变量需要存储在global-session中。全局作用域与Servlet中的session作用域效果相同。

39、Spring 中的单例bean是线程安全的吗?

Spring中的Bean默认是单例模式的,框架并没有对bean进行多线程的封装处理。

如果Bean是有状态的那就需要开发人员自己来进行线程安全的保证,最简单的办法就是改变bean的作用域把"singleton"改为"protopyte’这样每次请求Bean就相当于是new Bean()这样就可以保证线程的安全了。

  • 有状态就是有数据存储功能
  • 无状态就是不会保存数据

controller、service和dao层本身并不是线程安全的, 如果只是调用里面的方法,而且多线程调用一个实例的方法,会在内存中复制变量,这是自己的线程的工作内存,是安全的。

Dao会操作数据库Connection, Connection是带有状态的, 比如说数据库事务,Spring的事务管理器使用Threadlocal为不同线程维护了一套独立的connection副本,保证线程之间不会互相影响(Spring 是如何保证事务获取同一个Connection的)

不要在bean中声明任何有状态的实例变量或类变量,如果必须如此,那么就使用ThreadLocal把变量变为线程私有的,如果bean的实例变量或类变量需要在多个线程之间共享,那么就只能使用synchronized、 lock. CAS等这些实现线程同步的方法了。

40、Spring框架中都用到了哪些设计模式?

简单工厂:由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类。

Spring中的BeanFactory就是简单工厂模式的体现,根据传入一个唯一的标识来获得Bean对象,但是否是在传入参数后创建还是传入参数前创建这个要根据具体情况来定。

工厂方法:

实现了FactoryBean接口的bean是一类叫做factory的bean。 其特点是,spring会 在使用getBean(调用获得该bean时,会自动调用该bean的getobject()方法,所以返回的不是factory这个bean,而是这个bean. getojbect()方法的返回值。

单例模式:保证一个类仅有一 个实例, 并提供一个访问它的全局访问点

spring对单例的实现: spring中的单例模式完成 了后半句话,即提供了全局的访问点BeanFactory.但没有从构造器级别去控制单例,这是因为spring管理的是任意的java对象。

适配器模式:

Spring定义了一个适配接口,使得每一种Controller 有一种 对应的适配器实现类,让适配器代替contro11er执行相应的方法。这样在扩展Contro1ler时,只需要增加一个适配器类就完成了SpringMVC的扩展了。

**装饰器模式:**动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator模式相比生成子类更为灵活。

Spring中用到的包装器模式在类名上有两种表现:一种是类名中含有Wrapper,另一种是 类名中含有Decorator。

动态代理:

切面在应用运行的时刻被织入。一般情况下,在织入切面时,AOP容器会为目标对象动态的创建一个代理对象。

SpringAOP就是以这种方式织入切面的。

织入:把切面应用到目标对象并创建新的代理对象的过程。

观察者模式:

spring的事件驱动模型使用的是观察者模式,Spring中observer 模式常用的地方是listener的实现。

策略模式:

Spring框架的资源访问Resource接口。该接口提供了更强的资源访问能力,Spring框架本身大量使用了Resource
接口来访问底层资源。

41、Spring事务的实现方式和原理以及隔离级别

在使用Spring框架时,可以有两种使用事务的方式,一种是编程式的,一种是申明式的,@Transactional注解就是申明式的。

首先,事务这个概念是数据库层面的,Spring只是基 于数据库中的事务进行了扩展,以及提供了- -些能让程序员更加方便操作事务的方式。

比如我们可以通过在某个方法上增加@Transactional注解,就可以开启事务,这个方法中所有的sq|都会在一个事务中执行,统- -成功或失败。

在一个方法.上加了@Transactional注解后,Spring会基于这个类生成一个代理对象, 会将这个代理对象作为bean,当在使用这个代理对象的方法时,如果这个方法.上存在@Transactional注解,那么代理逻辑会先把事务的自动提交设置为false,然后再去执行原本的业务逻辑方法,如果执行业务逻辑方法没有出现异常,那么代理逻辑中就会将事务进行提交,如果执行业务逻辑方法出现了异常,那么则会将事务进行回滚。

当然,针对哪些异常回滚事务是可以配置的,可以利用@Transactional注解中的rollbackFor属性进行配置, 默认情况下会对RuntimeException和Error进行回滚。

spring事务隔离级别就是数据库的隔离级别:外加一个默认级别

  • read uncommitted (未提交读)
  • read committed (提交读、不可重复读)
  • repeatable read (可重复读)
  • serializable (可串行化)

数据库的配置隔离级别是Read Commited ,而Spr ing配置的隔离级别是Repeatable Read, 请问这时隔离级别是以哪一个为准?
以Spring配置的为准,如果spring设 置的隔离级别数据库不支持,效果取决于数据库

42、Spring事务传播机制

多个事务方法相互调用时,事务如何在这些方法间传播

方法A是一个事务的方法, 方法A执行过程中调用了方法B,那么方法B有无事务以及方法B对事务的要求不同都会对方法A的事务具体执行造成影响,同时方法A的事务对方法B的事务执行也有影响,这种影响具体是什么就由两个方法所定义的事务传播类型所决定。

  • REQUIRED(Spring默认的事务传播类型):如果当前没有事务,则自己新建一个事务, 如果当前存在事务,则加入这个事务
  • SUPPORTS:当前存在事务,则加入当前事务,如果当前没有事务,就以非事务方法执行
  • MANDATORY:当前存在事务,则加入当前事务,如果当前事务不存在,则抛出异常。
  • REQUIRES_ NEW:创建一个 新事务,如果存在当前事务,则挂起该事务。
  • NOT_ SUPPORTED:以非事务方式执行,如果当前存在事务,则挂起当前事务
  • NEVER:不使用事务,如果当前事务存在,则抛出异常
  • NESTED:如果当前事务存在,则在嵌套事务中执行,否则REQUIRED的操作-样(开启一个事务 )

和REQUIRES_ NEW的区别

REQUIRES_ NEW是新建一个事务 并且新开启的这个事务与原有事务无关,而NESTED则是当前存在事务时(我们把当前事务称之为父事务)会开启一个嵌套事务(称之为一个子事务)。在NESTED情况 下父事务回滚时,子事务也会回滚,而在REQUIRES_ NEW情况下,原有事务回滚,不会影响新开启的事务。

和IREQUIRED的区别

REQUIRED情况下,调用方存在事务时,则被调用方和调用方使用同一事务,那么被调用方出现异常时,由于共用一个事务,所以无论调用方是否catch其异常,事务都会回滚而在NESTED情况下,被调用方发生异常时,调用方可以catch其导常,这样子事务回滚,父事务也不会回滚。

43、Spring事务什么时候失效

spring事务的原理是AOP,进行了切面增强,那么失效的根本原因是这个AOP不起作用了!常见情况有如下几种

1、发生自调用,类里面使用this调用本类的方法(this通常省略) ,此时这个this对象不是代理类,而是UserService对象本身!

解决方法很简单,让那个this变成UserService的代理类即可!

2、方法不是public的

@Transactional只能用于public的方法上,否则事务不会失效,如果要用在非public 方法上,可以开启AspectJ代理模式。

3、数据库不支持事务

4、没有被spring管理(组件不在IOC 容器)

5、异常被吃掉,事务不会回滚(或者抛出的异常没有被定义,默认为RuntimeException)

44、什么是Bean的自动装配,有哪些方式?

开启自动装配,只需要在xml配置文件中定义"autowire"属性。

<bean id="cutomer" Class="com.xxx.xxx.Customer" autowire="" />

autowire属性有五种装配的方式:

  • no-缺省情况下,自动配置是通过"ref"属性手动设定。

    手动装配:以value或ref的方式明确指定属性值都是手动装配。需要通过’ref '属性来连接bean.

  • byName 根据bean的属性名称进行自动装配。

    Cutomer的属性名称是person, Spring 会将bean id为person的bean通过setter 方法进行自动装配。

    <bean id="cutomer" class="com.xxx.xxx.Customer" autowire="byName"/>
    <bean id="person" class="com.xxx.xxx.Person'"/>
    
  • byType-根据bean的类型进行自动装配。

    Cutomer的属性person的类型为Person, Spi rng会将Person类型通过setter方法进行自动装配。如果有多个bean可用Qualifier明确指定。

    <bean id=" cutomer" class="com.xxx.xxx.Customer" autowire="byType"/>
    <bean id="person" class="com.XXX.xxx.Person"/>
    
  • constructor类似byType,不过是应用于构造器的参数。如果一个bean与构造器参 数的类型形同,则进行自动装配,否则导致异常。

    Cutomer构造函数的参数person的类型为Person, Spi rng会将Person类型通过构造方法进行自动装配。

    <bean id="cutomer" class="com. xxX . xxx. Cutomer" autowi re="construtor"/>
    <bean id="person" class="com. xxX. xxx.Person"/>
    
  • autodetect-如果有默认的构造器,则通过constructor方式进行自动装配, 否则使用byType方式进行自动装配。

    @Autowired自动装配bean,可以在字段、setter方法、 构造函数上使用。

45、Spring Boot、Spring Cloud、Spring MVC和Spring有什么区别

  • spring是一个IOC容器,用来管理Bean, 使用依赖注入实现控制反转,可以很方便的整合各种框架,提供AOP机制弥补OOP的代码重复问题、更動便将不同类不同方法中的共同处理抽取成切面、自动注入给方法执行,比如日志、异常等
  • springmvc是spring对web框架的一个解决方案,提供了-个总的前端控制器Servlet,用来接收请求,然后定义了一套路由策略 (url到handle的映射) 及适配执行handle,将handle结果使用视图解析技术生成视图展现给前端
  • springboot是spring提供的一个快速开发工具包,让程序员能更方便、更快速的开发spring+springmvc应用, 简化了配置(约定了默认配置), 整合了一系列的解决方案(starter机制) 、redis、 mongodb、 es, 可以开箱即用
  • Spring Cloud为开发人员提供了用于快速构建分布式系统中某些常见模式的工具(例如,配置管理,服务发现,断路器,智能路由,微代理,控制总线)。分布式系统的协调产生了样板模式,并且使用Spring云开发人员可以快速支持实现这些模式的服务和应用程序。它们可以在任何分布式环境中正常工作,包括开发人员自己的笔记本电脑,裸机数据中心和受管理的平台,例如Cloud Foundry。

46、SpringMVC 的工作流程

  1. 用户发送请求至前端控制器DispatcherServlet。
  1. DispatcherServlet 收到请求调用HandlerMapping处理器映射器。
  2. 处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器及处理器拦截器(如果有则生
    成)一并返回给DispatcherServlet。
  3. DispatcherServlet 调用HandlerAdapter处理器适配器。
  4. HandlerAdapter 经过适配调用具体的处理器(Controller,也叫后端控制器)
  5. Controller 执行完成返回ModelAndView。
  6. HandlerAdapter 将controller执行结果ModelAndView返回给DispatcherServlet。
  7. DispatcherServlet将ModelAndView传给ViewResolver视图解析器。
  8. ViewResolver 解析后返回具体View。
  9. DispatcherServlet 根据View进行渲染视图(即将模型数据填充至视图中)。
  10. DispatcherServlet 响应用户。
#mermaid-svg-14TzQiFwQS48J0Lf .label{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);fill:#333;color:#333}#mermaid-svg-14TzQiFwQS48J0Lf .label text{fill:#333}#mermaid-svg-14TzQiFwQS48J0Lf .node rect,#mermaid-svg-14TzQiFwQS48J0Lf .node circle,#mermaid-svg-14TzQiFwQS48J0Lf .node ellipse,#mermaid-svg-14TzQiFwQS48J0Lf .node polygon,#mermaid-svg-14TzQiFwQS48J0Lf .node path{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-14TzQiFwQS48J0Lf .node .label{text-align:center;fill:#333}#mermaid-svg-14TzQiFwQS48J0Lf .node.clickable{cursor:pointer}#mermaid-svg-14TzQiFwQS48J0Lf .arrowheadPath{fill:#333}#mermaid-svg-14TzQiFwQS48J0Lf .edgePath .path{stroke:#333;stroke-width:1.5px}#mermaid-svg-14TzQiFwQS48J0Lf .flowchart-link{stroke:#333;fill:none}#mermaid-svg-14TzQiFwQS48J0Lf .edgeLabel{background-color:#e8e8e8;text-align:center}#mermaid-svg-14TzQiFwQS48J0Lf .edgeLabel rect{opacity:0.9}#mermaid-svg-14TzQiFwQS48J0Lf .edgeLabel span{color:#333}#mermaid-svg-14TzQiFwQS48J0Lf .cluster rect{fill:#ffffde;stroke:#aa3;stroke-width:1px}#mermaid-svg-14TzQiFwQS48J0Lf .cluster text{fill:#333}#mermaid-svg-14TzQiFwQS48J0Lf div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:12px;background:#ffffde;border:1px solid #aa3;border-radius:2px;pointer-events:none;z-index:100}#mermaid-svg-14TzQiFwQS48J0Lf .actor{stroke:#ccf;fill:#ECECFF}#mermaid-svg-14TzQiFwQS48J0Lf text.actor>tspan{fill:#000;stroke:none}#mermaid-svg-14TzQiFwQS48J0Lf .actor-line{stroke:grey}#mermaid-svg-14TzQiFwQS48J0Lf .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333}#mermaid-svg-14TzQiFwQS48J0Lf .messageLine1{stroke-width:1.5;stroke-dasharray:2, 2;stroke:#333}#mermaid-svg-14TzQiFwQS48J0Lf #arrowhead path{fill:#333;stroke:#333}#mermaid-svg-14TzQiFwQS48J0Lf .sequenceNumber{fill:#fff}#mermaid-svg-14TzQiFwQS48J0Lf #sequencenumber{fill:#333}#mermaid-svg-14TzQiFwQS48J0Lf #crosshead path{fill:#333;stroke:#333}#mermaid-svg-14TzQiFwQS48J0Lf .messageText{fill:#333;stroke:#333}#mermaid-svg-14TzQiFwQS48J0Lf .labelBox{stroke:#ccf;fill:#ECECFF}#mermaid-svg-14TzQiFwQS48J0Lf .labelText,#mermaid-svg-14TzQiFwQS48J0Lf .labelText>tspan{fill:#000;stroke:none}#mermaid-svg-14TzQiFwQS48J0Lf .loopText,#mermaid-svg-14TzQiFwQS48J0Lf .loopText>tspan{fill:#000;stroke:none}#mermaid-svg-14TzQiFwQS48J0Lf .loopLine{stroke-width:2px;stroke-dasharray:2, 2;stroke:#ccf;fill:#ccf}#mermaid-svg-14TzQiFwQS48J0Lf .note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-14TzQiFwQS48J0Lf .noteText,#mermaid-svg-14TzQiFwQS48J0Lf .noteText>tspan{fill:#000;stroke:none}#mermaid-svg-14TzQiFwQS48J0Lf .activation0{fill:#f4f4f4;stroke:#666}#mermaid-svg-14TzQiFwQS48J0Lf .activation1{fill:#f4f4f4;stroke:#666}#mermaid-svg-14TzQiFwQS48J0Lf .activation2{fill:#f4f4f4;stroke:#666}#mermaid-svg-14TzQiFwQS48J0Lf .mermaid-main-font{font-family:"trebuchet ms", verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-14TzQiFwQS48J0Lf .section{stroke:none;opacity:0.2}#mermaid-svg-14TzQiFwQS48J0Lf .section0{fill:rgba(102,102,255,0.49)}#mermaid-svg-14TzQiFwQS48J0Lf .section2{fill:#fff400}#mermaid-svg-14TzQiFwQS48J0Lf .section1,#mermaid-svg-14TzQiFwQS48J0Lf .section3{fill:#fff;opacity:0.2}#mermaid-svg-14TzQiFwQS48J0Lf .sectionTitle0{fill:#333}#mermaid-svg-14TzQiFwQS48J0Lf .sectionTitle1{fill:#333}#mermaid-svg-14TzQiFwQS48J0Lf .sectionTitle2{fill:#333}#mermaid-svg-14TzQiFwQS48J0Lf .sectionTitle3{fill:#333}#mermaid-svg-14TzQiFwQS48J0Lf .sectionTitle{text-anchor:start;font-size:11px;text-height:14px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-14TzQiFwQS48J0Lf .grid .tick{stroke:#d3d3d3;opacity:0.8;shape-rendering:crispEdges}#mermaid-svg-14TzQiFwQS48J0Lf .grid .tick text{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-14TzQiFwQS48J0Lf .grid path{stroke-width:0}#mermaid-svg-14TzQiFwQS48J0Lf .today{fill:none;stroke:red;stroke-width:2px}#mermaid-svg-14TzQiFwQS48J0Lf .task{stroke-width:2}#mermaid-svg-14TzQiFwQS48J0Lf .taskText{text-anchor:middle;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-14TzQiFwQS48J0Lf .taskText:not([font-size]){font-size:11px}#mermaid-svg-14TzQiFwQS48J0Lf .taskTextOutsideRight{fill:#000;text-anchor:start;font-size:11px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-14TzQiFwQS48J0Lf .taskTextOutsideLeft{fill:#000;text-anchor:end;font-size:11px}#mermaid-svg-14TzQiFwQS48J0Lf .task.clickable{cursor:pointer}#mermaid-svg-14TzQiFwQS48J0Lf .taskText.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-14TzQiFwQS48J0Lf .taskTextOutsideLeft.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-14TzQiFwQS48J0Lf .taskTextOutsideRight.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-14TzQiFwQS48J0Lf .taskText0,#mermaid-svg-14TzQiFwQS48J0Lf .taskText1,#mermaid-svg-14TzQiFwQS48J0Lf .taskText2,#mermaid-svg-14TzQiFwQS48J0Lf .taskText3{fill:#fff}#mermaid-svg-14TzQiFwQS48J0Lf .task0,#mermaid-svg-14TzQiFwQS48J0Lf .task1,#mermaid-svg-14TzQiFwQS48J0Lf .task2,#mermaid-svg-14TzQiFwQS48J0Lf .task3{fill:#8a90dd;stroke:#534fbc}#mermaid-svg-14TzQiFwQS48J0Lf .taskTextOutside0,#mermaid-svg-14TzQiFwQS48J0Lf .taskTextOutside2{fill:#000}#mermaid-svg-14TzQiFwQS48J0Lf .taskTextOutside1,#mermaid-svg-14TzQiFwQS48J0Lf .taskTextOutside3{fill:#000}#mermaid-svg-14TzQiFwQS48J0Lf .active0,#mermaid-svg-14TzQiFwQS48J0Lf .active1,#mermaid-svg-14TzQiFwQS48J0Lf .active2,#mermaid-svg-14TzQiFwQS48J0Lf .active3{fill:#bfc7ff;stroke:#534fbc}#mermaid-svg-14TzQiFwQS48J0Lf .activeText0,#mermaid-svg-14TzQiFwQS48J0Lf .activeText1,#mermaid-svg-14TzQiFwQS48J0Lf .activeText2,#mermaid-svg-14TzQiFwQS48J0Lf .activeText3{fill:#000 !important}#mermaid-svg-14TzQiFwQS48J0Lf .done0,#mermaid-svg-14TzQiFwQS48J0Lf .done1,#mermaid-svg-14TzQiFwQS48J0Lf .done2,#mermaid-svg-14TzQiFwQS48J0Lf .done3{stroke:grey;fill:#d3d3d3;stroke-width:2}#mermaid-svg-14TzQiFwQS48J0Lf .doneText0,#mermaid-svg-14TzQiFwQS48J0Lf .doneText1,#mermaid-svg-14TzQiFwQS48J0Lf .doneText2,#mermaid-svg-14TzQiFwQS48J0Lf .doneText3{fill:#000 !important}#mermaid-svg-14TzQiFwQS48J0Lf .crit0,#mermaid-svg-14TzQiFwQS48J0Lf .crit1,#mermaid-svg-14TzQiFwQS48J0Lf .crit2,#mermaid-svg-14TzQiFwQS48J0Lf .crit3{stroke:#f88;fill:red;stroke-width:2}#mermaid-svg-14TzQiFwQS48J0Lf .activeCrit0,#mermaid-svg-14TzQiFwQS48J0Lf .activeCrit1,#mermaid-svg-14TzQiFwQS48J0Lf .activeCrit2,#mermaid-svg-14TzQiFwQS48J0Lf .activeCrit3{stroke:#f88;fill:#bfc7ff;stroke-width:2}#mermaid-svg-14TzQiFwQS48J0Lf .doneCrit0,#mermaid-svg-14TzQiFwQS48J0Lf .doneCrit1,#mermaid-svg-14TzQiFwQS48J0Lf .doneCrit2,#mermaid-svg-14TzQiFwQS48J0Lf .doneCrit3{stroke:#f88;fill:#d3d3d3;stroke-width:2;cursor:pointer;shape-rendering:crispEdges}#mermaid-svg-14TzQiFwQS48J0Lf .milestone{transform:rotate(45deg) scale(0.8, 0.8)}#mermaid-svg-14TzQiFwQS48J0Lf .milestoneText{font-style:italic}#mermaid-svg-14TzQiFwQS48J0Lf .doneCritText0,#mermaid-svg-14TzQiFwQS48J0Lf .doneCritText1,#mermaid-svg-14TzQiFwQS48J0Lf .doneCritText2,#mermaid-svg-14TzQiFwQS48J0Lf .doneCritText3{fill:#000 !important}#mermaid-svg-14TzQiFwQS48J0Lf .activeCritText0,#mermaid-svg-14TzQiFwQS48J0Lf .activeCritText1,#mermaid-svg-14TzQiFwQS48J0Lf .activeCritText2,#mermaid-svg-14TzQiFwQS48J0Lf .activeCritText3{fill:#000 !important}#mermaid-svg-14TzQiFwQS48J0Lf .titleText{text-anchor:middle;font-size:18px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-14TzQiFwQS48J0Lf g.classGroup text{fill:#9370db;stroke:none;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:10px}#mermaid-svg-14TzQiFwQS48J0Lf g.classGroup text .title{font-weight:bolder}#mermaid-svg-14TzQiFwQS48J0Lf g.clickable{cursor:pointer}#mermaid-svg-14TzQiFwQS48J0Lf g.classGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-14TzQiFwQS48J0Lf g.classGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-14TzQiFwQS48J0Lf .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5}#mermaid-svg-14TzQiFwQS48J0Lf .classLabel .label{fill:#9370db;font-size:10px}#mermaid-svg-14TzQiFwQS48J0Lf .relation{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-14TzQiFwQS48J0Lf .dashed-line{stroke-dasharray:3}#mermaid-svg-14TzQiFwQS48J0Lf #compositionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-14TzQiFwQS48J0Lf #compositionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-14TzQiFwQS48J0Lf #aggregationStart{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-14TzQiFwQS48J0Lf #aggregationEnd{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-14TzQiFwQS48J0Lf #dependencyStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-14TzQiFwQS48J0Lf #dependencyEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-14TzQiFwQS48J0Lf #extensionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-14TzQiFwQS48J0Lf #extensionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-14TzQiFwQS48J0Lf .commit-id,#mermaid-svg-14TzQiFwQS48J0Lf .commit-msg,#mermaid-svg-14TzQiFwQS48J0Lf .branch-label{fill:lightgrey;color:lightgrey;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-14TzQiFwQS48J0Lf .pieTitleText{text-anchor:middle;font-size:25px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-14TzQiFwQS48J0Lf .slice{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-14TzQiFwQS48J0Lf g.stateGroup text{fill:#9370db;stroke:none;font-size:10px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-14TzQiFwQS48J0Lf g.stateGroup text{fill:#9370db;fill:#333;stroke:none;font-size:10px}#mermaid-svg-14TzQiFwQS48J0Lf g.statediagram-cluster .cluster-label text{fill:#333}#mermaid-svg-14TzQiFwQS48J0Lf g.stateGroup .state-title{font-weight:bolder;fill:#000}#mermaid-svg-14TzQiFwQS48J0Lf g.stateGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-14TzQiFwQS48J0Lf g.stateGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-14TzQiFwQS48J0Lf .transition{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-14TzQiFwQS48J0Lf .stateGroup .composit{fill:white;border-bottom:1px}#mermaid-svg-14TzQiFwQS48J0Lf .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px}#mermaid-svg-14TzQiFwQS48J0Lf .state-note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-14TzQiFwQS48J0Lf .state-note text{fill:black;stroke:none;font-size:10px}#mermaid-svg-14TzQiFwQS48J0Lf .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.7}#mermaid-svg-14TzQiFwQS48J0Lf .edgeLabel text{fill:#333}#mermaid-svg-14TzQiFwQS48J0Lf .stateLabel text{fill:#000;font-size:10px;font-weight:bold;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-14TzQiFwQS48J0Lf .node circle.state-start{fill:black;stroke:black}#mermaid-svg-14TzQiFwQS48J0Lf .node circle.state-end{fill:black;stroke:white;stroke-width:1.5}#mermaid-svg-14TzQiFwQS48J0Lf #statediagram-barbEnd{fill:#9370db}#mermaid-svg-14TzQiFwQS48J0Lf .statediagram-cluster rect{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-14TzQiFwQS48J0Lf .statediagram-cluster rect.outer{rx:5px;ry:5px}#mermaid-svg-14TzQiFwQS48J0Lf .statediagram-state .divider{stroke:#9370db}#mermaid-svg-14TzQiFwQS48J0Lf .statediagram-state .title-state{rx:5px;ry:5px}#mermaid-svg-14TzQiFwQS48J0Lf .statediagram-cluster.statediagram-cluster .inner{fill:white}#mermaid-svg-14TzQiFwQS48J0Lf .statediagram-cluster.statediagram-cluster-alt .inner{fill:#e0e0e0}#mermaid-svg-14TzQiFwQS48J0Lf .statediagram-cluster .inner{rx:0;ry:0}#mermaid-svg-14TzQiFwQS48J0Lf .statediagram-state rect.basic{rx:5px;ry:5px}#mermaid-svg-14TzQiFwQS48J0Lf .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#efefef}#mermaid-svg-14TzQiFwQS48J0Lf .note-edge{stroke-dasharray:5}#mermaid-svg-14TzQiFwQS48J0Lf .statediagram-note rect{fill:#fff5ad;stroke:#aa3;stroke-width:1px;rx:0;ry:0}:root{--mermaid-font-family: '"trebuchet ms", verdana, arial';--mermaid-font-family: "Comic Sans MS", "Comic Sans", cursive}#mermaid-svg-14TzQiFwQS48J0Lf .error-icon{fill:#522}#mermaid-svg-14TzQiFwQS48J0Lf .error-text{fill:#522;stroke:#522}#mermaid-svg-14TzQiFwQS48J0Lf .edge-thickness-normal{stroke-width:2px}#mermaid-svg-14TzQiFwQS48J0Lf .edge-thickness-thick{stroke-width:3.5px}#mermaid-svg-14TzQiFwQS48J0Lf .edge-pattern-solid{stroke-dasharray:0}#mermaid-svg-14TzQiFwQS48J0Lf .edge-pattern-dashed{stroke-dasharray:3}#mermaid-svg-14TzQiFwQS48J0Lf .edge-pattern-dotted{stroke-dasharray:2}#mermaid-svg-14TzQiFwQS48J0Lf .marker{fill:#333}#mermaid-svg-14TzQiFwQS48J0Lf .marker.cross{stroke:#333}:root { --mermaid-font-family: "trebuchet ms", verdana, arial;} #mermaid-svg-14TzQiFwQS48J0Lf {color: rgba(0, 0, 0, 0.75);font: ;}

1、发送请求
2、查找handler
3、返回HandlerExecutionChain调用链
HandlerIntercepter处理器拦截器
Handler处理器
11、响应请求
4、调用HandlerAdapter
5、调用handler
6、返回ModelAndView
7、返回ModelAndView
8、视图解析ModelAndView
9、返回View
10、渲染视图
client
DispatcherServlet
中央处理器
HandlerMapping
处理器映射器
HandlerAdapter
处理器适配器
Handler
Controller
ViewReSolver
视图解析器

47、SpringMVC有哪些主要组件?(疑问)

**Handler:**也就是处理器。它直接应对着MVC中的C也就是Controller层,它的具体表现形式有很多,可以是类,也可以是方法。在Controller层中@RequestMapping标注的所有方法都可以看成是一个Handler, 只要可以实际处理请求就可以是Handler

1、HandlerMapping

initHandlerMappings(context),处理器映射器,根据用户请求的资源uri来查找Handler的。在SpringMVC中会有很多请求,每个请求都需要一个Handler处理, 具体接收到一个请求之后使用哪个Handler进行,这就是HandlerMapping需要做的事。

2、HandlerAdapter

initHandlerAdapters(context),适配器。因为SpringMVC中的Handler可以是任意的形式,只要能处理请求就ok,但是Servlet需要的处理方法的结构却是固定的,都是以request和response为参 数的方法。如何让固定的Servlet处理方法调用灵活的Handler来进行处理呢?这就是HandlerAdapter要做的事情。

Handler是用来干活的工具; HandlerMapping用于根据需要干的活找到相应的工具; HandlerAdapter 是使用工具干活的人。

3、HandlerExceptionResolver

initHandlerExceptionResolvers(context),其它组件都是用来干活的。 在干活的过程中难免会出现问题,出问题后怎么办呢?这就需要有一个专门的角色对异常情况进行处理,在SpringMVC中就是HandlerExceptionResolver。具体来说,此组件的作用是根据异常设置ModelAndView,之后再交给render方法进行渲染。

4、ViewResolver

initViewResolvers(context),ViewResolver用来将String类型的视图名和Locale解析为View类型的视图。 View是用来渲染页面的,也就是将程序返回的参数填入模板里,生成html (也可能是其它类型)文件。这里就有两个关键问题:使用哪个模板?用什么技术(规则)填入参数?这其实是ViewResolver主要要做的工作,ViewResolver需要找到渲染所用的模板和所用的技术(也就是视图的类型)进行渲染,具体的渲染过程则交由不同的视图自己完成。

5、RequestToViewNameTranslator

initRequestToViewNameTranslator(context),ViewResolver是 根据ViewName查找View,但有的Handler处理完后并没有设置View也没有设置ViewName,这时就需要从request获取ViewName 了,如何从request中获取ViewName就是RequestToViewNameTranslator要做的事情了。RequestToViewNameTranslator在Spring MVC容器里只可以配置一个, 所以所有request到ViewName的转换规则都要在一个Translator里面全部实现。

6、LocaleResolver

initLocaleResolver(context),解析视图需要两个参数:一是视图名,另一个是Locale。视图名是处理器返回的,Locale是从哪里来的?这就是LocaleResolver要做的事情。 LocaleResolver用于从request解析出Locale, Locale就是zh-cn之类,表示一个区域,有了这个就可以对不同区域的用户显示不同的结果。SpringMVC主要有两个地方用到了Locale:一是ViewResolver视图解析的时候; 二 是用到国际化资源或者主题的时候。

7、ThemeResolver

initThemeResolver(context),用于解析主题。SpringMVC中一 个主题对应-个properties文件,里面存放着跟当前主题相关的所有资源、如图片、css样式等。 SpringMVC的主 题也支持国际化,同一个主题不同区域也可以显示不同的风格。SpringMVC中跟主 题相关的类有ThemeResolver. ThemeSource和Theme。 主题是通过一系列资源来具体体现的,要得到一个主题的资源,首先要得到资源的名称,这是ThemeResolver的工作。然后通过主题名称找到对应的主题(可以理解为一个配置)文件,这是ThemeSource的工作。 最后从主题中获取资源就可以了。

8、MultipartResolver

initMultipartResolver(context),用于处理上传请求。处理方法是将普通的request包装成MultipartHttpServletRequest,后者可以直接调用getFile方法获取File, 如果上传多个文件,还可以调用getFileMap得到FileName->File结构的Map。此组件中-共有三个方法,作用分别是判断是不是上传请求,将request包装成MultipartHttpServletRequest、处理完后清理上传过程中产生的临时资源。

9、FlashMapManager

initFlashMapManager(context),用来管理FlashMap的, FlashMap主要 用在redirect中传递参数。

48、Springboot自动装配原理

@lmport + @Configuration + Spring spi

自动配置类由各个starter提供,使用@Configuration + @Bean定义配置类,放到META-INF/spring.factories下

使用Spring spi扫描META-INF/spring.factories下的配置类

使用@Import导入自动配置类

#mermaid-svg-ledmSgQp92834stI .label{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);fill:#333;color:#333}#mermaid-svg-ledmSgQp92834stI .label text{fill:#333}#mermaid-svg-ledmSgQp92834stI .node rect,#mermaid-svg-ledmSgQp92834stI .node circle,#mermaid-svg-ledmSgQp92834stI .node ellipse,#mermaid-svg-ledmSgQp92834stI .node polygon,#mermaid-svg-ledmSgQp92834stI .node path{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-ledmSgQp92834stI .node .label{text-align:center;fill:#333}#mermaid-svg-ledmSgQp92834stI .node.clickable{cursor:pointer}#mermaid-svg-ledmSgQp92834stI .arrowheadPath{fill:#333}#mermaid-svg-ledmSgQp92834stI .edgePath .path{stroke:#333;stroke-width:1.5px}#mermaid-svg-ledmSgQp92834stI .flowchart-link{stroke:#333;fill:none}#mermaid-svg-ledmSgQp92834stI .edgeLabel{background-color:#e8e8e8;text-align:center}#mermaid-svg-ledmSgQp92834stI .edgeLabel rect{opacity:0.9}#mermaid-svg-ledmSgQp92834stI .edgeLabel span{color:#333}#mermaid-svg-ledmSgQp92834stI .cluster rect{fill:#ffffde;stroke:#aa3;stroke-width:1px}#mermaid-svg-ledmSgQp92834stI .cluster text{fill:#333}#mermaid-svg-ledmSgQp92834stI div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:12px;background:#ffffde;border:1px solid #aa3;border-radius:2px;pointer-events:none;z-index:100}#mermaid-svg-ledmSgQp92834stI .actor{stroke:#ccf;fill:#ECECFF}#mermaid-svg-ledmSgQp92834stI text.actor>tspan{fill:#000;stroke:none}#mermaid-svg-ledmSgQp92834stI .actor-line{stroke:grey}#mermaid-svg-ledmSgQp92834stI .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333}#mermaid-svg-ledmSgQp92834stI .messageLine1{stroke-width:1.5;stroke-dasharray:2, 2;stroke:#333}#mermaid-svg-ledmSgQp92834stI #arrowhead path{fill:#333;stroke:#333}#mermaid-svg-ledmSgQp92834stI .sequenceNumber{fill:#fff}#mermaid-svg-ledmSgQp92834stI #sequencenumber{fill:#333}#mermaid-svg-ledmSgQp92834stI #crosshead path{fill:#333;stroke:#333}#mermaid-svg-ledmSgQp92834stI .messageText{fill:#333;stroke:#333}#mermaid-svg-ledmSgQp92834stI .labelBox{stroke:#ccf;fill:#ECECFF}#mermaid-svg-ledmSgQp92834stI .labelText,#mermaid-svg-ledmSgQp92834stI .labelText>tspan{fill:#000;stroke:none}#mermaid-svg-ledmSgQp92834stI .loopText,#mermaid-svg-ledmSgQp92834stI .loopText>tspan{fill:#000;stroke:none}#mermaid-svg-ledmSgQp92834stI .loopLine{stroke-width:2px;stroke-dasharray:2, 2;stroke:#ccf;fill:#ccf}#mermaid-svg-ledmSgQp92834stI .note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-ledmSgQp92834stI .noteText,#mermaid-svg-ledmSgQp92834stI .noteText>tspan{fill:#000;stroke:none}#mermaid-svg-ledmSgQp92834stI .activation0{fill:#f4f4f4;stroke:#666}#mermaid-svg-ledmSgQp92834stI .activation1{fill:#f4f4f4;stroke:#666}#mermaid-svg-ledmSgQp92834stI .activation2{fill:#f4f4f4;stroke:#666}#mermaid-svg-ledmSgQp92834stI .mermaid-main-font{font-family:"trebuchet ms", verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-ledmSgQp92834stI .section{stroke:none;opacity:0.2}#mermaid-svg-ledmSgQp92834stI .section0{fill:rgba(102,102,255,0.49)}#mermaid-svg-ledmSgQp92834stI .section2{fill:#fff400}#mermaid-svg-ledmSgQp92834stI .section1,#mermaid-svg-ledmSgQp92834stI .section3{fill:#fff;opacity:0.2}#mermaid-svg-ledmSgQp92834stI .sectionTitle0{fill:#333}#mermaid-svg-ledmSgQp92834stI .sectionTitle1{fill:#333}#mermaid-svg-ledmSgQp92834stI .sectionTitle2{fill:#333}#mermaid-svg-ledmSgQp92834stI .sectionTitle3{fill:#333}#mermaid-svg-ledmSgQp92834stI .sectionTitle{text-anchor:start;font-size:11px;text-height:14px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-ledmSgQp92834stI .grid .tick{stroke:#d3d3d3;opacity:0.8;shape-rendering:crispEdges}#mermaid-svg-ledmSgQp92834stI .grid .tick text{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-ledmSgQp92834stI .grid path{stroke-width:0}#mermaid-svg-ledmSgQp92834stI .today{fill:none;stroke:red;stroke-width:2px}#mermaid-svg-ledmSgQp92834stI .task{stroke-width:2}#mermaid-svg-ledmSgQp92834stI .taskText{text-anchor:middle;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-ledmSgQp92834stI .taskText:not([font-size]){font-size:11px}#mermaid-svg-ledmSgQp92834stI .taskTextOutsideRight{fill:#000;text-anchor:start;font-size:11px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-ledmSgQp92834stI .taskTextOutsideLeft{fill:#000;text-anchor:end;font-size:11px}#mermaid-svg-ledmSgQp92834stI .task.clickable{cursor:pointer}#mermaid-svg-ledmSgQp92834stI .taskText.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-ledmSgQp92834stI .taskTextOutsideLeft.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-ledmSgQp92834stI .taskTextOutsideRight.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-ledmSgQp92834stI .taskText0,#mermaid-svg-ledmSgQp92834stI .taskText1,#mermaid-svg-ledmSgQp92834stI .taskText2,#mermaid-svg-ledmSgQp92834stI .taskText3{fill:#fff}#mermaid-svg-ledmSgQp92834stI .task0,#mermaid-svg-ledmSgQp92834stI .task1,#mermaid-svg-ledmSgQp92834stI .task2,#mermaid-svg-ledmSgQp92834stI .task3{fill:#8a90dd;stroke:#534fbc}#mermaid-svg-ledmSgQp92834stI .taskTextOutside0,#mermaid-svg-ledmSgQp92834stI .taskTextOutside2{fill:#000}#mermaid-svg-ledmSgQp92834stI .taskTextOutside1,#mermaid-svg-ledmSgQp92834stI .taskTextOutside3{fill:#000}#mermaid-svg-ledmSgQp92834stI .active0,#mermaid-svg-ledmSgQp92834stI .active1,#mermaid-svg-ledmSgQp92834stI .active2,#mermaid-svg-ledmSgQp92834stI .active3{fill:#bfc7ff;stroke:#534fbc}#mermaid-svg-ledmSgQp92834stI .activeText0,#mermaid-svg-ledmSgQp92834stI .activeText1,#mermaid-svg-ledmSgQp92834stI .activeText2,#mermaid-svg-ledmSgQp92834stI .activeText3{fill:#000 !important}#mermaid-svg-ledmSgQp92834stI .done0,#mermaid-svg-ledmSgQp92834stI .done1,#mermaid-svg-ledmSgQp92834stI .done2,#mermaid-svg-ledmSgQp92834stI .done3{stroke:grey;fill:#d3d3d3;stroke-width:2}#mermaid-svg-ledmSgQp92834stI .doneText0,#mermaid-svg-ledmSgQp92834stI .doneText1,#mermaid-svg-ledmSgQp92834stI .doneText2,#mermaid-svg-ledmSgQp92834stI .doneText3{fill:#000 !important}#mermaid-svg-ledmSgQp92834stI .crit0,#mermaid-svg-ledmSgQp92834stI .crit1,#mermaid-svg-ledmSgQp92834stI .crit2,#mermaid-svg-ledmSgQp92834stI .crit3{stroke:#f88;fill:red;stroke-width:2}#mermaid-svg-ledmSgQp92834stI .activeCrit0,#mermaid-svg-ledmSgQp92834stI .activeCrit1,#mermaid-svg-ledmSgQp92834stI .activeCrit2,#mermaid-svg-ledmSgQp92834stI .activeCrit3{stroke:#f88;fill:#bfc7ff;stroke-width:2}#mermaid-svg-ledmSgQp92834stI .doneCrit0,#mermaid-svg-ledmSgQp92834stI .doneCrit1,#mermaid-svg-ledmSgQp92834stI .doneCrit2,#mermaid-svg-ledmSgQp92834stI .doneCrit3{stroke:#f88;fill:#d3d3d3;stroke-width:2;cursor:pointer;shape-rendering:crispEdges}#mermaid-svg-ledmSgQp92834stI .milestone{transform:rotate(45deg) scale(0.8, 0.8)}#mermaid-svg-ledmSgQp92834stI .milestoneText{font-style:italic}#mermaid-svg-ledmSgQp92834stI .doneCritText0,#mermaid-svg-ledmSgQp92834stI .doneCritText1,#mermaid-svg-ledmSgQp92834stI .doneCritText2,#mermaid-svg-ledmSgQp92834stI .doneCritText3{fill:#000 !important}#mermaid-svg-ledmSgQp92834stI .activeCritText0,#mermaid-svg-ledmSgQp92834stI .activeCritText1,#mermaid-svg-ledmSgQp92834stI .activeCritText2,#mermaid-svg-ledmSgQp92834stI .activeCritText3{fill:#000 !important}#mermaid-svg-ledmSgQp92834stI .titleText{text-anchor:middle;font-size:18px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-ledmSgQp92834stI g.classGroup text{fill:#9370db;stroke:none;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:10px}#mermaid-svg-ledmSgQp92834stI g.classGroup text .title{font-weight:bolder}#mermaid-svg-ledmSgQp92834stI g.clickable{cursor:pointer}#mermaid-svg-ledmSgQp92834stI g.classGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-ledmSgQp92834stI g.classGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-ledmSgQp92834stI .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5}#mermaid-svg-ledmSgQp92834stI .classLabel .label{fill:#9370db;font-size:10px}#mermaid-svg-ledmSgQp92834stI .relation{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-ledmSgQp92834stI .dashed-line{stroke-dasharray:3}#mermaid-svg-ledmSgQp92834stI #compositionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-ledmSgQp92834stI #compositionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-ledmSgQp92834stI #aggregationStart{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-ledmSgQp92834stI #aggregationEnd{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-ledmSgQp92834stI #dependencyStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-ledmSgQp92834stI #dependencyEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-ledmSgQp92834stI #extensionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-ledmSgQp92834stI #extensionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-ledmSgQp92834stI .commit-id,#mermaid-svg-ledmSgQp92834stI .commit-msg,#mermaid-svg-ledmSgQp92834stI .branch-label{fill:lightgrey;color:lightgrey;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-ledmSgQp92834stI .pieTitleText{text-anchor:middle;font-size:25px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-ledmSgQp92834stI .slice{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-ledmSgQp92834stI g.stateGroup text{fill:#9370db;stroke:none;font-size:10px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-ledmSgQp92834stI g.stateGroup text{fill:#9370db;fill:#333;stroke:none;font-size:10px}#mermaid-svg-ledmSgQp92834stI g.statediagram-cluster .cluster-label text{fill:#333}#mermaid-svg-ledmSgQp92834stI g.stateGroup .state-title{font-weight:bolder;fill:#000}#mermaid-svg-ledmSgQp92834stI g.stateGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-ledmSgQp92834stI g.stateGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-ledmSgQp92834stI .transition{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-ledmSgQp92834stI .stateGroup .composit{fill:white;border-bottom:1px}#mermaid-svg-ledmSgQp92834stI .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px}#mermaid-svg-ledmSgQp92834stI .state-note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-ledmSgQp92834stI .state-note text{fill:black;stroke:none;font-size:10px}#mermaid-svg-ledmSgQp92834stI .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.7}#mermaid-svg-ledmSgQp92834stI .edgeLabel text{fill:#333}#mermaid-svg-ledmSgQp92834stI .stateLabel text{fill:#000;font-size:10px;font-weight:bold;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-ledmSgQp92834stI .node circle.state-start{fill:black;stroke:black}#mermaid-svg-ledmSgQp92834stI .node circle.state-end{fill:black;stroke:white;stroke-width:1.5}#mermaid-svg-ledmSgQp92834stI #statediagram-barbEnd{fill:#9370db}#mermaid-svg-ledmSgQp92834stI .statediagram-cluster rect{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-ledmSgQp92834stI .statediagram-cluster rect.outer{rx:5px;ry:5px}#mermaid-svg-ledmSgQp92834stI .statediagram-state .divider{stroke:#9370db}#mermaid-svg-ledmSgQp92834stI .statediagram-state .title-state{rx:5px;ry:5px}#mermaid-svg-ledmSgQp92834stI .statediagram-cluster.statediagram-cluster .inner{fill:white}#mermaid-svg-ledmSgQp92834stI .statediagram-cluster.statediagram-cluster-alt .inner{fill:#e0e0e0}#mermaid-svg-ledmSgQp92834stI .statediagram-cluster .inner{rx:0;ry:0}#mermaid-svg-ledmSgQp92834stI .statediagram-state rect.basic{rx:5px;ry:5px}#mermaid-svg-ledmSgQp92834stI .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#efefef}#mermaid-svg-ledmSgQp92834stI .note-edge{stroke-dasharray:5}#mermaid-svg-ledmSgQp92834stI .statediagram-note rect{fill:#fff5ad;stroke:#aa3;stroke-width:1px;rx:0;ry:0}:root{--mermaid-font-family: '"trebuchet ms", verdana, arial';--mermaid-font-family: "Comic Sans MS", "Comic Sans", cursive}#mermaid-svg-ledmSgQp92834stI .error-icon{fill:#522}#mermaid-svg-ledmSgQp92834stI .error-text{fill:#522;stroke:#522}#mermaid-svg-ledmSgQp92834stI .edge-thickness-normal{stroke-width:2px}#mermaid-svg-ledmSgQp92834stI .edge-thickness-thick{stroke-width:3.5px}#mermaid-svg-ledmSgQp92834stI .edge-pattern-solid{stroke-dasharray:0}#mermaid-svg-ledmSgQp92834stI .edge-pattern-dashed{stroke-dasharray:3}#mermaid-svg-ledmSgQp92834stI .edge-pattern-dotted{stroke-dasharray:2}#mermaid-svg-ledmSgQp92834stI .marker{fill:#333}#mermaid-svg-ledmSgQp92834stI .marker.cross{stroke:#333}:root { --mermaid-font-family: "trebuchet ms", verdana, arial;} #mermaid-svg-ledmSgQp92834stI {color: rgba(0, 0, 0, 0.75);font: ;}

@SpringBootApplication
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan
@Configuration
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
@Import(AutoConfigurationPackages.Registrar.class)
ImportBeanDefinitionRegistrar
注册扫描路径到全局变量
ImportSelector通过
SpringFactoriesLoader.loadFactoryNames
加载META-INF/spring.factories中的
EnableAutoConfiguration属性的类
@Configuration + @Bean
完成自动装配

49、如何理解Springboot 中的starter

使用spring + springmvc使用,如果需要引入mybatis等框架,需要到xml中定义mybatis需要的bean

starter就是定义一个starter的jar包,写-个@Configuration配置类、将这些bean定义在里面,然后在starter包的META-INF/spring.factories中写入该配置类,springboot会按照约定来加载该配置类

开发人员只需要将相应的starter包依赖引进应用,进行相应的属性配置(使用默认配置时,不需要配置), 就可以直接进行代码开发,使用对应的功能了,比如mybatis-spring-boot–starter, spring-boot-starter-redis

50、什么是嵌入式服务器?为什么要使用嵌入式服务器?

节省了下载安装tomcat,应用也不需要再打war包,然后放到webapp目录下再运行

只需要一个安装了Java的虚拟机,就可以直接在上面部署应用程序了

springboot已经内置了tomcat.jar,运行main方法时会去启动tomcat,并利用tomcat的spi机制加载springmvc

51、mybatis的优缺点

优点:

1、基于SQL语句编程,相当灵活,不会对应用程序或者数据库的现有设计造成任何影响,SQL写在XML里,解除sql与程序代码的耦合,便于统一管理;提供XML标签,支持编写动态SQL语询,可重用。

2、与JDBC相比,减少了50%以上的代码量,消除了JDBC大量冗余的代码,不需要手动开关连接; .

3、很好的与各种数据库兼容(因为MyBatis使用JDBC来连接数据库,所以只要JDBC支持的数据库MyBatis都支持)。

4、能够与Spring很好的集成;

5、提供映射标签,支持对象与数据库的ORM字段关系映射;提供对象关系映射标签,支持对象关系组件维护。

缺点:

1、SQL语句的编写工作量较大,尤其当字段多、关联表多时,对开发人员编写SQL语句的功底有一 定要求。

2、SQL语句依赖于数据库,导致数据库移植性差, 不能随意 更换数据库。

52、Mybatis 与 Hibernate 有哪些不同

开发速度的对比:

Hibernate的真正掌握要比Mybatis难些。Mybatis框架相对简单很容易上手,但也相对简陋些。

比起两者的开发速度,不仅仅要考虑到两者的特性及性能,更要根据项目需求去考虑究竟哪一个更适合项目开发,比如:一个项目中用到的复杂查询基本没有,就是简单的增删改查,这样选择hibernate效率就很快了 ,因为基本的sql语句已经被封装好了,根本不需要你去写sql语句,这就节省了大量的时间,但是对于一个大型项目,复杂语句较多,这样再去选择hibernate就不是一个太好的选择, 选择mybatis就 会加快许多,而且语句的管理也比较方便。

开发工作量的对比:

Hibernate和MyBatis都有相应的代码生成工具。可以生成简单基本的DAO层方法。针对高级查询,Mybatis需要手动编写SQL语句,以及ResultMap。而Hibernate有良好的映射机制,开发者无需关心SQL的生成与结果映射,可以更专注于业务流程

SQL优化方面:

Hibernate的查询会将表中的所有字段查询出来,这一点会有性能消耗。 Hibernate也可以自己写SQL来指定需要查询的字段,但这样就破坏了Hibernate开发的简洁性。而Mybatis的SQL 是手动编写的,所以可以按需求指定查询的字段。

Hibernate HQL语句的调优需要将SQL打印出来,而Hibernate的SQL被很多 人嫌弃因为太丑了。MyBatis的SQL是自己手动写的所以调整方便。但Hibernate具有自 己的日志统计。Mybatis本身不带日志统计,使用Log4j进行日志记录。

对象管理的对比:

Hibernate是完整的对象/关系映射解决方案,它提供了对象状态管理(state management)的功能,使开发者不再需要理会底层数据库系统的细节。也就是说,相对于常见的JDBC/SQL持款层方案中需要管理SQL语句,Hibernate采用了更自然的面向对象的视角来持久化Java应用中的数据。

换句话说,使用Hibernate的开发者应该总是关注对象的状态(state) ,不必考虑SQL语句的执行。这部分细节已经由Hibernate掌管妥当,只有开发者在进行系统性能调优的时候才需要进行了解。而MyBatis在这一 块没有文档说明,用户需要对对象自己进行详细的管理。

缓存机制对比:

相同点:都可以实现自己的缓存或使用其他第三方缓存方案,创建适配器来完全覆盖缓存行为。

不同点: Hibernate的 二级缓存配置在SessionFactory生成的配置文件中进行详细配置,然后再在具体的表_对象映射中配置是哪种缓存。

MyBatis的二级缓存配置都是在每个具体的表对象映射中进行详细配置,这样针对不同的表可以自定义不同的缓存机制。并且Mybatis可以在命名空间中共享相同的缓存配置和实例,通过Cache-ref来实现。

两者比较:因为Hibernate对查询对象有着良好的管理机制,用户无需关心SQL。所以在使用二级缓存时如果出现脏数据,系统会报出错误并提示。

而MyBatis在这一方面, 使用二级缓存时需要特别小心。如果不能完全确定数据更新操作的波及范围,避免Cache的盲目使用。否则,脏数据的出现会给系统的正常运行带来很大的隐患。

Hibernate功能强大,数据库无关性好,O/R映射能力强,如果你对Hibernate相当精通,而且对Hibernate进行了适当的封装,那么你的项目整个持久层代码会相当简单,需要写的代码很少,开发速度很快,非常爽。

Hibernate的缺点就是学习门槛不低,要精通门槛更高,而且怎么设计O/R映射,在性能和对象模型之间如何权衡取得平衡,以及怎样用好Hibernate方面需要你的经验和能力都很强才行。

iBATIS入i门简单,即学即用,提供了数据库查询的自动对象绑定功能,而且延续了很好的SQL使用经验,对于没有那么高的对象模型要求的项目来说,相当完美。

iBATIS的缺点就是框架还是比较简陋,功能尚有缺失,虽然简化了数据绑定代码,但是整个底层数据库查询实际还是要自己写的,工作量也比较大,且不太容易适应快速数据库修改。

53、Mybatis中#{}和${}区别

#{}是预编译处理、是占位符,${}是字符串替换、 是拼接符。

Mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement来赋值;

Mybatis在处理 时 , 就 是 把 {}时,就是把 时,就是把{}替换成变量的值,调用Statement来赋值;

#{}的变量替换是在DBMS中、变量替换后,#{} 对应的变量自动加上单引号

的 变 量 替 换 是 在 D B M S 外 、 变 量 替 换 后 , {}的变量替换是在DBMS外、变量替换后, 的变量替换是在DBMS外、变量替换后,{} 对应的变量不会加上单引号

使用#{}可以有效的防止SQL注入,提高系统安全性。

54、简述Mybatis的插件运行原理,如何编写一个插件

Mybatis 只支持针对ParameterHandler、ResultSetHandler、 StatementHandler、 Executor 这4种接口的插件,Mybatis 使用JDK的动态代理,为需要拦 截的接口生成代理对象以实现接口方法拦截功能,每当执行这4种接口对象的方法时,就会进入拦截方法,具体就是InvocationHandler的invoke()方法,拦截那些你指定需要拦截的方法。

编写插件:实现Mybatis的Interceptor接口并复写intercept()方法,然后在给插件编写注解,指定要拦截哪一个接口的哪些方法即可,在配置文件中配置编写的插件。

@Intercepts({
@Signature(type = StatementHandler.class,method = "query",args ={Statement.class,ResultHandler.class}),
@Signature(type = StatementHandler.class,method = "update",args ={Statement.class}),
@Signature(type = StatementHandler.class,method = "batch",args = {Statement.class }           })
@Component
invocation.proceed();//执行具体的业务逻辑

55、索引的基本原理

索引用来快速地寻找那些具有特定值的记录。如果没有索引,一般来说执行查询时遍历整张表。

索弓|的原理:就是把无序的数据变成有序的查询

1.把创建了索引的列的内容进行排序

2.对排序结果生成倒排表

3.在倒排表内容上拼上数据地址链

4.在查询的时候,先镎到倒排表内容,再取出数据地址链,从而拿到具体数据

56、mysql聚簇和非聚簇索引的区别

都是使用B+树的数据结构

聚簇索引:将数据存储与索引放到了一块、并且是按照一定的顺序组织的, 找到索弓|也就找到了数据,数据的物理存放顺序与索引顺序是一致的, 即:只要索弓|是相邻的,那么对应的数据一定也是相邻地存放在磁盘上的

非聚簇索引:叶子节点不存储数据、存储的是数据行地址,也就是说根据索弓|查找到数据行的位置再取磁盘查找数据,这个就有点类似一本树的目录,比如我们要找第三章第一节, 那我们先在这个目录里面找,找到对应的页码后再去对应的页码看文章。

优势:
1、查询通过聚簇索引可以直接获取数据,相比非聚簇索引需要第二次查询(非覆盖索引的情况下)效率要高
2、聚簇索引对于范围查询的效率很高,因为其数据是按照大小排列的
3、聚簇索引适合用在排序的场合,非聚簇索引不适合

劣势:
1、维护索引很昂贵,特别是插入新行或者主键被更新导至要分页(page sp1it)的时候。建议在大量插入新行后,选在负载较低的时间段,通过0PTIMIZE TABLE优化表,因为必须被移动的行数据可能造成碎片。使用独享表空间可以弱化碎片
2、表因为使用UUId (随机ID)作为主键,使数据存储稀疏,这就会出现聚族索引有可能有比全表扫面更慢,所以建议使用int的auto_ increment作为 主键
3、如果主键比较大的话,那辅助索引将会变的更大,因为辅助索引的叶子存储的是主键值;过长的主键值,会导致非叶子节点占用占用更多的物理空间

InnoDB中一定有主键,主键一定是聚簇索引, 不手动设置、则会使用unique索引, 没有unique索引,则会使用数据库内部的一个行的隐藏id来当作主键索引。在聚簇索引之上创建的索引|称之为辅助索引,辅助索弓|访问数据总是需要二次查找,非聚簇索弓|都是辅助索引,像复合索引、前缀索引、唯一索引,辅助索引叶子节点存储的不再是行的物理位置,而是主键值

MyISM使用的是非聚簇索引,没有聚簇索引,非聚簇索引的两棵B+树看.上去没什么不同,节点的结构完全-致只是存储的内容不同而已,主键索引B+树的节点存储了主键,辅助键索引B+树存储了辅助键。表数据存储在独立的地方,这两颗B+树的叶子节点都使用一个地址指向真正的表数据,对于表数据来说,这两个键没有任何差别。由于索引|树是独立的,通过辅助键检索无需访问主键的索引|树。

如果涉及到大数据量的排序、全表扫描、count之 类的操作的话,还是MyISAM占优势些,因为索引所占空间小,这些操作是需要在内存中完成的。

57、mysql索引的数据结构,各自优劣

索弓的数据结构和具体存储引擎的实现有关,在MySQL 中使用较多的索引有Hash索引,B+树索引等, InnoDB存储引擎的默认索引实现为: B+树索引。 对于哈希索引来说,底层的数据结构就是哈希表,因此在绝大多数需求为单条记录查询的时候,可以选择哈希索引,查询性能最快;其余大部分场景,建议选择BTree索引。

B+树:
B+树是一个平衡的多叉树,从根节点到每个叶子节点的高度差值不超过1,而且同层级的节点间有指针相互链接。在B+树上的常规检索,从根节点到叶子节点的搜索效率基本相当,不会出现大幅波动,而且基于索引的顺序扫描时,也可以利用双向指针快速左右移动,效率非常高。因此,B+树索引被广泛应用于数据库、文件系统等场景。

哈希索引:
哈希索引就是采用一定的哈希 算法,把键值换算成新的哈希值,检索时不需要类似B+树那样从根节点到叶子节点逐级查找,只需一次哈希算法即可立刻定位到相应的位置,速度非常快

如果是等值查询,那么哈希索引明显有绝对优势,因为只需要经过一次算法即可找到相应的键值;前提是键值都是唯一的。如果键值不是唯一的,就需要先找到该键所在位置,然后再根据链表往后扫描, 直到找到相应的数据;

如果是范围查询检索,这时候哈希索引就亳无用武之地了,因为原先是有序的键值,经过哈希算法后,有可能变成不连续的了,就没办法再利用索引完成范围查询检索;

哈希索引也没办法利用索引|完成排序,以及like 'xxx%6’这样的部分模糊查询(这种部分模糊查询,实本质上也是范围查询;

哈希索引也不支持多列联合索弓的最左匹配规则;

B+树索弓的关键字检索效率比较平均,不像B树那样波动幅度大。在有大量重复键值情况下,哈希索引的效率也是极低的,因为存在哈希碰撞问题。

58、索引的设计原则

查询更快、占用空间更小

1.适合索引|的列是出现在where子句中的列,或者连接子句中指定的列

2.基数较小的表,索引效果较差,没有必要在此列建立索引

3.使用短索引,如果对长字符串列进行索引,应该指定一个前缀长度,这样能够节省大量索引空间,如果搜索词超过索引前缀长度,则使用索弓|排除不匹配的行,然后检查其余行是否可能匹配。

4.不要过度索引。索弓|需要额外的磁盘空间,并降低写操作的性能。在修改表内容的时候,索引会进行更新甚至重构,索弓列越多,这个时间就会越长。所以只保持需要的索弓|有利于查询即可。

5.定义有外键的数据列-定要建立索引。

6.更新频繁字段不适合创建索引

7.若是不能有效区分数据的列不适合做索引|列(如性别,男女未知,最多也就三种,区分度实在太低)

8.尽量的扩展索引,不要新建索引。比如表中已经有a的索引,现在要加(a,b)的索引, 那么只需要修改原来的索引即可。

9.对于那些查询中很少涉及的列,重复值比较多的列不要建立索引。

10.对于定义为text、image和bit的数据类型的列不要建立索引。

59、MySQL锁的类型有那些?

基于锁的属性分类:共享锁、排他锁。

基于锁的粒度分类:行级锁(INNODB)、表级锁(INNODB、 MYISAM)、 页级锁(BDB引擎)、记录锁、间隙锁、临键锁。

基于锁的状态分类:意向共享锁、意向排它锁。

  • 共享锁(Share Lock)

    共享锁又称读锁,简称S锁; 当一个事务为数据加上读锁之后,其他事务只能对该数据加读锁,而不能对数据加写锁,直到所有的读锁释放之后其他事务才能对其进行加持写锁。共享锁的特性主要是为了支持并发的读取数据,读取数据的时候不支持修改,避免出现重复读的问题。

  • 排他锁(eXclusive Lock)

    排他锁又称写锁,简称X锁; 当- 个事务为数据加上写锁时,其他请求将不能再为数据加任何锁,直到该锁释放之后,其他事务才能对数据进行加锁。排他锁的目的是在数据修改时候,不允许其他人同时修改,也不允许其他人读取。避免了出现脏数据和脏读的问题。

  • 表锁

    表锁是指上锁的时候锁住的是整个表,当下一个事务访问该表的时候,必须等前一个 事务释放了锁才能进行对表进行访问;

    特点:粒度大, 加锁简单,容易冲突;

  • 行锁

    行锁是指上锁的时候锁住的是表的某一行或多行记录, 其他事务访问同一-张表时,只有被锁住的记录不能访问,其他的记录可正常访问;

    特点:粒度小,加锁比表锁麻烦,不容易冲突,相比表锁支持的并发要高;

  • 记录锁(Record Lock)

    记录锁也属于行锁中的一种,只不过记录锁的范围只是表中的某一条记录,记录锁是说事务在加锁后锁住的只是表的某一条记录。

    精准条件命中,并且命中的条件字段是唯一索引

    加了记录锁之后数据可以避免数据在查询的时候被修改的重复读问题,也避免了在修改的事务未提交前被其他事务读取的脏读问题。

  • 页锁

    页级锁是MySQL中锁定粒度介于行级锁和表级锁中间的一种锁。 表级锁速度快,但冲突多,行级冲突少,但速度慢。
    所以取了折衷的页级,一次锁定相邻的一组记录。
    特点:开销和加锁时间界于表锁和行锁之间;会出现死锁:锁定粒度界于表锁和行锁之间,并发度一般

  • 间隙锁(Gap Lock)

    属于行锁中的一种,间隙锁是在事务加锁后其锁住的是表记录的某一个区间,当表的相邻ID之间出现空隙则会形成一个区间,遵循左开右闭原则。

    范围查询并且查询未命中记录,查询条件必须命中索引、间隙锁只会出现在REPEATABLE READ (重复读)的事务级别

    触发条件:防止幻读问题,事务并发的时候,如果没有间隙锁,就会发生如下图的问题,在同一个事务里,A事务的两次查询出的结果会不一样。

    比如表里面的数据ID为1,4,5,7,10 , 那么会形成以下几个间隙区间,-n-1区间,1-4区间, 7-10区间,10-n区间(-n代表负无穷大, n代表正无穷大)

  • 临建锁(Next-Key Lock)

    也属于行锁的一种,并且它是INNODB的行锁默认算法,总结来说它就是记录锁和间隙锁的组合,临键锁会把查询出来的记录锁住,同时也会把该范围查询内的所有间隙空间也会锁住,再之它会把相邻的下一个区间也会锁住

    触发条件:范围查询并命中,查询命中了索引。

    结合记录锁和间隙锁的特性,临键锁避免了在范围查询时出现脏读、重复读、幻读问题。加了临键锁之后,在范围区间内数据不允许被修改和插入。

如果当事务A加锁成功之后就设置一个状态告诉后面的人, 已经有人对表里的行加了一个排他锁了,你们不能对整个表加共享锁或排它锁了,那么后面需要对整个表加锁的人只需要获取这个状态就知道自己是不是可以对表加锁,避免了对整个索引树的每个节点扫描是否加锁,而这个状态就是意向锁。

  • 意向共享锁

    当一个事务试图对整个表进行加共享锁之前,首先需要获得这个表的意向共享锁。

  • 意向排他锁

    当一个事务试图对整个表进行加排它锁之前,首先需要获得这个表的意向排它锁。

60、mysql执行计划怎么看

执行计划就是sql的执行查询的顺序,以及如何使用索引查询,返回的结果集的行数

EXPLAIN SELECT * from A where X=? and Y=?

id select_type table partitions type possible_keys key key_len ref rows filtered Extra
  1. id :是一个有顺序的编号,是查询的顺序号,有几个select就显示几行。id的顺序是按select出现的顺序增长的。id列的值越大执行优先级越高越先执行,id列的值相同则从上往下执行,id列的值为NULL最后执行。

  2. selectType 表示查询中每个select子句的类型

    • SIMPLE: 表示此查询不包含UNION查询或子查询

    • PRIMARY: 表示此查询是 最外层的查询(包含子查询)

    • SUBQUERY: 子查询中的第一个SELECT

    • UNION: 示此查询是UNION的第二或随后的查询

    • DEPENDENT UNION: UNION 中的第二个或后面的查询语句,取决于外面的查询

    • UNION RESULT, UNION的结果

    • DEPENDENT SUBQUERY:子查询中的第一个SELECT,取决于外面的查询.即子查询依赖于外层查询的结果.

    • DERIVED: 衍生,表示导出表的SELECT (FROM子句的子查询)

  3. table:表示该语句查询的表

  4. type:优化sql的重要字段,也是我们判断sql性能和优化程度重要指标。他的取值类型范围:

    • const:通过索引一次命中,匹配一行数据
    • system:表中只有一行记录, 相当于系统表;
    • eq_ref:唯一性索引扫描,对于每个索引键 ,表中只有一条记录与之匹西配
    • ref:非唯一性索引 扫描,返回匹配某个值的所有
    • range:只检索给定范围的行,使用一个索引来选择行, 一般用于between、<、>;
    • index:只遍历索引树;
    • ALL:表示全表扫描,这个类型的查询是性能最差的查询之一。那么基本就是随着表的数量增多,执行效率越慢。

    执行效率: ALL < index < range< ref< eq_ref < const < system。最好是避免ALL和index

  5. possible_ keys:它表示Mysq|在执行该sq|语句的时候,可能用到的索引信息,仅仅是可能,实际不一定会用到。

  6. key:此字段是mysql在当前查询时所真正使用到的索引。他是possible_ keys的子集

  7. key_Jen;表示查询优化器使用了索引的字节数,这个字段可以评估组合索引是否完全被使用,这也是我们优化sq时,评估索可的重要指标

  8. ref :索引字段

  9. rows: mysql 查询优化器根据统计信息,估算该sq|返回结果集需要扫描读取的行数,这个值相关重要,索引优化之后,扫描读取的行数越多说明素引设置不对 或者字段传入 的类型之类的问题说叩要优化空间越大

  10. filtered.返回结果的行占需要读刹的行rows列的道的百货比,就是百分比越高,完归需要查间到数据越准确,百分比越小,说明查询到的数据量大,而结果集很少

  11. extra

    • using filesort: 表示mysql对结果集进行外部排序,不能通过索弓顺序达到排序效果。-般有using filesort都建议仇化去掉,因为这样的查询cpu资源消耗大,延时大。
    • using 1dex:覆盖索引扫描,表示查询在索引树中就可查找所需数据,不用扫描表数据文件,往往说明性能不错。
    • using temporary:查询有使用临时表, -般出现于排序,分组和多表join的情况,查询效率不高, 建议优化。
    • using where : sql使用了where过滤效率较高。

61、事务的基本特性和隔离级别

事务基本特性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串行,一般是不会使用的,他会给每一行读取的数据加锁, 会导致大量超时和锁竞争的问题。

**脏读(Drity Read)

100道java面试题相关推荐

  1. 这100道Java面试题,面试不是什么难事了!

    临近毕业季,大批同学涌入职场,又有大量的职场人打算跳槽,在这一重要节点,Java程序员该如何把握好时机,应付好面试官,找到理想的工作? Java Java序列化是什么?需要在何种情况下进行序列? 简而 ...

  2. 100道Java笔试题

    欲知详情,请点击http://mouselearnjava.iteye.com/blog/2165577 转载于:https://blog.51cto.com/macxiao/1588940

  3. ie 访问 java接口_2019年面试总结,100道Java程序员面试题(含答案)分享

    2019年即将结束,一边是大批同学涌入职场,另一边是大群职场人打算跳槽,在这个重要的节点,Java程序员如何才能把握时机,搞定面试官,拿到一份心仪的工作呢? 除了掌握扎实的专业技能之外,你还需要一份& ...

  4. 稍微有点难度的10道java面试题,你会几道?

    转载自 稍微有点难度的10道java面试题,你会几道? 1.jvm对频繁调用的方法做了哪些优化? 2.常见的攻击手段有哪些?如何防范? 3.restful api有哪些设计原则? 4.hessian是 ...

  5. hashmap是有序的吗_这里有675道Java面试题,你准备好接招了吗?(完整版)

    上周发布了418道Java面试题之后, 有粉丝留言:希望可以尽快更新题集. 这次,675道面试题,全部送给你! 还有粉丝留言:不知道怎么获取答案? 分享本文至朋友圈,集赞3个及以上,截图发送公众号对话 ...

  6. 微软的100道算法面试题(终结版)

    前言 数据结构与算法的重要性已不言而喻,最近,我整理出十大经典排序算法.五大常用算法总结,今天特意整理出微软面试的100题,若有不足之处,欢迎指正!由于篇幅过长,前30道题目写在上一篇,大家可以进我的 ...

  7. java腾讯字符串面试题_面试百度、阿里、腾讯,这134道Java面试题你会多少?

    这里一共是134道Java面试题,看看你能对几道吧! 1. Java 语言有哪些特点 2. 面向对象和面向过程的区别 3. 关于 JVM JDK 和 JRE 最详细通俗的解答 4. Oracle JD ...

  8. 建议收藏 100 道 Linux 面试题 附答案

    关注公众号"Java后端技术全栈" 回复"000"获取程序员必备电子书 大家好,我是老田,今天我给大家分享100道Linux面试题. 本文一共 3万多字,分别从 ...

  9. 精选30道Java笔试题解答

    精选30道Java笔试题解答       都是一些非常非常基础的题,是我最近参加各大IT公司笔试后靠记忆记下来的,经过整理献给与我一样参加各大IT校园招聘的同学们,纯考Java基础功底,老手们就不用进 ...

最新文章

  1. 【廖雪峰Python学习笔记】错误、调试、测试
  2. 部署exchange2010三合一:之七:安装证书服务器
  3. Python操作数据库之 MySQL
  4. 给GridView中的buttonField添加一个删除确认功能
  5. sql update 日期减6个月_【干货】SQL基础快速入门
  6. CentOS 初体验二: 切换语言,连接互联网
  7. Angular 下的 function
  8. LeetCode 1743. 从相邻元素对还原数组(拓扑排序)
  9. 为什么强烈禁止开发人员使用isSuccess作为变量名
  10. go error的理解
  11. CCF NOI1149 N皇后问题
  12. Haskell分解质因数
  13. CreateThread()和_beginthread()有什么不同?
  14. 微信小程序 选项卡的简单实例
  15. 移动端开发使用rem时动态设置html的字体大小
  16. 机器学习-胯下运球之Naive Bayes<朴素贝叶斯法>
  17. 切莫让这三只猫跑进管理工作中
  18. web服务器性能排名,主流Web服务器性能测试
  19. 软件测试之测试用例设计(三)
  20. Three.js - 使用 ThreeBSP 对模型进行布尔运算

热门文章

  1. Base64——加密和解密
  2. iOS - RunLoop 深入理解
  3. 卷积神经网络中二维卷积核与三维卷积核有什么区别?
  4. 使用EasyBCD引导安装Ubuntu系统
  5. 【VINS-Mono】RealsenseD435i运行VINS-Mono,在ubuntu18.04和opencv3和cv_bridge的报错记录
  6. 判断是否三角形 是什么三角形 解一元二次方程 if选择结构(java)
  7. 药品使用说明书 (转载)
  8. android垃圾软件还多吗,手机变慢是因为软件产生的垃圾过多吗?
  9. Android布局——Linearlayout线性布局
  10. Spring框架笔记