
1.Spring 框架中的单例 bean 是线程安全的吗①Spring 单例 bean 本身非线程安全框架未做任何线程安全封装并发安全问题需开发者自行处理②多线程并发访问时若单例 bean 存在成员属性修改等状态变更操作会引发线程安全问题③实际项目中Service、DAO 等无状态单例 bean无状态修改可认为是线程安全的④若为有状态 bean如 ViewModel需自行实现线程同步或将作用域从singleton改为prototype。1.Autowired和Resource的区别注入的优先级是什么Autowired和Resource都是 Spring 依赖注入注解核心区别有 3 点所属规范不同Autowired是 Spring 框架自带注解Resource是 JDK/EE 规范注解Spring 对其兼容支持。注入规则不同Autowired默认按类型注入遇到多个同类型 Bean 时需配合Qualifier指定名称Resource默认按名称注入可直接通过name属性指定 Bean 名无需额外注解。灵活性不同Autowired支持构造方法、参数等多场景注入只有required一个属性Resource不支持构造方法注入但有name/type等多属性配置更灵活。2. 什么是 AOP①AOP 即面向切面编程是 Spring 核心特性之一②核心思想抽取与业务无关、对多个对象有公共影响的逻辑为切面实现公共代码复用③核心价值降低业务代码与公共逻辑的耦合度让业务代码更专注核心业务④典型应用场景系统操作日志、事务管理、权限控制、统一异常处理。3.什么是IOCIOC 是Inversion of Control的缩写翻译为控制反转是 Spring 框架的核心设计思想而非具体技术核心是将对象的创建、依赖管理、生命周期控制的权力从开发者的代码中转移到 Spring 的 IOC 容器中由容器统一接管开发者不再手动通过new创建对象、维护对象间依赖而是通过配置注解 / XML/JavaConfig告诉容器规则由容器自动完成所有操作。3. 项目中有没有使用到 AOP①项目中在后台管理系统使用 AOP记录系统操作日志②核心实现通过 AOP 的环绕通知 切点表达式定位需要记录日志的目标方法③关键操作通过环绕通知的参数获取请求的类信息、方法信息、注解、请求方式等数据④最终处理将获取的日志数据持久化保存至数据库。4.Spring 中的事务是如何实现的①Spring 事务的实现本质基于 AOP 面向切面编程②核心逻辑对目标方法进行前后拦截实现事务的统一管理③执行流程方法执行前开启事务方法执行完成后根据执行结果是否抛出异常决定提交或回滚事务。5.Spring 中事务失效的场景有哪些①方法内部捕获异常并自行处理未将异常抛出导致事务无法感知异常而失效②方法抛出检查型异常checked exception且Transactional注解未配置rollbackFor Exception.class异常发生时事务不回滚③Transactional注解标注在非 public 修饰的方法上因 AOP 代理机制限制导致事务失效。6.Spring 的 bean 的生命周期①通过 BeanDefinition 获取 bean 的完整定义信息②调用 bean 的构造函数完成 bean 的实例化③执行 bean 的依赖注入如Autowired注解、setter 方法注入等④处理实现 Aware 接口的 bean注入容器相关信息如 BeanNameAware、BeanClassLoaderAware、BeanFactoryAware⑤ 执行 BeanPostProcessor 的前置处理器方法postProcessBeforeInitialization核心作用对初始化前的原始 Bean 对象进行统一前置处理如属性合法性校验、基础属性修正 / 补全、日志埋点等轻量增强确保 Bean 进入初始化步骤前状态合法、符合定制化要求为后续初始化做准备。⑥调用 bean 的初始化方法如实现 InitializingBean 接口的afterPropertiesSet()、通过PostConstructor注解自定义init-method⑦ 执行 BeanPostProcessor 的后置处理器方法postProcessAfterInitialization核心作用对初始化完成的完整 Bean 对象进行最终增强与包装此步骤可能生成 AOP 代理对象是 Spring AOP 动态代理的核心实现步骤同时支持 Bean 最终属性校验、自定义 Bean 包装 / 替换、初始化后业务回调等。⑧bean 完成全部初始化进入可用状态⑨Spring 容器销毁时调用 bean 的销毁方法如 DisposableBean 接口、通过PreDestory注解自定义destroy-method。7.Spring 中的循环引用①循环引用两个或两个以上的 bean 互相持有对方的引用形成依赖闭环②Spring 支持解决单例 bean的循环依赖多例 bean 无法解决③核心解决方案通过三级缓存机制实现提前暴露未完成初始化的 bean 对象④三级缓存具体说明1一级缓存单例池缓存已完成全部生命周期的成熟 bean 对象2二级缓存缓存尚未完成初始化的早期 bean 对象3三级缓存缓存 ObjectFactory 对象用于创建 bean 的早期对象。8.Spring 解决循环依赖的具体流程①实例化 A 对象创建对应的 ObjectFactory 并存入三级缓存②A 对象进行依赖注入时发现需要 B 对象触发 B 对象的创建流程③实例化 B 对象创建对应的 ObjectFactory 并存入三级缓存④B 对象进行依赖注入时发现需要 A 对象从三级缓存获取 ObjectFactory 生成 A 的早期对象存入二级缓存⑤B 对象注入 A 的早期对象后完成全部初始化成为成熟 bean存入一级缓存⑥A 对象继续依赖注入从一级缓存获取已初始化完成的 B 对象完成注入⑦A 对象完成全部初始化成为成熟 bean存入一级缓存⑧清除二级缓存中的 A 对象早期实例释放临时资源。9. 构造方法出现了循环依赖怎么解决①Spring 框架无法解决构造方法层面的循环依赖因构造函数是 bean 实例化第一步对象尚未创建无法提前暴露②核心解决方式使用Lazy懒加载注解标注在构造方法的依赖参数上③Lazy作用延迟该 bean 的创建时机直到实际调用时再完成实例化和依赖注入打破构造方法的循环依赖闭环。10.SpringMVC 的执行流程版本一视图版本JSP①用户发送 HTTP 请求由前端控制器 DispatcherServlet 统一接收②DispatcherServlet 调用 HandlerMapping根据请求路径查找对应的处理器Controller③Controller 处理完成后返回 ModelAndView 对象包含数据模型和视图名称④DispatcherServlet 将 ModelAndView 传给 ViewResolver 视图解析器进行视图解析⑤ViewResolver 解析后返回具体的 View 视图对象给 DispatcherServlet⑥DispatcherServlet 渲染视图将数据模型填充至视图并将结果响应给用户。版本二前后端开发接口开发① 客户端发出 HTTP 请求请求抵达 DispatcherServlet它是 SpringMVC 的入口所有请求先到这里。② DispatcherServlet 把请求交给 HandlerMapping目的根据请求的 URL去找对应的控制器。③ HandlerMapping 匹配 URL定位到对应的 Controller同时把拦截器一起封装好返回给 DispatcherServlet。⚠️重点这一步仅仅是找到 Controller还没有执行业务代码。匹配不到就返回 404。④ DispatcherServlet 拿到 Controller 信息后交给 HandlerAdapter。不能直接调用 Controller因为 Spring 支持多种 Controller 实现需要适配器做统一调用。⑤ HandlerAdapter 完成适配调用 Controller 里面的业务方法执行业务。⑥ Controller 处理完业务返回 ModelAndView里面包含业务数据、要跳转的视图名称。 ⑦ HandlerAdapter 把 ModelAndView 交还给 DispatcherServlet。⑧ DispatcherServlet 把视图名称交给 ViewResolver 视图解析器解析器把逻辑视图名转换成真实的视图对象 View。⑨ View 做渲染把 Model 中的数据填充到页面。⑩ DispatcherServlet 把最终生成好的页面数据响应返回客户端。11.SpringBoot 自动配置原理①核心注解SpringBootApplication其封装了三个核心注解SpringBootConfiguration、EnableAutoConfiguration、ComponentScan②核心实现基于EnableAutoConfiguration注解该注解是自动配置的核心③关键步骤 1EnableAutoConfiguration通过Import导入自动配置选择器AutoConfigurationImportSelector④关键步骤 2选择器读取类路径下META-INF/spring.factories文件获取配置类全限定名⑤关键步骤 3通过条件注解如ConditionalOnClass、ConditionalOnMissingBean判断是否满足配置条件⑥最终结果满足条件的配置类会被导入 Spring 容器完成 Bean 的自动注册实现零配置或少配置。12.Spring 的常见注解有哪些①声明 Bean 相关Component通用、Service业务层、Repository数据访问层、Controller控制层②依赖注入相关Autowired按类型注入、Qualifier按名称限定、Resource按名称 / 类型注入JDK 注解③作用域相关Scope指定 bean 作用域如 singleton、prototype④配置相关Configuration标注配置类、ComponentScan扫描 Bean、Bean方法级声明 Bean⑤AOP 相关Aspect标注切面类、Pointcut定义切点、Before前置通知、After后置通知、Around环绕通知⑥其他常用Lazy懒加载、Value注入属性值、Transactional声明事务。13.SpringMVC 常见的注解有哪些①请求映射相关RequestMapping通用请求映射支持多请求方式、GetMappingGET 请求专用、PostMappingPOST 请求专用、PutMapping、DeleteMapping②请求参数接收RequestParam获取请求参数、PathVariable获取路径中的参数、RequestHeader获取请求头信息、CookieValue获取 Cookie 值③请求体 / 响应体相关RequestBody接收 HTTP 请求体的 JSON/XML 数据绑定到对象、ResponseBody将方法返回值转为 JSON/XML响应给客户端④其他常用RestController组合ControllerResponseBody、ModelAttribute绑定请求参数到模型、CrossOrigin解决跨域。14.SpringBoot 常见注解有哪些①核心启动注解SpringBootApplicationSpringBoot 项目启动核心封装三大注解②简化 Web 开发RestController替代ControllerResponseBody、GetMapping/PostMapping继承自 SpringMVC③配置相关ConfigurationProperties绑定配置文件属性到实体类、EnableConfigurationProperties启用配置属性绑定、PropertySource加载自定义配置文件④自动配置相关EnableAutoConfiguration开启自动配置、ConditionalOnXxx条件注解决定自动配置是否生效⑤其他常用SpringBootTest单元测试核心注解、EnableCaching开启缓存支持、EnableAsync开启异步支持。15.MyBatis 执行流程①读取 MyBatis 核心配置文件mybatis-config.xml获取数据源、别名、映射器等配置信息②通过配置信息构建 SqlSessionFactory会话工厂SqlSessionFactory 为单例设计③通过 SqlSessionFactory 创建 SqlSession 对象SqlSession 封装了数据库操作的所有方法④SqlSession 通过 Executor 执行器默认 SimpleExecutor执行数据库操作⑤Executor 执行时会获取 MappedStatement 对象封装 SQL 语句、参数类型、返回值类型等⑥对传入的参数进行参数映射处理 #{}、${} 占位符设置参数值⑦执行 SQL 语句获取数据库返回的结果集⑧对结果集进行结果映射将结果集封装为 Java 实体类 / 集合⑨返回映射后的结果完成数据库操作⑩关闭 SqlSession或通过 try-with-resources 自动关闭。16.MyBatis 是否支持延迟加载①MyBatis原生支持延迟加载也叫懒加载核心思想是按需加载数据②触发时机仅当实际调用关联对象的属性 / 方法时才会执行对应的 SQL 语句查询数据③开启方式通过 MyBatis 配置文件或配置类设置lazyLoadingEnabled true即可启用④适用场景多表关联查询时避免一次性加载所有关联数据提升查询性能。17.MyBatis 延迟加载的底层原理①MyBatis 延迟加载的底层核心是动态代理主要通过 CGLIB针对无接口类或 JDK 动态代理针对有接口类实现②初始化时查询主表数据后关联对象的属性会被赋值为动态代理对象而非实际数据此时不会执行关联查询 SQL③触发加载当程序调用该关联代理对象的任意方法 / 属性时会触发动态代理的拦截方法④执行查询拦截方法中会判断关联数据是否已加载若未加载则立即执行对应的关联查询 SQL⑤数据赋值查询到关联数据后将真实数据赋值给原属性后续调用直接使用真实数据避免重复查询。18.MyBatis 的一级、二级缓存用过吗①一级缓存1.默认开启无需额外配置2.底层基于 PerpetualCache使用 HashMap 存储3.作用域为SqlSession同一个 SqlSession 内的相同查询会复用缓存4.SqlSession 关闭 / 提交 / 回滚后一级缓存会被清空。5.当你在同一个 SqlSession里执行「任何增删改操作」不管改的是哪个订单 IDMyBatis 会清空当前 SqlSession 的所有一级缓存。②二级缓存1.需手动开启全局配置cacheEnabled true映射文件添加cache/2.底层同样基于 PerpetualCacheHashMap 存储3.作用域为Namespace/Mapper多个 SqlSession 可共享同一 Mapper 的二级缓存4.默认采用序列化方式存储数据要求缓存的实体类实现 Serializable 接口。19.MyBatis 的二级缓存什么时候会清理缓存中的数据①当当前 Namespace/Mapper 下执行新增insert、修改update、删除delete操作后该作用域下所有 select 查询的二级缓存会被自动清空②手动调用 SqlSession 的clearCache()方法会清空当前 SqlSession 关联的二级缓存数据③当二级缓存的过期时间配置eviction和flushInterval到达时会自动清理过期的缓存数据④关闭 SqlSessionFactory 时整个 MyBatis 的二级缓存会被全部清空。20.MyBatis和MyBatisPlus的区别MyBatis 是半自动 ORM 框架需手动编写单表 CRUD 的 SQL 语句和动态条件拼接分页、主键生成等功能也需自定义实现灵活性高适合复杂多表关联查询而 MyBatis-Plus 是基于 MyBatis 的增强工具库遵循只增强不修改原则封装了通用 BaseMapper/Service单表操作无需手写 SQL还提供 Lambda 条件构造器、内置分页插件、多种主键生成策略等便捷功能大幅提升单表开发效率同时完全兼容 MyBatis 的原生用法复杂 SQL 仍可通过 XML / 注解自定义二者可无缝结合使用单表为主用 MP 简化开发复杂查询用 MyBatis 保证灵活。