开源框架面试题目整理

目录

SpringIOC

SpringAOP

Spring的生命周期

Spring Bean作用域

Spring Bean作用域并发安全

Spring循环依赖

Spring@Async注解

同步调用和异步调用

Spring实现的线程池

@Async自定义线程池

依赖注入 DI

基于field注入

基于Setter注入

基于构造器注入

Spring中用到哪些设计模式

Mybatis一级缓存和二级缓存的区别

Mybatis一级缓存失效情况

Mybatis二级缓存失效情况

Mybatis中用到的设计模式有哪些


SpringIOC

控制反转(Inversion Of Control),将对象的创建和依赖关系(对象之间的依赖关系可以通过配置文件或者注解来建立)交给第三方容器处理,所有的对象创建都被容器控制。

SpringAOP

AOP(Aspect Oriented Programming)面向切面思想。Java是一个面向对象(OOP)的编程语言,当需要为多个不具有继承关系的对象引入一个公共行为时,例如日志记录、权限校验、事务管理、统计等功能,只能在每个对象里都引用公共行为,这样做不便于维护,而且有大量重复代码,AOP的出现弥补了OOP的这点不足。

给对象提供代理以控制对这个对象的访问,分为静态代理和动态代理,静态代理就是在程序运行前就已经存在代理类的字节码文件,代理类和原始类的关系在运行前就已经确定。动态代理类的源码是在程序运行期间通过JVM反射等机制动态生成,代理类和委托类的关系是运行时才确定的。JDK代理和Cglib代理两种动态代理,Spring框架在底层都集成了进去,无需担心实现动态生成代理

Spring的生命周期

Spring Bean的生命周期可以分为四个阶段,实例化、属性赋值、初始化、使用、销毁。Bean的实例化时机分两种,BeanFactory管理的bean是在使用到Bean时才会实例化,ApplicationContext管理的Bean在容器初始化时就会完成Bean的实例化。Srping中有一些独立的方法也会注入到容器里面,在bean的实例化前后,对bean进行一些相应处理。Bean容器先从配置文件中找到bean的定义,然后使用Java反射机制创建Bean的实例,对bean进行属性注入,然后调用setBeanName方法设置bean的名称,然后把bean的名称放到beanFactory里面,使用的时候从工厂里面取就可以了,使用完之后调用destroy()方法销毁即可。

Spring Bean作用域

Sping中bean的scope的值可以是singleton、prototype、request、session、global session。默认情况下是singleton。只有在web容器中才能使用request、session、global session。

singleton:单例模式,spring容器中有且仅有一个对象,init方法在创建容器时仅执行一次。关闭容器会导致bean实例的销毁,调用destroy方法一次。当spring创建applicationContext容器的时候,spring会初始化所有的该作用域实例,加上lazy-init就可以避免预处理。

prototype:原型模式,spring容器要创建同一类型的多个对象,对象的销毁由垃圾回收机制gc()控制,destroy方法将不会被执行,init方法在每个对象创建时均执行一次。每次通过getBean获取该bean就会新产生一个实例,创建后spring将不再对其管理。

request:每次请求都新产生一个实例,和prototype不同的是创建后接下来的管理spring依然在监听。

session:每次会话,同上。

global session:全局的web域,类似于servlet中的application。

Spring Bean作用域并发安全

Spring的bean默认是单例,在Controller中定义成员变量,多个请求进来,进入的都是同一个单例的Controller对象,并对此成员变量的值进行修改操作,多个请求互相影响,导致并发安全问题。

@Controller
public class HomeController {
    private int i;
    @GetMapping("testsingleton1")
    @ResponseBody
    public int test1() {
        return ++i;
    }
}

多次访问此url,可以看到每次的结果都是自增的,所以这样的代码显然是并发不安全的。

解决方案

让无状态的海量Http请求之间不受影响,可以采取以下几种措施:

1.单例变原型:对web项目可以Controller类上加注解@Scope("prototype")@Scope("request"),对非web项目,在Component类上添加注解@Scope("prototype")

优点:实现简单。

缺点:很大程度上增大了bean创建实例化销毁的服务器资源开销。线程隔离类ThreadLocal

2.线程隔离类ThreadLocal:将成员变量包装为ThreadLocal,以试图达到并发安全,同时打印出Http请求的线程名,修改代码如下:

@Controller
public class HomeController {
    private ThreadLocal i = new ThreadLocal<>();
    @GetMapping("testsingleton1")
    @ResponseBody
    public int test1() {
        if (i.get() == null) {
            i.set(0);
        }
        i.set(i.get().intValue() + 1);
        log.info("{} -> {}", Thread.currentThread().getName(), i.get());
        return i.get().intValue();
    }
}

多次访问此url测试一把,打印日志如下

[INFO ] 2019-12-03 11:49:08,226 com.cjia.ds.controller.HomeController.test1(HomeController.java:50)
http-nio-8080-exec-1 -> 1
[INFO ] 2019-12-03 11:49:16,457 com.cjia.ds.controller.HomeController.test1(HomeController.java:50)
http-nio-8080-exec-2 -> 1
[INFO ] 2019-12-03 11:49:17,858 com.cjia.ds.controller.HomeController.test1(HomeController.java:50)
http-nio-8080-exec-3 -> 1
[INFO ] 2019-12-03 11:49:18,461 com.cjia.ds.controller.HomeController.test1(HomeController.java:50)
http-nio-8080-exec-4 -> 1
[INFO ] 2019-12-03 11:49:18,974 com.cjia.ds.controller.HomeController.test1(HomeController.java:50)
http-nio-8080-exec-5 -> 1
[INFO ] 2019-12-03 11:49:19,696 com.cjia.ds.controller.HomeController.test1(HomeController.java:50)
http-nio-8080-exec-6 -> 1
[INFO ] 2019-12-03 11:49:22,138 com.cjia.ds.controller.HomeController.test1(HomeController.java:50)
http-nio-8080-exec-7 -&

你可能感兴趣的:(开源框架,面试,java,spring,spring,boot)