Spring面试题——第五篇

news2024/11/28 2:31:30

1. Spring的优点

  • 轻量级和非侵入性:不需要引入大量的依赖和配置。
  • 面向切面编程:Spring提供了强大的面向切面编程,允许用户定义横切关注点,并将其与核心业务逻辑分离,提高了灵活性。
  • 依赖注入(DI)和控制反转:Spring的核心容器是IOC,他实现了依赖注入模式,通过配置文件或者注解来管理对象之间的依赖关系,降低了耦合度,提高了代码的可维护性和可测试性。
  • 拥有大量的生态和活跃的社区。

2. Spring IOC容器初始化过程

一共有四个阶段,分别是启动、Bean定义注册、实例化和依赖注入、初始化。

  1. 启动阶段
  • 配置加载:加载配置文件或者配置类,IOC容器首先需要加载应用程序的配置信息,这些配置信息可以是XML配置文件、Java配置类或者注解配置等方式。
  • 创建容器:Spring创建IOC容器(BeanFactory、ApplicationContext),准备加载和管理Bean。
  1. Bean定义注册阶段
  • 解析和注册:BeanDefinitionReader读取解析配置中的Bean定义,并将其注册到容器中,形成BeanDefinition对象。
  1. 实例化和依赖注入
  • 实例化:根据BeanDefinition创建Bean实例
  • 依赖注入:根据BeanDefinition中的依赖关系,可以通过构造函数注入、Setter注入或者字段注入、将依赖注册到Bean中。
  1. 初始化
  • BeanPostProcessor:这些处理器会在Bean初始化生命周期中加入定义的处理逻辑,postProcessBeforeInitialization和postProcessAfterInitialization
  • Aware接口调用:如果Bean实现了Aware接口(如BeanNameAware、BeanFactoryAware),Spring会回调这些接口,传递容器相关信息。
  • 初始化方法调用:调用Bean的初始化方法(如通过@PostConstruct注解标注的方法,或者实现InitializingBean接口的bean会被调用afterPropertiesSet的方法)。

3. Spring Bean注册到容器有哪些方式

Spring Bean注册到容器的方式有以下几种

  • 基于XML的配置:使用XML文件配置Bean,并定义Bean的依赖关系
  • 基于@Component注解及其衍生注解:@Component、@Service、@Controller、@Repository
  • 基于@Configuration(声明配置类)、@Bean(注解定义Bean)注解
  • 基于@Import注解:@Import可以将普通类导入到Spring容器中,这些类会自动被注册为Bean。

4. @Qualifier注解作用

@Qualifier注解在Spring的主要作用是用于在依赖注入时消除歧义,当一个类型有多个实现时,@Qualifier注解可以指定需要注入哪一个具体的Bean。

例如,当Service有多个实现类的时候,可以通过@Qualifier指定名称选择对应的实现Bean。

@Component
public class Client {

    private final Service service;

    @Autowired
    public Client(@Qualifier("serviceImpl1") Service service) {
        this.service = service;
    }

    public void doSomething() {
        service.serve();
    }
}

扩展@Primary
@Primary注解用于指定当有多个候选Bean时默认注入哪个Bean,也就是指定了第一顺位。当结合@Qualifier使用时,可以覆盖@Primary的默认行为,例如:
在这里插入图片描述
即使DefaultService被标记为@Primary,但由于@Qualifier(“specificService”),所以最终注入的仍然是specificService

5. @Bean和@Component有什么区别

@Bean和@Component 都是用于定义spring容器中的Bean的注解,但是,他们的使用场景和方式有所不同:

  • @Bean注解通常用于Java配置类的方法上,以声明一个Bean并将其添加到Spring容器中,用于显示声明。
  • @Component注解用于类级别,将该类标记为Spring容器中的一个组件,自动检测并注册为Bean,用于自动扫描和注入。
