JAVA面试题,框架篇

Spring框架

一、spring是什么?

Spring是一个轻量级的JAVA EE 开发框架,用于简化企业级应用程序的开发

二、spring有哪些特性?

DI:依赖注入,通过配置文件或者set注入,构造器注入的方式,在IOC容器中找到相应的bean对象并关联上当前声明的对象

IOC:控制反转,将类注册到IOC容器中并创建该类的bean对象,使用bean的生命周期来统一管理注入的对象;使用对象时可以直接从容器中取而不用去new,实现依赖倒置,解耦。

AOP:面向切面,通过切点将系统服务从业务逻辑中分离出来,解耦

事务管理:通过一套事务管理接口来应对不同数据源的事务

三、说说你对AOP的理解

面向切面是一种编程思想,定义了切点,切面和通知的概念;

  • 对于一个一般的程序来讲,我们可以把程序的执行步骤按照时间顺序在时间轴上做一个从上到下的纵向排序,正常的执行顺序就是按时间流动的顺序;

  • 现在假设每一个时间点会执行一个步骤,每一个步骤是一个相应的方法。AOP就把这些方法定义为一个个切点,将这些方法要额外执行的步骤定义为切面,使用通知将切点和切面连接。

  • 这些方法还是按照原来的时间轴顺序去执行,但是AOP把被拦截的方法横向添加了一个维度来处理要扩展的步骤。

  • 就是说原来方法的执行只跟时间有关,AOP的思想就是把方法的执行变成了跟时间和切面有关;从原来的一维(只有时间)变成了二维(时间+切面),以上是我个人的理解。

  • 更通俗的理解是:在不改变程序线性执行流程的基础上,添加了一个维度来处理横切关注点。

四、IOC是什么?

IOC是控制反转的意思,被spring管理的对象获得对象的过程由自身管理变成了由容器主动注入;spring实现控制反转主要是通过容器和依赖注入

  • 容器:底层是一个map,里面存放各种bean对象(被@repository,@service,@Controller,@Conponent注解标记的类和xml里面配置的bean),在项目启动的时候根据注解标记的类和xml文件中的全类名(路径加类名,确保类的唯一性)使用反射创建bean对象到map里。再通过bean的生命周期来实现统一管理容器中的对象

  • 依赖注入:在容器运行期间,通过set方式、构造器方式、自动注入方式,动态的将某种依赖关系注入到对象中。

五、BeanFactory和FactoryBean有什么区别?
  • BeanFactory:是spring的IOC容器的核心接口,提供了管理Bean的操作,比如获取Bean,检查Bean是否存在,确定Bean的作用域等等;常见的子接口有ApplicationContext,提供了更完整的功能。

  • FactoryBean:特殊的Bean对象,用于创建Bean;允许自定义Bean的创建逻辑:实现该接口的类,可以通过重写里边的getObject方法来创建复杂的Bean对象。

六、BeanFactory和ApplicationContext有什么区别?

两个都是用于管理bean的接口

功能上:

  • BeanFactory是最基础的IOC容器,提供了最基础的配置、创建、管理bean的功能

  • ApplicationContext是BeanFactory的子接口,包含Beanfactory的所有功能;统一了资源文件访问方式;还继承了MessageSource接口,支持国际化和本地化消息的处理;支持发布/订阅事件模型, 允许bean注册为监听器来响应容器中发生的特定事件。

初始化时机:

  • BeanFactory里的bean实例化是延迟进行的,调用getBean方法才会实例化,启动初期内存占用小;

  • ApplicationContext在启动时就会创建并初始化所有单例的bean,这种机制有助于在启动阶段发现bean的配置问题,但是启动初期占用的内存会比较大。

七、bean的生命周期
  1. 首先通过BeanDefintion接口获取bean的注册信息,比如类的全类名,是否为单例,是否延迟加载;

  2. 调用构造函数实例化Bean:在容器中创建Bean对象

  3. 依赖注入:将当前类与容器中的Bean对象关联起来,可以通过自动注入,set注入,构造器注入等方式

  4. 处理Aware接口:比如BeanNameAware(设置bean的名字),BeanFactoryAware(设置管理bean的IOC容器),是spring与bean通信的一种方式:通过他们的set方法,使Bean能够意识到它的运行环境,从而运行bean获取到环境信息。

  5. 执行BeanPostProcessor的前置处理方法,可以用来修改前面创建的Bean实例。

  6. 执行初始化方法,比如InitializingBean方法,或者加了@PostContruct注解的方法、配置文件中的init-method标签指定的方法。

  7. 执行BeanPostProcessor的后置处理方法,可能会进行AOP(产生代理对象);完成了bean的初始化。

  8. 使用bean

  9. 销毁bean

八、装饰器模式和代理模式的区别

装饰器模式是结构型模式,强调的不改变目标对象的前提下扩展目标对象的功能

