首页 > 编程语言 >Java 面试题 05 - Spring Boot

Java 面试题 05 - Spring Boot

时间:2022-10-06 18:34:57浏览次数:63  
标签:容器 面试题 依赖 Java Spring 事务 Bean 方法

Spring 是什么?

是一个 轻量级的控制反转和面向切面的容器框架

  • 控制反转(IOC):一个对象所依赖的其他对象的创建,不由这个对象负责,而是由 容器负责,容器会在对象初始化时就将所需依赖传递给它。实现了 松耦合
  • 面向切面(AOP):可以 分离应用的业务逻辑与系统级服务,如日志。
  • 容器:Spring 管理对象的配置和生命周期,从这个意义上说它是一种容器。
  • 框架:Spring 将简单的组件配置、组合成复杂的应用 —— 组件组合的典型做法是写在一个 XML 配置文件里。另一方面,Spring 也提供了很多基础功能(事务管理、持久化框架集成等),将 应用逻辑 的开发留给开发者。

Spring 主要有哪些模块?

  • 数据访问:JDBC、ORM、Transaction、JMS(Java 消息服务)
  • Web:Web、WebMVC、WebFlux(响应式)、WebSocket
  • 切面:AOP
  • 核心:Beans、Core、Context、Expression
  • 测试:Test

IOC 是什么?

IOC 容器用来实现相互依赖的对象之间的解耦,对象不会自己主动去创建所依赖的其他对象,而是 将对象之间的依赖交给 IOC 容器来管理。Spring 通过依赖注入来实现控制反转,常用注入方法有三种:构造器注入、setter 注入、基于注解的注入。

依赖注入指的是 容器动态地将所需依赖注入到组件之中,提升了组件重用的概率。通过 DI,只需要通过简单的配置,无需任何代码就能指定目标所需的资源,完成自身的业务逻辑,而不需要关系资源具体来自何处。

三种依赖注入方式的比较

  • 属性注入:对于 IoC 容器以外的环境,除非使用反射才能获取它所需要的依赖,因为该类没有提供该属性的 setter 方法或者响应的构造方法来完成该属性的初始化。也就是说,在 IoC 容器之外,不能完成相关依赖的注入。另外,如果出现循环依赖问题,即 A 注入了 B,B 又注入了 A,那么在编译阶段是不能发现问题的,只有使用到这个 Bean 时才会发现。而使用构造器注入,在项目启动时就会报错。
  • 构造器注入:能够保证注入的 依赖不可变、不为空、总是能够在返回组件代码时保证 完全初始化 的状态。
    • 依赖不可变:指定了 final 关键字。
    • 依赖不为空:因为是构造器注入,所以在实例化当前类时,会调用这个构造函数,从而需要传入相关依赖,如果这个依赖指向的 Bean 为空,则会报错。
    • 依赖对象为完全初始化状态:调用构造器时,需要传入相关依赖,那么这个依赖需要首先完成实例化,所以返回来的依赖都是初始化之后的状态。

什么是 AOP?

面向切面编程,可以看成面向对象编程的补充。

面向对象 引入封装、继承、多态等概念来建立一种 对象层次结构模拟同一类对象的公共行为。而如果需要为分散的无关对象引入公共行为时,OOP 就没有办法了。例如日志代码往往水平地散布在所有对象层次中,与它所处对象的核心功能毫无关系。这种散布各处的无关代码被称为 横切代码OOP 中横切代码会大量重复,不利于模块的重用。

面向切面将这些散布各处的公共行为封装到一个可重用的模块,将其命名为 切面,以减少代码重复,降低模块耦合。


Spring AOP 和 AspectJ 是什么关系?

  • AspectJ 是一个 Java 实现的 AOP 框架,是实际上的 AOP 标准。
  • Spring 使用 AspectJ 来做切入点的解析和匹配。
  • AspectJ 的织入方式为 静态织入,即在编译期将 aspect 类编译成字节码,在 java 目标类编译时织入;而 Spring AOP 使用 动态织入,即在运行时将 aspect 代码织入到目标类中,使用 JDK 的动态代理来实现。