特性@Bean@Component
使用位置方法级别(在@Configuration类中)类级别
扫描机制不支持自动扫描,需要手动注册支持自动扫描,通过@ComponentScan自动发现
主要用途用于配置第三方库或者复杂对象用于自动发现并注册自定义类
常见场景手动配置复杂对象、第三方库类自定义服务、DAO层、控制器等类的自动注册
灵活性更灵活,适合复杂初始化自动化更强,适合类的简单注册

扩展
@Bean注解用于显示声明spring容器管理的Bean,通常用于以下场景

  • 手动创建复杂的对象:需要进行复杂的初始化过程,或者需要传递参数给构造函数的对象
  • 如果某个类不是自己开发,且无法添加spring注解时,可以通过@Bean来手动注册。

@Component使用场景
@Component注解用于类级别的扫描和注入,spring会自动发现和管理这些类,他是spring中实现自动扫描Bean的基础。
@Component 是一个通用的注解,还有一些特定用途的衍生注解

  • @Service
  • @Repository
  • @Controller

6. spring事务在什么情况下会失效

一般而言,失效的情况都是用了声明式事务即@Transactional注解,如果使用了这个注解那么在以下几种情况下会导致事务失效

  • rollbackFor没设置对,比如默认没有任何设置(只有发生了RuntimeException或者Error才能回滚),则方法内抛出IOException则不会回滚。需要设置@Transactional(rollbackFor=Exception.class).
  • 异常被捕获了,比如代码抛错,但是被catch了,这样事务无法正常获取到错误,因此不会回滚。
  • 同一个类中的方法调用,因此事务是基于动态代理实现的,同类的方法调用不会走代理方法,因此,事务自然就失效了。
  • @Transactional应用在非public修饰的方法上,spring事务管理器判断非公共方法则不应用事务。
  • @Transactional应用在final和static方法上,因为aop默认是cglib代理,无法对final方法子类化。static是静态方法,属于类,不属于实例对象,无法被代理。
  • propagation传播机制错误
  • 多线程环境,因为@Transactional是基于ThreadLocal存储上下文的,多线程情况下每个线程都有自己的上下文,那么就无法保持事务同步。
  • 用的是MySQL的MyISAM引擎,这个引擎本身不支持事务。

7. Spring启动过程

  1. 加载配置文件,初始化容器:spring启动时首先读取配置文件,包括配置数据库连接、事务管理、AOP配置等。
  2. 实例化容器:spring根据配置文件中的信息创建容器ApplicationContext,在容器启动阶段实例化BeanFactory,并加载容器中的BeanDefinitions。
  3. 解析BeanDefinitions:spring容器会解析配置文件中的BeanDefinitions,即声明的Bean元数据,包括Bean的作用域,依赖关系等信息。
  4. 实例化Bean:spring根据BeanDefinitions实例化Bean对象,将其放入容器管理。
  5. 注入依赖:spring进行依赖注入,将Bean之间的依赖关系进行注入,包括构造函数注入、属性注入等。
  6. 处理Bean生命周期初始化方法
  • spring调用Bean初始化方法,对Bean进行初始化
  • 如果Bean实现了InitializingBean接口,spring会调用其afterPropertiesSet方法。
  1. 处理BeanPostProcessors:容器定义了很多BeanPostProcessor,处理其中的自定义逻辑,例如PostProcessBeforeInitializaiton会在Bean初始化前调用。PostProcessAfterInitializaiton则在Bean初始化之后调用。
  2. 发布事件:Spring可能会在启动过程中发布一些事件,比如容器启动事件。
  3. 完成启动:当所有Bean初始化完毕、依赖注入完成、AOP配置生效等都准备就绪时,Spring容器启动完成。

8. Spring的单例Bean是否有并发安全问题

存在并发安全问题,因为Spring容器默认将Bean作为单例管理,因此同一个Bean的实例会在整个应用程序中被多个线程共享。在多线程环境中,如果Bean中包含全局可变状态(如实例变量或者非线程安全资源),则可能会引发线程安全问题。

