面试
1.索引优化和事务的四个属性:
索引优化:
1.避免在开头模糊查询(右模糊查询)
2.避免使用in和not in (连续数值时,用between代替)
3.避免使用or(用union代替)
4.避免对null值的判断(字段添加默认值0)
5.避免在where条件等号左侧进行表达式、函数操作
6.避免使用where 1=1,(有where条件就加and,没有就去掉where)
7.查询条件不用<>或者!=
8.有联合索引时,遵循最左匹配原则
9.隐式类型转换用不了索引
事务(ACID)
原子性:是不可分割的最小操作单位,要么同时成功,要么同时失败。
持久性:当事务提交或回滚后,数据库会持久化的保存数据。
隔离性:多个事务之间。相互独立,多个事务并发执行时,事物之间不影响其他事务的执行
一致性:事务操作前后,数据总量不变
2.springBoot的自动装配:
SpringBoot自动装配就是自动去把第三方组件的bean装载到ioc容器里面,不需要开发人员再去写bean的相关配置。
首先springBoot的启动是依靠main方法来实现的,main方法执行的是SpringApplication.run()方法,而SpringApplication.run()方法会创建spring的容器,并且刷新容器,在springBoot启动类上加,@SpringBootApplication注解就可以实现自动装配,在刷新容器的时候同时会去解析启动类上的注解,@SpringBootApplication注解是一个复合注解,真正实现自动装配注解的是@EnableAutoConfiguration
自动装配的实现主要依靠三个核心的关键技术:
1.引入starter,启动依赖组件的时候,这个组件要包含一个@Configuration配置类,在这个配置类中,我们需要通过@Bean这个注解去声明需要装配到ioc容器里面的bean对象
2.这个配置类是在放第三方的jar包里面,然后通过springBoot中,约定优于配置的这样一个理念,把这个配置类的全路径放在classpath:/META-INF/spring.factories文件里面,然后再用@EnableAutoConfiguration里@import注解引入的AutoConfigurationImportSelector这个类,经过一些核心方法,扫描所有jar包下META-INF的spring.factories文件,SpringBoot就可以知道第三方jar包里面这个配置类的位置,这个步骤主要使用到了Spring里面的SpringFactoriesLoader来完成的
3.SpringBoot拿到所有第三方jar包里面声明的配置类以后再通过spring提供的importSelector这样一个接口来实现对这些配置类的动态加载,从而去完成自动装配这样一个动作
在我看来,springBoot是一个约定大于配置的一个产物,所有在很多地方都会看到这一类的思想,它的出现可以更好的帮助开发人员聚焦在业务代码的编写上,而不需要去关心和业务无关的配置其实自动装配思想在SpringFrameWork3.x版本里面的
@Enable注解就已经有了实现的一个雏形,@Enable注解是一个模块驱动的意思,也就是说我们只需要增加@Enable注解,就能自动打开某个功能,而不需要针对这个功能去做Bean的配置,@Enable注解的底层也是去帮我们自动去完成这样一个模块相关bean的注入的以上就是我对springBoot自动装配的理解
3.spring:
轻量级,半成品,开源的
作用:方便解耦,简化开发,集成框架,
方便程序测试(基于Test测试),切面编程支持(aop),声明式事务支持@Transactional
降低JavaEE Api的使用难度
体系结构:
-
核心容器:Beans,Core,Context,SpringEI表达式
-
中间层技术:Aop,Aspects
-
应用层技术:数据访问与数据集成,Web集成,Web实现
-
基于Test测试
1.ioc、di、aop
ioc控制反转
概念:
-
就是由 Spring IOC 容器来负责对象的生命周期和对象之间的关系
-
使用对象时,由主动new产生对象转换为由Spring IOC容器来提供对象,此过程中对象的创建权由程序转移到Spring IOC容器
作用:
-
负责对象的创建、初始化等一系列工作,其中包含了数据层和业务层的类对象
-
被创建或被管理的对象在IOC容器中统称为Bean
-
IOC容器中放的是一个个Bean对象
di依赖注入:
概念:
- 在spring IOC容器中建立bean与bean之间的依赖关系的过程
- 业务层要用数据层的类对象,以前是自己new出来的,现在靠IOC容器注入进来
作用:
service层运行需要依赖dao层对象,IOC容器中虽然有service层对象和dao层对象,但是两者之间没有任何关系,需要把dao层对象交给service层,也就是说要绑定service层和dao层对象之间的关系
aop面向切面
无侵入式,面向切面编程,在程序运行期间,在不修改源码的情况下对方法进行功能增强
概述:
- AOP 的底层是通过 Spring 提供的动态代理技术实现的。在运行期间,Spring通过动态代理技术动态生成代理对象,代理对象方法执行时进行增强功能的介入,再去调用目标对象的方法,从而完成功能的增强。
动态代理技术:
- JDK 代理 : 基于接口的动态代理技术
- cglib 代理: 基于父类的动态代理技术
名字解释:
- 目标对象(Target ):
原始功能去掉共性功能对应的类产生的对象,这种对象是无法直接完成最终工作的
- 连接点(JoinPoint):
在SpringAOP中,理解为方法的执行
- 切入点(Pointcut ):
在SpringAOP中,一个切入点可以只描述一个具体方法,也可以匹配多个方法
一个具体方法:包下的接口中的无形参无返回值的方法
匹配多个方法:所有的save方法,所有的get开头的方法,所有以Dao结尾的接口中的任意方法,所有带有一个参数的方法
- 通知(Advice):
在切入点处执行的操作,也就是共性功能在SpringAop中,功能最终以方法的形式呈现
- 通知类:
定义通知的类
- 切面(Aspect):
描述通知与切入点的对应关系
- 代理对象( Proxy):
目标对象无法直接完成工作,需要对其进行功能回填,通过原始对象的代理对象实现
通知程序中的共性功能,在通知类中定义方法
切入点和通知类中方法的关系(切面)
连接点是所有方法
切入点表达式:
两种描述方式:
- execution(里面写接口方法);
- execution(里面写实现接口类的方法)
切入点表达式标准格式:
- 动作关键字( 访问修饰符 返回值 包名.类/接口名.方法名(参数) 异常名)
- 动作关键字:描述切入点的行为动作,例如execution表示执行到指定切入点
- 访问修饰符: public,private等,可以省略
- 返回值
- 包名
- 类/接口名
- 方法名
- 参数
- 异常名:方法定义中抛出指定异常,可以省略
拦截器
动态拦截方法调用的机制,运用aop思想
作用:
- 在指定方法调用前后执行预先设定后的代码
- 阻止原始方法执行
2.注解开发:
@Component,@Controllrt,@Service,@Repository,@Value
3.bean的生命周期:
1)当scope的取值为singleton时(系统默认的)
Bean的实例化个数:1个
Bean的实例化时机:Spring核心文件被加载时,实例化配置的Bean实例
Bean的生命周期:
对象创建:当应用加载,容器创建时,对象创建
对象运行:对象和容器共存亡,只要容器在,对象就一直存活
对象销毁:当应用卸载,容器销毁时,对象销毁
2)当scope的取值为prototype时
Bean的实例化个数:多个
Bean的实例化时机:当调用getBean()方法时实例化Bean
对象创建:当使用对象时,创建新的对象实例
对象运行:对象在使用中存在
对象销毁:当对象长时间不用时,会被 Java 的垃圾回收器回收了 ( jvm gc垃圾回收)
4.spring MVC:
实现Web MVC设计模式的轻量级Web框架
理念:
1.浏览器发送一个请求给后端服务器,后端服务器使用Servlet来接收和请求数据,如果所有的请求都交给Servlet来处理的话,所有的东西都耦合在一起,对后期的维护和扩展极为不利,所以将后端服务器Servlet拆分成三层,分别是web
、service
和dao
- 表现层(web):负责数据展示
- 业务层(service):负责业务处理
- 数据层(dao):负责数据操作
但是servlet处理请求和数据的时候,存在的问题是一个servlet只能单次处理一个请求
针对web层进行了优化,采用了MVC设计模式,
将其设计为controller
、view
和Model
- Model(模型):数据模型,用于封装数据
- View(视图):页面视图,用于数据数据
- Controller(Handle 处理器):根据用户需求处理程序逻辑
controller负责请求、数据接收,接收后将其转发给service进行业务处理,service层根据需要会调用dao层方法对数据进行增删改查,dao把数据处理完后将结果交给service,service再交给controller,controller根据需求组装成ModelAndView,并生成页面,转发给前端浏览器,这样做的好处就是controller可以处理多个请求,并对请求进行分发,执行不同的业务操作。
随着互联网的发展,mvc模式因为是同步调用,性能慢慢的跟不上需求,所以异步调用慢慢的走到了前台,是现在比较流行的一种处理方式,因为是异步调用,所以后端不需要返回view视图,将其去除,前端如果通过异步调用的方式进行交互,后台就需要将返回的数据转换成json格式进行返回。
`### web的三大组件:
处理器映射器,处理器适配器,试图解析器
1 dispatcherServlet 前置控制器,负责接收并处理所有的web请求,根据handlerMapping(处理器映射)找到具体的Controller(处理器),由controller完成具体的处理逻辑。
2 HandlerMapping(处理器映射器):负责处理web请求和具体的Controller之间的映射关系匹配。
3HandlerAdapter(处理器适配器) 通过 HandlerAdapter 对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行。 主要处理方法参数、相关注解、数据绑定、消息转换、返回值、调用视图解析器等等。
4.Controller(处理器):DispatherServlet的次级控制器,web请求的具体处理者。DispatherServlet获得handlerMapping的返回结果后,调用controller的处理方法处理当前的业务请求,处理完成后返回ModelAndView对象。
5 ViewResolver( 视图解析器):用来处理视图名与具体的view实例之间的映射对应关系。根据ModelAndView中的视图名查找相应的View实现类,然后将查找的结果返回给DispatcherServlet,DispatcherServlet最终会将ModelAndView中的模型数据交给返回的View处理最终的视图渲染工作。
Springmvc架构原理解析:
第一步:发起请求到前端控制器(DispatcherServlet)
第二步:前端控制器请求处理器映射器(HandlerMapping)查找 Handler,根据xml配置、注解进行查找
第三步:处理器映射器HandlerMapping向前端控制器返回Handler
第四步:前端控制器调用处理器适配器去执行Handler
第五步:处理器适配器去执行Handler
第六步:Handler执行完成给适配器返回ModelAndView
第七步:处理器适配器向前端控制器返回ModelAndView
ModelAndView是springmvc框架的一个底层对象,包括 Model和view
第八步:前端控制器请求视图解析器去进行视图解析
根据逻辑视图名解析成真正的视图(jsp)
第九步:视图解析器向前端控制器返回View
第十步:前端控制器进行视图渲染
视图渲染将模型数据(在ModelAndView对象中)填充到request域
第十一步:前端控制器向用户响应结果
4.mybatis(基于ORM思想)
半成品软件,基于java的持久层框架,内部封装了jdbc,使开发者只需要关注sql语句本身,而不需要花费精力去处理加载驱动、创建连接、创建statement等繁杂的过程。mybatis通过xml或注解的方式将要执行的各种 statement配置起来,并通过java对象和statement中sql的动态参数进行映射生成最终执行的sql语句。
最后mybatis框架执行sql并将结果映射为java对象并返回。采用ORM思想解决了实体和数据库映射的问题,对jdbc 进行了封装,屏蔽了jdbc api 底层访问细节,使我们不用与jdbc api 打交道,就可以完成对数据库的持久化操作。
缓存:
mybatis缓存是针对查询操作的
一级缓存默认开启,SqlSession级别的缓存
二级缓存,默认不开启,mapper 映射级别的缓存
隔离级别:
1.读未提交:脏读
一个事务在执行过程中读取到了其他事务还没有提交的数据
2.读已提交:
两次读取的数据不一样,自己事务没有提交的时候可以读取别的已经提交的事务。
3.可重复读:幻读
自己事务没有提交的时候,读不到已经提交的事务。
4.串行化:
避免 脏读,幻读的发生
5.重载和重写的区别:
重写
重写是子类对父类允许访问方法的实现过程进行重新编写, 返回值和形参都不能改变,访问修饰符不能做出更严格的限制,异常可以减少或删除,不能抛出新的或者更广的异常
重载
在一个类里面,方法名字相同,而形参不同,且必须修改。
返回类型可以相同也可以不同。
异常和访问修饰符没有严格限制
6."=="和"equals"的区别:
"=="是一种比较运算符,通常用于比较两个对象或对象的值是否相等
”equals“是一种方法,通常用于自定义类对象之间的比较
7.冒泡排序:
public static void main(String[] args) {
int[] arr={6,3,8,2,9,1};
System.out.println(Arrays.toString(arr));
for (int i=0;i<arr.length-1;i++){
for (int j=0;j<arr.length-1-i;j++){
int temp = 0;
if (arr[j]>arr[j+1]) {
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
System.out.println(Arrays.toString(arr));
}
8.String、StringBuilder、StringBuffer的区别及使用场景
String一旦定义就不可改变,可空赋值。操作少量数据时使用。
StringBuilder 可改变,线程不安全。操作单线程大量数据时使用。
StringBuffer 可改变,线程安全。操作多线程大量数据时使用。
9.int和Integer的区别
int是Java中的原始类型,Integer是Java为int提供的封装类
10.ArrayList、Vector和LinkedList的区别及使用场景
ArrayList和Vector都是使用数组方式存储数据
LinkedList 使用双向链表方式存储数据
11.List和Map的区别
List是存储单列数据的集合,Map是存储键值对双列数据的集合。
List存储的数据是有顺序且可重复的,Map存储的数据是无顺序,键不可重复,值可重复的。
12.Mybatis中 #{} 和 ${}的区别
#{}是预编译,可防止SQL注入。
${}是直接拼接在SQL语句中。
13.HashMap和HashTable的区别
HashMap是Map接口的实现,非线程安全,允许空键值。
HashTable是Dictionary的子类,线程安全,不允许空键值
14.HashMap底层实现原理和扩容机制
JDK1.8以前:数组+单链表的组合,以键值对的方式存储元素。
JDK1.8及以后:引入红黑树结构,添加元素时若链表个数大于8,链表会转换为红黑树,反之小于6时会修剪或还原成链表结构。
选择6和8可以有效防止频繁的链表和红黑树转换。
扩容机制:
存放新值时当前已有元素个数大于阈值。
存放新值时当前存放数据发生hash碰撞(当前key计算的hash值换算出来的数组下标位置已经存在值)
默认容量是16,负载因子0.75,所以扩容阈值是12。
每次扩容的容量是原有的2倍。
15.ORM
ORM全称是:Object Relational Mapping(对象关系映射),其主要作用是在编程中,把面向对象的概念跟数据库中表的概念对应起来。
一个对象,那就对应着一张表,对象的实例,就对应着表中的一条记录