代理模式是创建型模式,强调的是不改变目标对象的前提下创建代理对象来控制目标对象的行为,代理对象可以为目标对象扩展功能,

九、AOP使用了什么设计模式的思想?

使用了代理模式的思想,通过创建动态代理对象来控制目标方法的执行时机;代理对象有两种形式:

  • CGlib:没实现接口的类默认使用CGlib包创建代理对象,

  • JDK自带:实现了接口的类默认使用JDK自带的代理对象,需要手动创建代理类;可以在AOP配置中指定Proxy-target-class=true来指定CGlib代理模式

十、解释一下Spring中Bean的几种作用域

常用的

  • singleton(单例):默认,每个容器中只有一个bean的实例,单例模式

  • prototype:为每一个bean请求提供一个实例,在每次注入时都会创建一个新的对象。

  • request:在每个HTTP请求中创建一个单例对象,也就是说在单个请求中都会复用这一个单例对象

一般的

  • session:每个session中保存一个bean的实例,session过期后,bean就会失效

  • Application:在每个ServletContext的生命周期中复用一个单例对象。

  • websocket:在websocket的生命周期中复用一个单例对象。

十一、Spring的单例bean是安全的吗?

不安全;只是我们一般情况下用来创建bean的类是无状态的(bean的使用不依赖外部环境,外部无法对他进行修改);如果我们需要使用多例的bean,可以改变bean的作用域(将singleton改为prototype指定生成的bean为多例),或者使用锁来做保证

十二、Spring事务的实现方式

实现方式分为两种

  • 编程式事务:使用TransactionTemplate来实现,需要手动控制事务开始和提交或回滚,可以控制事务块的粒度,比较灵活,但是对业务代码具有侵入性。

  • 声明式事务:本质是使用AOP对执行事务的方法做拦截,在方法执行之前开始事务,方法执行结束提交或回滚事务;只需要在要使用事务的方法上添加@Transactional注解,就能自动开始和提交或回滚事务;

十三、spring事务的隔离级别

Spring事务隔离级别:数据库的隔离级别+数据库的默认隔离级别(不同数据库的默认隔离级别不同)

  • default:数据库的默认隔离级别

  • read uncommitted:未提交读

  • read committed:已提交读

  • repeatable read:可重复读

  • serializable:串行化

十四、spring事务的传播机制

事务的传播机制:方法A调用了方法B;方法B是否有事务会对方法A有影响;方法A是否有事务也会对方法B有影响;这种影响具体是什么由事务的传播机制来决定。

  • required:默认的;如果当前没有事务,就自己新建一个事务;如果当前存在事务,就加入当前事务

  • supports:当前存在事务,则加入事务;如果没有事务,就以非事务方法执行

  • mandatory:必须在一个存在的事务中运行,否则抛出异常。

  • required_new:总是启动一个新的事务,并且在新事务中执行;如果当前存在事务,则将当前事务挂起。

  • not_supported:总是以非事务方式执行,如果当前存在事务,将当前事务挂起

  • never:不在事务中运行,如果存在事务,则抛出异常

  • nested:如果当前存在事务,则在嵌套事务中执行(事务的内部创建新的事务,新事务可以独立的提交和回滚,不会影响外部事务),如果不存在事务,就新建一个事务。

十五、事务什么时候会失效?
  1. 出现异常,但是没有抛出,在事务内部处理了异常

  2. 抛出了没有在事务处理范围内的异常,默认只能识别RuntimeException,可以指定注解中rollbackFor为Exception,就可以识别所有异常了

  3. 在非public方法中使用事务

十六、Spring Boot、Spring MVC Spring 有什么区别
  • Spring是一个轻量级的开发框架,通过IOC容器,依赖注入,以及AOP来实现便捷的开发

  • SpringMVC是Spring针对web开发的一套解决方案,

    • 提供了一个总的前端控制器用来接收请求

    • 前端控制器把url给到处理器映射器,处理器映射器找到处理器路径返回给前端控制器

    • 前端控制器把映射地址给到处理器适配器,处理器适配器找到相应的处理器执行请求,然后返回ModelAndView给前端控制器

    • 前端控制器将ModelAndView给到视图解析器,视图解析器解析视图返回给前端控制器

    • 前端控制器将视图返回给前端服务器。

  • Springboot是对spring的一个快速开发包,简化了配置(自动化配置),整合了一套解决方案(starter机制)

    • starter机制:整合了很多第三方组件,约定了配置格式,每一个组件都定义为starter,通过pom文件的方式导入名为xxx-spring-boot-starter的组件;在这些组件的META-INF包下的spring.factories文件下定义了一些初始化配置,springboot项目启动的时候会去加载这个spring.factories下的初始化配置,根据约定的配置规则选择性的开启第三方组件的某些功能;到达简化配置,便捷使用第三方组件的效果

    • 自动化配置原理:SpringBootApplication 注解里边包含三个注解分别是 SpringBootConfiguration(标识配置类的注解),EnableAutoConfiguration 和ComponentScan (配置扫描包路径);其中EnableAutoConfiguration是实现自动配置的核心,里面有两个注解:

      • AutoConfigurationPackage :指定默认包的规则,就是将主程序类所在包及所有子包下的组件扫描到Spring容器中

      • @Import(AutoConfigurationImportSelector.class):通过AutoConfigurationImportSelector类的selectImports方法去读取META-INF/spring.factories文件中的配置的组件的全类名,并按照一定的规则过滤掉不符合要求的组件的全类名,将剩余读取到的各个组件的全类名集合返回给IOC 容器并将这些组件注册为bean。