解决方案

  • 避免在单例Bean中使用可变状态:确保单例Bean是无状态的或仅使用线程安全的数据结构。
  • 使用@Scope(“prototype”) :对于有状态的Bean,Spring提供了原型作用域,每次请求都会创建一个新的Bean实例,从而避免共享同一个实例带来的并发问题。
  • 加锁:如果需要在单例Bean中管理共享资源,可以通过synchronize关键字或者其他线程同步机制来确保线程安全。
  • 使用ThreadLocal保存变量。

9. Spring和Spring MVC的关系

Spring是基础,Spring MVC构建于Spring核心之上,利用其提供的容器管理、依赖注入、AOP等功能来实现Web层的处理。

Spring MVC的核心功能

  1. 基于MVC模式的Web开发
  • Model:负责封装数据,可以是POJO、DTO或者其他形式对象
  • View:负责展示数据
  • Controller:负责用户请求处理。

请求处理流程
Spring MVC通过前端控制器拦截所有的请求,并将请求分发给合适的控制器进行处理。

  1. DispatcherServlet拦截请求
  2. HandlerMapping根据请求URL查找对应的控制器
  3. Controller处理业务逻辑,并返回数据
  4. ViewResolver 决定渲染哪个视图模板
  5. 将响应返回给客户端。

10. Spring MVC中的拦截器是什么?如何定义一个拦截器

拦截器用于在请求处理流程的不同阶段拦截HTTP请求和响应,并对其进行预处理或者后处理,拦截器可以用于实现注入权限验证、日志记录、性能监控等功能,而无需将这些逻辑直接耦合在控制器代码中。

定义一个拦截器的步骤
实现HandlerInterceptor接口:自定义的拦截器需要实现HandlerInterceptor接口,并且重写其三个核心方法

  • preHandle(): 请求到达控制器之前的预处理
  • postHandle():控制器执行之后但视图渲染之前的后处理
  • afterCompletion(): 整个请求结束之后的回调。

11. Spring MVC如何处理异常

可以利用全局和局部的异常处理机制,用于捕获应用程序中的异常并返回适当的响应。

Spring MVC中处理异常的核心方式

  1. 局部异常处理:@ExceptionHandler注解,用于局部的异常处理,通常定义在控制器类中。他可以捕获特定的异常,并返回自定义的错误信息或者视图。
  2. 全局异常处理:@ControllerAdvice,应用于所有的控制器,通过这个注解,可以定义全局的异常处理逻辑,避免在每个控制器中重复编写相同的异常处理代码。

使用@ExceptionHandler处理局部异常

@Controller
public class UserController {

    @GetMapping("/user/{id}")
    public String getUser(@PathVariable Long id) {
        if (id == null) {
            throw new IllegalArgumentException("ID cannot be null");
        }
        // 业务逻辑
        return "userProfile";
    }

    // 局部异常处理方法
    @ExceptionHandler(IllegalArgumentException.class)
    public ResponseEntity<String> handleIllegalArgumentException(IllegalArgumentException ex) {
        return new ResponseEntity<>(ex.getMessage(), HttpStatus.BAD_REQUEST);
    }
}