常用的 Bean 作用域有哪些?

  • singleton:默认为单例,每次请求该 Bean 都会获得同一个实例,容器跟踪它的状态,维护它的生命周期。

  • prototype:每次请求该 Bean 都会返回新的实例,容器只负责创建这个实例,不会跟踪它的状态。

  • request:(Spring MVC)每个 HTTP 请求都会创建一个 Bean。

  • session:(Spring MVC)每个 session 中,每个 Bean 对应一个实例。

单例 Bean 有线程安全问题吗?

当多个线程操作同一个对象时,对非静态成员的写操作 存在线程安全问题,解决方法通常是在类中 定义一个 ThreadLocal 成员,将可变成员保存在 ThreadLocal 中。


Bean 的生命周期是怎样的?

  1. Spring 根据配置文件中 Bean 的定义,利用反射方式实例化 Bean。
  2. 将值和依赖的 Bean 注入到属性中。
  3. 初始化
    1. Aware 相关接口:若 Spring 检测到 Bean 实现了 Aware 接口,则会为其注入相应的依赖。
      • BeanNameAwareBeanClassLoaderAwareBeanFactoryAware
      • EnvironmentAwareEmbeddedValueResolverAwareApplicationContextAware
    2. BeanPostProcessor 为修改 Bean 提供了入口。
    3. InitializingBean 和 init-method 用于初始化 Bean。
  4. 销毁

BeanFactory 和 ApplicationContext 有什么区别?

  • 这是两个核心接口,都可以当做 Spring 容器,其中 ApplicationContext 是 BeanFactory 的子接口。
  • 功能:
    • BeanFactory 是 Spring 的底层接口,维护着 Bean 的定义,负责 Bean 的加载、实例化,控制 Bean 的生命周期,维护 Bean 之间的依赖关系。
    • ApplicationContext 是 BeanFactory 的派生,除了支持后者的所有功能,还提供了其他功能
      • 国际化
      • 统一的资源文件访问方式
      • 同时加载多个配置文件
      • 载入多个上下文,使得每个上下文专注于一个特定的层次。
  • 加载方式:
    • BeanFactory 采用 延迟加载 的方式来注入 Bean,只有在调用 getBean() 时才会对这个 Bean 进行实例化。这样就不能及时发现当前存在的配置问题。
    • ApplicationContext 在容器启动时 一次性创建所有 Bean,那么在容器启动时就可以发现存在的配置错误。

Spring MVC 运行的流程是什么?

  1. 浏览器发送请求,请求被 DispatcherServlet 捕获;
  2. DispatcherServlet 调用 HandlerMapping,后者根据请求的 URL,以及注解或者 XML 配置,寻找匹配的 Handler 信息;
  3. HandlerAdapter 根据 Handler 信息执行具体的 Handler(Controller),返回相应的数据和视图信息,封装至 ModelAndView 对象中,返回给 DispatcherServlet;
  4. DispatcherServlet 请求 ViewResolver 对 ModelAndView 进行解析,ViewResolver 根据 View 信息匹配到相应的视图结果(template),返回给 DispatcherServlet;
  5. DispatcherServlet 将 Model 中的数据填充到结果视图中,生成最终的视图;
  6. 将渲染结果返回给用户。

Spring 框架中用到了哪些设计模式?

  • 工厂模式:通过 BeanFactoryApplicationContext 创建 Bean。

  • 代理模式:AOP 的实现。

  • 单例模式:Bean 默认都是单例的。

  • 模板方法模式:jdbcTemplate 操作数据库。

  • 适配器模式:Spring MVC 中的 HandlerAdapter。


统一异常处理怎么做?

使用 @ControllerAdvice + @ExceptionHandler 这两个注解。

@ControllerAdvice
@ResponseBody
public class GlobalExceptionHandler {

