当前位置:   article > 正文

spring常见面试题总结_面试时java工程师常问的spring问题

面试时java工程师常问的spring问题

1、spring是什么

Spring:是一个轻量级的IOC和AOP的java开发框架,为了简化企业级开发而生。核心就是控制反转和面向切面编程。

IOC:控制反转(Inverse of Control),以前项目都是在哪儿用到对象 在哪儿new,把生成对象的权利反转给spring,让spring把对象管理起来,在哪用在哪注入。

AOP:面向切面编程。可以对业务逻辑和非业务逻辑进行隔离,将程序中的一些非业务代码进行提取,然后让代理对象去调用公共的方法,就可以做到在不需要修改原来代码的情况下,为程序添加额外的功能,从而使得各部分之间的耦合度降低,提高程序的可重用性。好处就是:减少重复,专注业务;

底层实现:使用的是动态代理模式。是通过一个代理对象来实现对非业务代码进行调用的。告诉代理对象,调用哪个方法时,让代理对象去帮助我们调用哪个方法。

AOP思想不是spring框架特有的,只是spring框架引入使用了这一思想。

非业务代码使用案例:

  • 事务处理:开启事务,关闭事务,出现异常后回滚事务
  • 验证权限:在执行方法前,判断是否具有权限
  • 打印日志:在执行前进行日志处
  • 统一异常处理

2、spring事务管理

jdbc自动事务提交,mybatis事务默认不自动提交,需要我们在程序中手动提交 sqlsession.commit();spring框架把提交事务的功能帮助我们管理起来了,封装好了。

保障一个事务中的多条sql,要么都执行,要么都不执行,只要有发生异常就回退到事务开始未进行操作的状态,(例如转账)@Transactional

@Transactional标签的用法:

  • 一般把事务管理的注解标签在service的方法中来进行控制,需要把这多个sql,放在同一个事务管理中进行
  • 添加在service层中上,也可以添加在方法上
事务管理,在以下情况会失效:(重点)
  1. 修饰非public的方法,底层权限只针对public修饰的方法
  2. 数据库引擎不支持事务。常用的两个引擎:innodb(支持事务功能),myisam(不支持事务)
  3. 方法中的异常被catch捕获处理了
  4. 出现编译期异常,事务不生效。默认情况下,事务只对运行期异常进行生效@Transactional(rollbackFor = RuntimeException.class)。我们可以把其修改为@Transactional(rollbackFor = Exception.class),这样就可以处理任意的异常
  5. @Transactional事务传播行为设置错误
  6. 同一个类中,使用非代理对象调用一个有事务的方法。在一个非事务方法中使用this(原始的对象==自己new出来的对象)

3、事务传播行为?

即然是传播,那么至少有两个方法才可以发生传播。

事务传播行为:A事务方法调用B事务方法时,B事务是一个独立的事务呢(独立的,表示B出现了问题,不影响A)?还是B事务合并到A事务中呢(B影响A,A影响B)?这就是由B的事务传播行为决定的。

是Spring框架独有的事务增强特性,不属于事务实际提供者mysql。

Spring 定义了七种传播行为:

事务传播行为类型说明
PROPAGATION_REQUIRED如果A有事务, B加入到A事务中;如果A没有事务,B就新建一个事务,与A没有关系。(常见)
PROPAGATION_REQUIRES_NEW无论A是否有事务,B都会创建新的事务(独立的)
PROPAGATION_SUPPORTS支持A事务;如果A没有事务,B就以非事务方式执行
PROPAGATION_NEVERB以非事务方式执行;如果A存在事务,则抛出异常。
PROPAGATION_MANDATORY使用A事务,如果A没有事务,就抛出异常。
PROPAGATION_NOT_SUPPORTED以非事务方式执行操作,如果当前存在事务,就把当前事务挂起
PROPAGATION_NESTED如果当前存在事务,则在嵌套事务内执行。如果当前没有事务, 则执行与 PROPAGATION_REQUIRED 类似的操作。

注意:事务传播行为不能是同一个类中的方法相互调用,必须是一个类中的方法调用另一个类中的方法

4、SpringWeb运行流程

  1. 用户发起请求,所有的请求都可以到达DispatcherServlet(servlet),DispatcherServlet收到请求调用 HandlerMapping
  2. HandlerMapping映射处理器,用来解析请求中的地址,有没有对应的处理器类,将生成处理器对象返回给 DispatcherServlet。如果本次有对应的拦截器,会执行相应的拦截器。
  3. HandlerAdapter适配器,封装请求中的参数
  4. Handler到达自己创建的处理器,接收参数、处理、响应。