使用@ControllerAdvice处理全局异常

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(Exception.class)
    public ResponseEntity<String> handleAllExceptions(Exception ex) {
        return new ResponseEntity<>("An error occurred: " + ex.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2222590.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

java对接钉钉发送消息(纯萌新文档解惑)

java对接钉钉&#xff08;纯萌新文档解惑&#xff09; 注意&#xff1a;不是其他直接给你个写好的钉钉工具类&#xff0c;但不知道它怎么来的。是以钉钉官方文档为准&#xff0c;流程是什么&#xff0c;你想要什么可以自己在文档找&#xff08;所有文档都有只是萌新看着懵&…

Kafka高可用性原理深度解析

在分布式系统中&#xff0c;高可用&#xff08;High Availability, HA&#xff09;是指系统在面对硬件故障、网络分区、软件崩溃等异常情况时&#xff0c;仍能继续提供服务的能力。对于消息队列系统而言&#xff0c;高可用性尤为重要&#xff0c;因为它通常作为数据流通的中枢&…

SSD | (十)PCIe介绍(上)

文章目录 📚从PCIe的速度说起📚PCIe拓扑结构🐇PCI——总线型拓扑结构🐇PCIe——树形拓扑结构📚PCIe分层结构📚PCIe TLP类型📚PCIe TLP结构🐇通用结构🐇具体TLP的Header📚从PCIe的速度说起 PCIe发展至今,速度一代比一代快。 连接速度所示1、2等是指PCIe链接…

Python 打包成 EXE 的方法详解

#1024程序员节&#xff5c;征文# 日常开发中&#xff0c;python由于其便捷性成为了很多人的首选语言&#xff0c;但是python的环境配置也是有点麻烦的&#xff0c;那么我们如何让其变得更加友好呢&#xff1f;没错&#xff0c;就是打包成exe可执行文件。 一、PyInstaller 简介…

修改windows11的hosts,配置127.0.0.1域名(最清晰)

这里记录的是学习短链接项目&#xff0c;通过配置127.0.0.1域名&#xff0c;达到可以通过域名代替127.0.0.1访问127.0.0.1下的某个端口的服务&#xff0c;达到短链接的前缀的效果&#xff0c;这里展示windows11的更改过程。 一、hosts文件路径 C:\Windows\System32\drivers\e…

【Java数据结构】---哈希表

乐观学习&#xff0c;乐观生活&#xff0c;才能不断前进啊&#xff01;&#xff01;&#xff01; 我的主页&#xff1a;optimistic_chen 我的专栏&#xff1a;c语言 &#xff0c;Java 欢迎大家访问~ 创作不易&#xff0c;大佬们点赞鼓励下吧~ 前言 在顺序结构以及平衡树中&…

littlefs源码分析1-设计思考

1.littlefs设计目的 littlefs 最初是作为一个实验而构建的&#xff0c;目的是在微控制器的环境中了解文件系统设计。目的是&#xff1a;构建一个在不使用无限制内存的情况下对电源丢失和闪存磨损具有弹性的文件系统。 这对嵌入式文件系统littlefs提出了三个主要要求&#xff1…

【Linux】 exit 和 _exit 的区别

在Linux系统中&#xff0c;exit(int status) 和 _exit(int status) 都是用来终止进程的函数&#xff0c;都能通过参数 int status传递一个整型的退出状态码给父进程&#xff0c;但它们之间有一些重要的区别。 1. 头文件不同 exit() 函数定义在 <unistd.h> 中 _exit() 函…

【Python爬虫实战】高效解析和操作XML/HTML的实用指南

&#x1f308;个人主页&#xff1a;https://blog.csdn.net/2401_86688088?typeblog &#x1f525; 系列专栏&#xff1a;https://blog.csdn.net/2401_86688088/category_12797772.html 目录 前言 一、lxml的安装 &#xff08;一&#xff09;使用 pip 安装 &#xff08;二&…

(一)ubuntu下通过c++编译cpu版本paddleocr-2.8.1

编译环境 操作系统&#xff1a;ubuntu 20.04/22.04 OCR版本&#xff1a;paddleocr 2.8.1 Opencv版本&#xff1a;opencv3.4.16/4.10.0 o参照官方文档&#xff1a; PaddleOCR/deploy/cpp_infer/readme_ch.md at release/2.6 PaddlePaddle/PaddleOCR GitHubhttps://github…

Vue3脚手架和指令

什么是Vue&#xff1f; 简单来说&#xff0c;vue就是可以让有写代码很爽的体验。 概念&#xff1a;Vue是一套构建用户界面的渐进式JavaScript框架。 什么是构建用户界面&#xff1f; 基于数据渲染出用户可以看到的界面 什么是渐进式&#xff1f; 渐进式就是循序渐进的学习…

LabVIEW提高开发效率技巧----VI继承与重载

在LabVIEW开发中&#xff0c;继承和重载是面向对象编程&#xff08;OOP&#xff09;中的重要概念。通过合理运用继承与重载&#xff0c;不仅能提高代码的复用性和灵活性&#xff0c;还能减少开发时间和维护成本。下面从多个角度介绍如何在LabVIEW中使用继承和重载&#xff0c;并…

HttpURLConnection构造请求体传文件

HttpURLConnection构造请求体传文件 在Java中&#xff0c;使用HttpURLConnection构造请求体传输文件&#xff0c;你需要做以下几步&#xff1a; 1、创建URL对象指向你想要请求的资源。 2、通过URL打开连接&#xff0c;转换为HttpURLConnection实例。 3、设置请求方法为POST。 …

Java 多线程(五)—— 阻塞队列、wait、notify

wait wait 和 notify 都是 Object 类提供的方法&#xff0c;也就是说 Java 任意对象都可以使用 这两个方法。 首先 wait 会抛出 InterruptedException 这个异常&#xff0c;说明这个方法可以被 interrupt 给唤醒。 然后我们是不能直接使用 wait 方法的&#xff0c;否则还会抛…

Win10系统安装docker操作步骤

Docker下载 docker下载地址&#xff1a;Docker: Accelerated Container Application Development 打开网页后&#xff0c;点击图下所示&#xff0c;下载windows版本的docker 启用Hyper-V 和容器特性 右键左下角windows图标&#xff0c;选择应用和功能 然后在下面的界面中&am…

电脑技巧:Rufus——最佳USB启动盘制作工具指南

目录 一、功能强大&#xff0c;兼容性广泛 二、界面友好&#xff0c;操作简便 三、快速高效&#xff0c;高度可定制 四、安全可靠&#xff0c;社区活跃 在日常的电脑使用中&#xff0c;无论是为了安装操作系统、修复系统故障还是进行其他需要可引导媒体的任务&#xff0c;拥…

初始JavaEE篇——多线程(2):join的用法、线程安全问题

找往期文章包括但不限于本期文章中不懂的知识点&#xff1a; 个人主页&#xff1a;我要学编程(ಥ_ಥ)-CSDN博客 所属专栏&#xff1a;JavaEE 目录 模拟实现线程中断 join的用法 线程的状态 NEW&#xff1a; RUNNABLE&#xff1a; TIMED_WAITING&#xff1a; TERMINATED…

ElasticSearch-7.17.10集群升级至ElasticSearch-7.17.24

文章目录 集群概览 主机名系统版本es01CentOS_7.6-aaarch64ElasticSearch-7.17.10es02CentOS_7.6-aaarch64ElasticSearch-7.17.10es03CentOS_7.6-aaarch64ElasticSearch-7.17.10 需求 1. 将三台ES节点从ElasticSearch-7.17.10升级至ElasticSearch-7.17.24&#xff1b; 2. 保证…

1212,查询球队积分

查询球队积分 表: Teams ------------------------- | Column Name | Type | ------------------------- | team_id | int | | team_name | varchar | ------------------------- team_id 是该表具有唯一值的列。 表中的每一行都代表一支独立足球队。表…

HarmonyOS 模块化设计

1.HarmonyOS 模块化设计 模块化设计文档   应用程序包开发与使用文档 1.1. 概述 组件化一直是移动端比较流行的开发方式&#xff0c;有着编译运行快&#xff0c;业务逻辑分明&#xff0c;任务划分清晰等优点&#xff0c;HarmonyOs组件化的使用&#xff0c;有利于模块之间的解…