前言
简单来对前段时间面试过程中的一些涉及到的方面进行一个总结吧~
一、Spring
Spring是目前很常见的一个容器框架,主要包括了表现层(web层),业务层(service层),以及持久层(dao层)。核心的话主要是IOC(控制反转)和AOP(面向切面)。
主要组件包括了
1.SpringCore:
主要就是IOC。将实体类创建的任务抛给了spring,我们只需要用到的时候从工厂中取即可。解耦。
通过DI(依赖注入)进行实现,依赖注入主要有三种方法:构造函数注入;setter方法注入;接口注入。但是目前我们多通过springboot的注解进行注入(@Autowired-按照类型,@Resource-按照名称)。可以通过(@order和@dependon注解控制前后顺序,@order控制的是注入的顺序,@dependon控制的是创建类的循序。)
循环依赖的问题:可以通过setter注入,三级缓存的形式解决;@lazy延迟加载(即使用时再进行加载)
2.SpringAop:
上面提到的面向切面,主要用于对已有方法的增强。通过动态代理实现。
通过@aspect注解来定义一个切面类(就是增强的方法的内容)
通过@Component注解来声明该类为IOC容器中的bean
通过@Pointcut注解来定义切点(即被加强的方法对应的路径,可定义多个切点)
通知方法(即加强操作对于原方法操作的时间):
@Around:环绕通知,使用此注解标注的通知方法在目标前、后都被执行。
@Before:前置通知,会在通知方法使用之前被执行。
@After:后置通知,会在通知方法使用之后被执行,无论是否有异常都会被执行。
@AfterReturning:返回后通知,会在方法完成后被执行,有异常不会执行。
@AfterThrowing:异常后通知,会在通知方法发生异常后执行。
如果对应多个切面,可以通过@order注解来决定执行的前后顺序。
除了以上的应用,Aop还可以自定义注解的形式进行展示。
通过@target定义一个自定义注解类
通过@Rerention注解来定义生命周期,通常都是默认RUNTIME
通过@Documented,可以将改注解提取成一个javadoc文档
通过@Inherited注解,表明该注解可以被继承
声明完自定义注解类之后,将切点方法指向该注解类的路径,即可通过自定义注解来使用加强方法。
3.整合Mybatis
mybatis是一个ORM持久层框架,通过大量的xml注解,实现了数据库的连接,以及数据库查询操作。
首先通过ResourcesReader,读取xml配置文件,创建Reader对象 → 将Reader流对象以参数的形式插入,通过SqlsessionFactoryBuilder来创建SqlsessionFactory对象 → 通过Sqlsession对象创建各个Sqlsession,执行sql操作(mybatis自定义了一些数据库操作的方法,但是也同样支持使用自己写的sql语句)→ 执行完成之后,调用commit方法提交 → 对Sqlsession进行销毁。
通常每个xml文件都会有一个DAO与之对应,DAO的全路径就是对应的映射文件中的namespace;方法名对应的就是映射 Statement的id。查询结果根据resultMap进行映射返回实体类。
mybatis关键机制:
延迟加载:在存在关联对象时,只有在使用关联对象字段时,才会进行进行额外的关联查询。使用动态代理的方式,与关联的对象形成新的代理对象;在使用延迟加载时,代理对象会拦截方法调用,检查是否有关联对象属性,如果没有,则进行额外的关联查询。
动态sql:可以通过动态标签实现较为复杂的判断和查询。
缓存机制:一级缓存和二级缓存。其中一级缓存是sqlsession级别,二级缓存是mapper级别。
mybatis-plus:本质就是mybatis的一个加强版或者升级版,感觉没有太多需要说的。它在继承了mybatis的基础上,又新增了一些新的功能,让我们在使用过程中更加的简单方便。
例如:加入的固有类,只需要继承就可以实现简单的crud操作;加入了代码生成器,对实体类的封装也更加的简便,不需要再手动写映射文件。
4.spring事务
事务的特点:
原子性:一个事务中所有的方法,要不全都执行,要不全不执行。
一致性:需要从一个一致性的状态转变为另外一个一致性的状态,不会破坏结构。
隔离性:事务之间操作相互隔离,互不影响。
持久性:执行完方法的改变是永久的。
事务通常是用@Transactional 注解实现的,其中包括rollbackFor参数,用于定义异常回滚抛出的错误;isolation隔离的级别,通常使用DEFAULT为默认级别,即默认使用数据库的事务隔离级别;Propagation事务的传递类型。
事务的隔离级别:
读未提交:指可以读取到其他线程未提交的数据,可能造成脏读,幻读和不可重复读。
读已提交:可以读取到别的线程已经提交的,可以避免脏读。但是不同时间,读取到的数据可能会不同,因此还是会存在幻读和不可重复读的情况。
可重复读:确保了同一事务每次读取数据库信息都是一样的,解决了幻读的问题。但是如果其他线程对数据进行了修改,就会出现不可重复读的问题。(mysql默认的事务级别)
序列化:强制所有事务进行排序处理,规避掉了脏读幻读和不可重复度的问题,但是执行效率最慢。
事务失效的一些场景:
1.用非Public关键字修饰。
2.在同一个类中进行调用。
3.未指定抛出的异常,或者抛出异常配置错误,或使用try...catch对异常进行了捕获。
4.数据库不支持事务。
二、springboot
springboot是基于spring框架的一个更为简单方便的框架,加入大量的注解,大大减少了spring中xml配置文件。同时还内嵌了tomcat等中间件。
核心注解@SpringBootApplication,主要由三个注解组成
@Configuration:表明该类是一个配置类,可以向其注入组件
@enableAutoConfiguration:启动可自动装配,通过@import进行引入
@ComponentScan:扫描对应路径的包
三、JVM
加载器:核心类加载器;拓展类加载器;系统类加载器;自定义类加载器
内存模块:线程共享的内存模块包括堆和方法区;非线程共享的包括本地方法栈,程序计数器,虚拟机方法栈。
其中方法区主要存放静态常量,方法关键字等。
堆主要存放创建的对象等。垃圾回收机制主要就是针对堆中的对象进行回收。
栈中主要存放方法状态,局部变量等。线程结束之后会自动释放内存。
可能存在栈溢出和内存溢出的异常。
常用配置xms:初始化堆内存大小;xmx最大堆内存大小。
垃圾回收模块:
主要是针对堆中的垃圾进行回收,有两种判断对象是否可以删除的方法:
引用计数法:每次使用一次会对对象+1,释放后会-1,当计数为0的时候,判断改对象可以进行回收。
可达性分析法:从cg root开始执行,如果没有直接或者间接可以连接到对象,那么改对象即被标记为可进行回收
垃圾回收的算法:
标记删除法:对内存中的对象进行遍历判断,如果再使用进行标记,遍历完成后,清除没有标记的对象。
标记整理法:堆内存中的对象进行遍历判断,将存活的对象整理放到一起,添加一个边界,之后将边界外的全部对象进行回收处理。
复制删除法:将内存区分为两部分,当一部分满了的时候,将其中存活的复制到另外一部分,回收之前的部分。
分代删除法:将内存分为了年轻代和老年代,更具不用的需求,对年轻代和老年代分别使用不同的回收方法进行回收。(通常在年轻代中使用复制删除法,在老年代中使用标记删除或者标记整理法)
年轻代和老年代的内存是1:2,当经历回收大于15或者对象内存超过年轻代的1/2,那么该对象会进入老年代。年轻代进一步分区又分为了Edem : From Survivor : To Survivor = 8 : 1 : 1。
主要的一些垃圾回收器:Serial、ParNew、Parallel Scavenge、CMS、Serial Old、Parallel Old、G1
对于mysql的总结之后再进行补充,有不对的地方欢迎指出哈~