    @ExceptionHandler(BaseException.class)
    public ResponseEntity<?> handleAppException(BaseException ex, 
                                                HttpServletRequest request) {
      //......
    }

    @ExceptionHandler(value = ResourceNotFoundException.class)
    public ResponseEntity<ErrorReponse> handleResourceNotFoundException(
        ResourceNotFoundException ex, HttpServletRequest request) {
      //......
    }
}

这种异常处理方式下,会给所有或者指定的 Controller 织入异常处理的逻辑(AOP),当 Controller 中的方法抛出异常的时候,由被@ExceptionHandler 注解修饰的方法进行处理。


Spring Boot 的核心注解是哪个?

@SpringBootApplication 是核心注解,包含三个注解:

  • @SpringBootConfiguration:指定当前类为配置类。
  • @EnableAutoConfiguration:自动配置所有需要的组件。
  • @ComponentScan:让 Spring 自动发现所有 Bean,并将它们注册为组件。

@Autowired@Resource 的区别是什么?

  • @Resource 不是 Spring 的注解,全限定名为 javax.annotation.Resource ,但是 Spring 支持该注解。

  • @Resource 可用于 字段、setter 方法 上;而 @Autowired 可以用在 字段、setter 方法、构造器 上。

  • 注入方式

    • @Autowired

      • 按照类型装配依赖对象(如果根据类型找到了多个 Bean,则默认根据字段名来选择。)
      • 有一个 required 属性,默认为 true,表示依赖对象必须存在,如果允许 null 值,可将其设置为 false
      • 如果想要按照名称来装配,可以 结合 @Qualifier 注解使用
      @AutoWired // 按照 UserDao 类型寻找 Bean 来注入
      @Qualifier("user") // Bean 的名字是 user
      public setUserDao(UserDao user) {
          this.userDao = user;
      }
      
    • @Resource

      • 有两个参数:nametype,如果不指定参数,则 默认按照名称来装配依赖对象。如果使用 type 参数,则按照类型来装配依赖对象。整体装配顺序为:
        1. 如果同时指定 nametype,则从上下文中寻找 同时满足这两个条件 的 Bean,找不到则抛出异常。
        2. 如果仅指定 name,则寻找该名称的 Bean,找不到则抛出异常。
        3. 如果仅指定 type,则寻找该类型的 Bean,找不到或者 找到多个 均抛出异常。
        4. 如果没有指定 nametype,则按照 byName 方式进行装配。

@Component@Bean 的区别是什么?

  • 作用对象:@Component 注解于类,@Bean 注解于方法。
  • @Component 是通过自动扫描来装配到 Spring 容器中,@Bean 表示当前方法中可以产生 Bean,告诉 Spring 需要用到这个 Bean 的时候,从这里创建。
  • 很多地方只能通过 @Bean 来注册 Bean,比如第三方库中的类需要装配到 Spring 容器中时。

Spring Boot 怎么开启事务?

  1. @Configuration 类上(通常是主类)注解 @EnableTransactionManagement

  2. 在 Service 方法上添加 @Transactional 注解。

Spring 的事务传播行为有哪些?

事务传播行为描述的是,当一个指定了事务传播行为的方法被另一个方法调用时,事务如何传播。

public void methodA() {
    methodB();
    // ...
}
@Transactional(Propagation=XXX)
public void methodB() {
	// ...
}