5、spring中用到的设计模式

单例模式、工厂模式、原型模式、代理模式。自己补充其他的几种

6、BeanFactory和ApplicationContext

BeanFactory和ApplicationContext都是spring中定义的上层的接口,ClassPathXmlApplicationContext类是spring框架的底层的实现。

BeanFactory接口是spring中最顶层的接口,定义bean管理的基本方法;ApplicationContext接口继承了BeanFactory,在此基础上进行功能的扩展。

区别:

  • BeanFactory是面向spring框架内部的,不支持aop、springweb等功能。ApplicationContext是面向应用程序的,功能强大。
  • 实现了BeanFactory的类,都是在使用时才进行加载创建。实现ApplicationContext的类,都是在程序启动就加载创建对象。

7、Spring中常用容器

平常说的Ioc容器、spring容器都是比较宏观的,对spring管理对象的称呼。Spring中常用容器,指的是具体实现IOC功能的类。

现在使用的是实现了ApplicationContext接口的具体实现类,下面有两个具体的实现类:

  • ClassPathXmlApplicationContext,从类路径ClassPath下读取XML配置文件,并完成ApplicationContext的实例化工作
  • FileSystemXmlApplicationContext,从指定的文件系统路径下读取XML配置文件,并完成ApplicationContext的实例化工作

WebApplicationContext是ApplicationContext的子接口,主要是用于Web应用。

AnnotationConfigApplicationContext中是不需要配置 XML 配置文件。

8、BeanFactory与FactoryBean有什么区别

BeanFactory是整个Spring IOC容器的核心,是定义如何管理bean。

FactoryBean也是一个接口,用来为具体创建对象的工厂进行功能定义。

9、SpringBean的生命周期

把交给spring容器管理的对象称为bean对象,与自己的new的对象有所不同。

spring管理的bean生命周期问题:spring管理的bean,从诞生到销毁的整个过程。可以分为5个阶段:

  1. 对象实例化(创建一个原始的普通的对象,类似于new对象)
  2. 为属性赋值
  3. 初始化(指的是spring框架对对象进行初始化)。初始化是spring对bean进行管理的最重要的一个环节,在此时可以根据类的配置,进行各种功能的装配。例如类中的方法是否要添加事务,统一异常处理.....还可以自定义初始化的方法,以及销毁对象时调用的方法。
  4. 将bean对象放入到容器中,去使用它。
  5. 销毁Destruction。

10、Spring中的bean是线程安全的吗?

回顾一下servlet,经常还有问到servlet是线程安全的吗?

  1. class XXXServlet{
  2. int count = 0; //本意是每次请求中都可以使用一个自己的count
  3. //但是在serlvet中不可以做到,因为serlvet对象是单实例
  4. doGet(){
  5. }
  6. }

Spring的bean作用域(scope)类型:

  • singleton:单例,默认作用域。
  • prototype:原型,每次创建一个新对象。

如果spring中的bean(xxxController..)是原型bean,那么每次请求到来时都会创建一个新的对象,不会存在数据共享,就是线程安全的。

如果spring中的bean是单例的,所有线程都共享一个对象,就会存在线程安全问题。但也不是绝对的,分情况。bean又分为

  • 有状态,可以存储数据,线程不安全
  • 无状态,不会存储数据,是线程安全的
  1. public class UserService {
  2. int num = 0;
  3. User user;//可以用来为每次请求存储数据 那么就是有状态的, 就会出现线程安全问题
  4. UserDao userDao;//只是用来负责调用对象中的方法,不存储数据 也是无状态的 是线程安全的
  5. }

如何解决有状态bean的线程安全问题?

  1. 把单例bean改为原型bean,每次请求都会创建一个新的对象。
  2. 使用ThreadLocal为变量在每次请求线程中进行复制。

11、Bean循环依赖

没有使用spring依赖注入,是不会有问题的。只是简单的创建A和B的对象,A类中b属性和B类中a属性都为null。

  1. class A{
  2. B b;
  3. }
  4. class B{
  5. A a;
  6. }

 一旦使用了spring框架的自动注入,就会出现循环依赖问题。A创建时-->需要B----B去创建--->需要 A,从而产生了循环。

  1. class A{
  2. @Autowired //自动注入注解, 当创建A类对象时,就需要为b属性注入值.
  3. B b;
  4. }
  5. class B{
  6. @Autowired //自动注入注解, 当创建B类对象时,就需要为a属性注入值.
  7. A a;
  8. }

 spring内部有三级缓存:三级缓存其实就是3种map,分别用来存储不同的对象。