十七、聊聊@Bean注解
  • 只能用在配置类(@Configuration)或被配置类引用(@Import)的类的方法上,将方法的返回值注册为bean到IOC容器中,bean的名字默认为方法名,可以在@bean注解里使用name属性指定bean的名字;

  • 如果用在非配置类的方法上,是不会主动的注册bean到IOC中的;除非该类被注入到IOC容器中(使用spring上下文类强行注入,使用其他注解注入),这个类里的所有@bean方法才会把返回值注册到IOC容器中。

十八、@Import注解、@Configuration注解和@Autowired注解的区别

@Import和@Configuration是将类注册到IOC容器中,并生成相应的bean对象;@Autowired是在IOC容器中找相应的bean对象,并关联上当前声明的对象。

  • @Configuration:在启动的时候执行。

    • @Configuration执行的时候会先把当前类注册到IOC容器中,然后检查当前类有没有@Import注解

      • 有就将@Import注解里面的类注册到IOC容器中,然后将这些类里的@bean方法的返回值注册到IOC容器中;

    • 然后将当前类中的@bean方法的返回值注册到IOC容器中

  • @Import:与@Configuration注解配合使用,在被标识的类被注册到IOC容器中的时候执行,先将当前类注册到IOC容器中,然后将这些类里的@bean方法的返回值注册到IOC容器中;

  • @Autowried:在程序运行时执行到相应语句的时候才会执行,按类型找IOC容器中的Bean对象,返回该类的bean对象,并关联上当前声明的对象。

Mybatis框架

十九、Mybatis的执行流程(Mybatis对JDBC做了哪些封装)
  1. 加载xml文件:配置连接信息,创建XNode对象封装sql

  2. 创建sqlSessionFactory对象

  3. 创建sqlSession对象

  4. 调用执行器封装MapperStatement对象,完成参数映射,执行sql,返回结果映射

二十、Mybatis延迟加载原理

原理:

  • 第一次调用sql查询时会将延迟加载的对象封装成CGlib代理对象,不会查询这些对象的值

  • 等到真正使用到这个对象的时候会被代理对象拦截,检查对象的值是不是null,

    • 是null,就执行相应的sql查询返回该字段的值给对象

    • 不是null,就直接返回实际值

  • 然后放行被拦截的方法。

使用流程:

  • 在配置文件中配置 lazyLoadingEnabled=true

  • 在相应的DAO接口中使用@Result注解配置fetchType = FetchType.LAZY

优点:

  • 启动项目的首次sql查询可以节省很多时间

  • 按需使用,避免资源浪费

缺点:

  • 会执行N+M次查询,使用不当的话,会导致速度更慢

二十一、讲一下Mybatis缓存机制

分为一级缓存和二级缓存

  • 一级缓存(默认开启且不能关闭)

    • 作用域为Session,在sqlSession中执行的sql会被缓存,

    • 执行sql的时候会先检查这个sqlSession中有没有执行增删改操作,

      • 没有的话,再检查这条sql有没有被缓存,被缓存了就直接返回结果

      • 执行了增删改操作,或者没有被缓存,都会执行这条sql

  • 二级缓存(默认不开启):

    • 作用域为sqlSessionFactory,在同一个sqlSessionFactory中的所有SqlSession都共享一个缓存

    • 作用范围大于一级缓存;当开启二级缓存后,执行sql时先检查一级缓存,没命中再检查二级缓存

二十三、Mybatis中二级缓存修饰器模式的使用

Apche提供了一个最基本的Cache接口,包含增删改查的抽象方法,Cache有个实现类是Perpetaul类使用HashMap实现了这些抽象方法;二级缓存是在这个基础上,通过修饰器模式动态扩展这个cache的功能

在装饰器模式中,Cache是Component的角色Perpetual充当被装饰者;Mybatis中提供了很多Cache的实现类,比如就有FIFOCache,他里边包含一个PerpetaulCache属性;引入了一些组件,比如队列,这就是装饰器;来实现先进先出的功能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值