外层方法 methodA 是否开启事务是可选的。

  • PROPAGATION_REQUIRED:如果当前没有事务,就创建一个新事物;否则就加入已存在的事务。
    • 外部方法未开启事务时,被 REQUIRED 修饰的内部方法会 开启自己的事务,且不同内部方法开启的事务相互独立,外部方法的异常不会影响内部方法的事务。
    • 外部方法开启事务时,被 REQUIRED 修饰的内部方法会 加入外部方法的事务中内部方法和外部方法同属于一个事务,只要任何一个方法(内部/外部)出现回滚,整个事务(其他所有方法)均需要回滚。
  • PROPAGATION_SUPPORTS:如果当前存在事务,就加入该事务;否则就以非事务执行。
  • PROPAGATION_MANDATORY:如果当前存在事务,就加入该事务;否则抛出异常。
  • PROPAGATION_REQUIRES_NEW:无论当前存不存在事务,都创建新事物。
    • 外部方法未开启事务时,被 REQUIRES_NEW 修饰的内部方法会 开启自己的事务,和其他内部方法的事务相互独立。
    • 外部方法开启事务时,被 REQUIRES_NEW 修饰的内部方法 仍然会开启自己的事务,和外部事务相互独立。
  • PROPAGATION_NOT_SUPPORTED:以非事务方式执行,如果当前存在事务,就把当前事务挂起。
  • PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,就抛出异常。
  • PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与 PROPAGATION_REQUIRED 类似的操作。
    • 外部方法未开启事务时NESTEDREQUIRED 行为相同,内部方法都会开启自己的事务,且彼此独立。
    • 外部方法开启事务时,被 NESTED 修饰的内部方法 成为外部事务的子事务,外部事物回滚,子事务一定回滚;子事务内部出现回滚时,如果外部事务察觉不到,就不会影响外部事务,进而不会影响到其他子事务;但若子事务的异常抛到了外部且未被处理,则会导致外部事务一同回滚,进而让其他子事务也回滚。

标签:容器,面试题,依赖,Java,Spring,事务,Bean,方法
From: https://www.cnblogs.com/lzh1995/p/16758157.html

相关文章

  • Java 面试题 06 - MySQL
    事务事务是逻辑上的一组操作,要么都执行,要么都不执行。事务的四个特性(ACID):原子性:事务不允许分割,要么全部完成,要么完全不执行。一致性:逻辑上的正确性,即这组操作的结果是......
  • 2022.9.30 Java第四次课后总结
    1.publicclassBoxAndUnbox{ /** *@paramargs */ publicstaticvoidmain(String[]args){ intvalue=100; Integerobj=value;//装箱 intresult=obj*2;......
  • java初步学习 方法的三种格式(基于黑马的课进行自学,初学者,不喜勿喷)9
    初步学习方法基本概念方法是程序(mathod)中最小的执行单元我们可以自己创建一个方法,并在其中写入想要执行的代码(将代码打包),这样可以重复使用,可以提高代码的复用性与可维......
  • JAVA 分布式电商项目高并发集群
    什么是分布式系统?要理解分布式系统,主要需要明白一下2个方面:1.分布式系统一定是由多个节点组成的系统。其中,节点指的是计算机服务器,而且这些节点一般不是孤立的,而是互......
  • JAVA中的高并发,解决高并发的方案
     java高并发,如何解决,什么方式解决一、什么是高并发二、高并发的解决方法有两种三、追加 一、什么是高并发1.1高并发(HighConcurrency)是互联网......
  • SpringBoot 实现文件上传
    参考:Javaspringboot进阶教程文件上传功能实现后端代码编写常见错误分析与解决在Service业务层接口中增加一个上传文件的方法因为文件并不是上传至数据库中,所以......
  • springboot整合prometheus和grafana
    准备springBoot服务pom引入依赖<!--集成micrometer,将监控数据存储到prometheus--><dependency><groupId>io.micrometer</groupId><artifactId>micrometer-r......
  • java---return,break,continue作用
    一:return在函数体中遇到return语句,则结束函数执行(函数体未执行完部分不再执行),将表达式的值返回到函数调用处。使用return最多只能返回一个值!二:breakbreak主要用在循......
  • 【持久层框架】- SpringData - JPA
    JPA简介JPA即JavaPersistenceAPI。是一款持久层框架,中文名Java持久层API,是JDK5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。JPA的对象......
  • SpringBoot应用自定义logback日志
    概述默认情况下,SpringBoot内部使用logback作为系统日志实现的框架,将日志输出到控制台,不会写到日志文件。如果在application.properties或application.yml配置,这样只能配置简......