3个map分别用来存储:

  • 一级缓存 singletonObjects:用来存储初始化完成的对象,完整的bean。
  • 二级缓存 earlySingletonObjects:用来存储实例化完成的bean(半成品)。提前暴露出来,提供给循环依赖的对方使用。
  • 三级缓存 singletonFactories:用来创建对象的工厂,因为bean还没有初始化完成

将处于不同阶段的bean对象进行分别的存储,以达到先将一个对象初始化完成,再初始化另一个对象。

Spring解决循环依赖问题:首先采用实例化,属性注入分离的策略。

12、Servlet的过滤器与Spring拦截器区别

过滤器是javaweb(servlet)中的规范,它是在请求进入到servlet之前进行拦截,可以拦截所有进入到web后端的请求。

拦截器是spring框架中封装的,只能拦截进入到controller中的请求。

13、spring常用注解

1.声明bean的注解

@Component:泛指各种组件。@Controller、@Service、@Repository都可以称为@Component

@RestController,组合的注解,里面包含两个注解:

  • @Controller
  • @ResponseBody
2.Bean的生命周期属性

@Scope设置类型包括:设置 Spring 容器如何新建 Bean 实例

  • singleton:单例,一个Spring容器中只有一个bean实例,默认模式
  • protetype:每次调用新建一个bean
  • request:web项目中,给每个http request新建一个bean
  • session:web项目中,给每个http session新建一个bean
  • globalSession:给每一个global http session新建一个Bean实例
3.注入 bean 的注解

@Autowired:由Spring提供

@Qualifier:当有多个同一类型的 Bean 时,可以用@Qualifier(“name”)来指定。与@Autowired 配合使用。

@Resource:由 java 提供

4.切面(AOP)相关注解

Spring支持AspectJ的注解式切面编程

@Aspect:声明一个切面

@After:在方法执行之后执行(方法上)

@Before:在方法执行之前执行(方法上)

@Around:在方法执行之前与之后执行(方法上)

@PointCut:声明切点

@EnableAspectJAutoProxy:开启Spring对AspectJ代理的支持

5.SpringMVC常用注解

@RestController:该注解为一个组合注解,相 当于@Controller和@ResponseBody的组合,注解在类上,意味着,该Controller的所有方法都默认加上了@ResponseBody。

@RequestMapping:用于映射 web 请求,包括访问路径和参数

@ResponseBody:支持将返回值放到 response 内,而不是一个页面,通常用户返回json数据

@RequestBody:允许request的参数在request体中,而不是在直接连接的地址后面。

@Transactional:注解放在类级别时,表示所有该类的公共方法都配置相同的事务属性信息。

6.SpringBoot注解

@SpringBootApplication里面包含三个注解标签:

  • @SpringBootConfiguration
  • @EnableAutoConfiguration
  • @ComponentScan:自动扫描启动类所在包下的所有类

@Confiquration用于配置类上面

@Bean在配置类的方法上,表示此方法会返回一个bean,交给spring框架,替代xml中的方式。

@RestControllerAdvice,@ExceptionHandler 用于统一异常处理,捕获指定的异常.

14、SpringBoot自动装配原理

sprinaboot是对spring框架的搭建进行简化,去掉xml配置文件,内置tomcat(容器)。

起步依赖(可以将相关的jar包自动依赖进来)

自动配置(自动装配):在springboot项目中,只需要添加一个组件的依赖(jar),springboot就会自动将这一组件进行装配,可以让我们在程序中直接使用。(例如redis,只需要添加依赖,可以注入使用Redistemplate)。

springboot是基于约定大于配置的思想。

自动装配实现

注解、以及底层类对pom.xml进程读取,读取完后找到组件对应配置类。

1.在启动类上有一个@SprinqBootApplication注解,它是一个复合注解标签,里面包含三个注解标签:

  • @SpringBootConfiguration
  • @EnableAutoConfiguration
  • @ComponentScan:自动扫描启动类所在包下的所有类

2.@EnableAutoConfiquration注解标签中包含@Import({AutoConfigurationImportSelector.class)注解,其中包含一个类AutoConfigurationImportSelector,此类是根据pom.xml文件中配置来进行组件的加载(例如配置redis、mail等依赖)。

3.根据pom.xml文件中的依赖的配置,去jar包的spring.factories文件中,找到组件对应配置类,对配置类进行加载。

4.在程序中可以直接注入使用。

总结:首先依赖启动类的注解标签,注解标签底层有具体的实现类,对pom.xml文件进行读取,找到对应组件的配置类,再在applcation.yml文件读取组件需要的配置信息,最终完成装载。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/433921
推荐阅读
相关标签
  

闽ICP备14008679号