常见面试题13

简介: 本文详解Spring核心机制:Bean生命周期(实例化、依赖注入、初始化、销毁)、三级缓存无法解决构造函数循环依赖(需@Lazy解决)、AOP原理(动态代理实现日志、权限控制)及事务管理(@Transactional与传播行为),并梳理常用注解分类。

聊一聊Bean的生命周期 ?

额,这个详细的步骤还是挺多的,我之前看过一些源码,我就挑几个主要的步骤说一下,大概流程是这样的。

首先会通过一个非常重要的类,叫做BeanDefinition获取bean的定义信息,这里面就封装了bean的所有信息,比如,类的全路径,是否是延迟加载,是否是单例等这些信息。

  • 第一步在创建bean的时候,就是调用构造函数实例化bean。
  • 第二步是bean的依赖注入,比如一些set方法注入,像平时开发用的@Autowired都是这一步完成。
  • 第三步是处理Aware接口,如果某一个bean实现了Aware接口(包括BeanNameAware、BeanFactoryAware、ApplicationContextAware)就会重写方法执行。
  • 第四步是bean的后置处理器BeanPostProcessor的postProcessBeforeInitialization方法运行,这个是前置增强。
  • 第五步是初始化方法执行,比如实现了接口InitializingBean或者自定义了方法init-method标签或@PostContruct。
  • 第六步是执行了bean的后置处理器BeanPostProcessor的postProcessAfterInitialization方法运行,这个是前置增强主要是对bean进行增强,有可能在这里产生代理对象。
  • 到此,spring容器的bean已经创建完毕了,业务逻辑运行。
  • 最后一步是销毁bean,比如自定义的方法destroy-method或@PreDestroy执行。

构造函数的循环依赖,三级缓存可以解决吗?

嗯~ 构造函数的循环依赖,三级缓存是解决不了的。

这是因为,由于bean的生命周期中,构造函数是第一个执行的,如果在执行构造函数的时候,发现依赖了另外一个bean,并且是循环依赖,spring框架是解决不了的,此时就需要我们手动解决,当然解决方案,也很简单,通过一个注解就搞定了, 就是 @Lazy 注解,通过这个注解实现延迟加载,什么时候需要对象,再进行bean对象的创建。

什么是AOP ?

aop是面向切面编程,在spring中用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取公共模块复用,降低耦合,一般像系统的公共日志记录,事务处理,权限的控制等都可以通过AOP来实现。

可能继续追问的问题:

1). 你们项目中有没有使用到AOP?

这个很多地方都用到了,比如我们当时在后台管理系统中,就是使用aop来记录了系统的操作日志、以及权限控制。那就来说一下,记录日志的操作思路吧。

主要思路是这样的,使用aop中的环绕通知 加上 基于注解@annotation 的切点表达式来实现的。

  • 首先,自定义了一个注解,比如叫 @Log,然后哪些操作需要记录日志,我们就在哪些方法上加上这个注解。
  • 然后再定义一个切面类,通过环绕通知,来获取原始方法在运行的各项信息,比如:类信息、方法信息、注解、请求方式、请求参数、当前操作人、操作时间、返回值等信息,全部记录下来,保存在数据库中。

当时,我们主要记录的是一些核心业务模块的增删改的操作日志,主要便于数据追踪。

2). AOP的底层是如何实现的?

SpringAOP的底层主要是通过动态代理技术实现的,主要是两种代理技术。一种是JDK的动态代理,而JDK的动态代理呢,有限制,只能针对于实现了接口的类做代理,所以,在spring中还有一种是Cglib动态代理,那Cglib动态代理呢,就没有这个限制。

3). JDK动态代理 与 Cglib动态代理有什么区别呢?

  • 限制不同。 JDK动态代理,要求被代理对象必须实现了接口才可以。 而Cglib动态代理,无论是否实现接口都可以(只要类不是final修饰即可)。
  • 代理对象不同。 JDK动态代理生成的代理对象,与被代理对象其实是实现了相同的接口,可以说是兄弟关系。 而Cglib动态代理生成的代理对象,其实是继承了被代理类,是基于继承体系的,所以是父子关系。 也正是因为此,所以Cglib不能为被final修饰的类做代理。

Spring中的事务是如何实现的?

spring实现的事务本质就是aop完成,对方法前后进行拦截,在执行方法之前开启事务,在执行完目标方法之后根据执行情况提交或者回滚事务。 而如果我们进行项目开发,不存在分布式事务问题,我们就可以直接使用Spring提供的@Transactional注解来控制事务即可。

可能继续发问的问题:

1). 在开发中,有没有遇到事务失效的场景 ?

在刚开始上班做项目时,遇到过,但是现在在做项目,写代码时,都会规避这些坑。 事务失效比较典型的场景呢就是:

  • 第一个,如果业务方法上try、catch处理,自己处理了异常,没有抛出,就会导致事务失效,所以一般处理了异常以后,别忘了抛出去就行。
  • 第二个,如果方法抛出检查异常,如果报错也会导致事务失效,因为默认spring事务管理只会针对于RuntimeException进行回滚。那这个呢,就可以在spring事务的注解上,就是@Transactional上配置rollbackFor属性为Exception.class,这样别管是什么异常,都会回滚事务。
  • 第三个,是我早期开发中遇到的一个,如果业务方法上不是public修饰的,也会导致事务失效。

嗯,就能想起来那么多

2). 什么是事务的传播行为 ?

Spring的事务传播行为,指的是两个被事务控制的方法,相互调用的过程中,到底是加入到已存在的事务,还是创建一个新的事务,控制的是这个事儿。 我们设置事务的传播行为,可以通过 @Transactional 注解的propagation属性来设置,可取值有很多啊,但是常见的就只有两个:

  • REQUIRED:也是默认值,表示如果没有事务,就新建一个事务,如果有事务,就加入到已存在的事务中。
  • REQIRES_NEW:表示需要一个新的事务,无论当前环境是否存在事务,都会开启一个新的事务。

聊聊Spring框架中的常用注解 ?

额,这个就很多很多了。 我就分为这么几类,说一下吧。

第一类是:声明bean,有@Component、@Service、@Repository、@Controller

第二类是:依赖注入相关的,有@Autowired、@Qualifier、@Resourse

第三类是:设置作用域 @Scope

第四类是:spring配置相关的,比如@Configuration,@ComponentScan 和 @Bean

第五类是:跟aop相关做增强的注解 @Aspect,@Before,@After,@Around,@AfterReturning,@AfterThrowing,@Pointcut



目录
相关文章
|
2月前
|
Java 数据库连接 应用服务中间件
基于springboot的母婴健康交流系统
本平台旨在为新手父母提供专业、系统的婴幼儿健康知识与交流空间,整合权威资源,解决育儿信息碎片化与误导问题,支持经验分享与情感互助,助力科学育儿。
|
2月前
|
缓存 监控 Java
SpringBoot @Scheduled 注解详解
使用`@Scheduled`注解实现方法周期性执行,支持固定间隔、延迟或Cron表达式触发,基于Spring Task,适用于日志清理、数据同步等定时任务场景。需启用`@EnableScheduling`,注意线程阻塞与分布式重复问题,推荐结合`@Async`异步处理,提升任务调度效率。
456 128
|
2月前
|
JavaScript Java 数据库连接
基于springboot的网球场场地预约系统
本系统基于Vue、Spring Boot、Java等技术,构建智能化网球场预约平台,提升用户体验与场地利用率,推动体育产业数字化发展。
|
2月前
|
存储 NoSQL Java
配置RedisTemplate序列化机制
通过上述步骤,你可以灵活配置RedisTemplate的序列化机制,根据应用需求选择合适的序列化器,从而确保数据在Redis中的存储和读取效率最优化。配置合适的序列化机制对于性能和存储效率至关重要,而且这样可以确保数据在存储和传输过程中的结构清晰和一致性。
183 11
|
2月前
|
前端开发 Java API
Java入门教程:掌握Spring MVC的双向数据绑定技术
以上步骤展示了如何利用 Spring MVC 实现双向数据绑定:从显示表单、提交表单、验证输入、直至返回结果页面都涉及到不同层次间交互过程,在整个过程都无需手动去编写繁琐代码去手动获取或设置每一项值。
65 11
|
2月前
|
SQL Java 索引
常见面试题12
通过SkyWalking链路追踪或MySQL慢查询日志定位慢SQL,结合explain分析执行计划,优化索引与表设计,提升SQL性能。Spring中IOC实现对象托管,DI完成依赖注入,Bean默认单例非线程安全,作用域可配置,初始化时机分情况而定。
108 7
|
1月前
|
缓存 监控 算法
常见面试题17
本文介绍如何使用Sentinel配置限流,包括启动控制台、引入依赖、设置QPS或线程数规则,并讲解滑动窗口算法在时间窗口限流中的应用。同时概述了Gateway网关的路由、鉴权、限流、缓存、监控等核心作用,及其基于过滤器链的请求处理机制与常见内置过滤器的使用方式。
93 0
|
3月前
|
消息中间件 Java 测试技术
RocketMQ-5.3.1异常、原因汇总表
本简介汇总了常见的RocketMQ异常信息及其解决方案,涵盖主题配置、网络通信、SSL设置、权限控制、消息发送与消费等多个方面,帮助开发者快速定位和理解异常原因。
361 26
|
监控 负载均衡 Java
5 大 SpringCloud 核心组件详解,8 张图彻底弄懂
本文图文详解 Spring Cloud 的五大核心组件,帮助深入理解和掌握微服务架构。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
5 大 SpringCloud 核心组件详解,8 张图彻底弄懂
|
11月前
|
缓存 Java Maven
【简单四步教你解决♥十分有效】Maven依赖报错、依赖或插件导入失败的万能解决办法
【简单四步教你解决♥十分有效】Maven依赖报错、依赖或插件导入失败的万能解决办法!在处理Maven项目问题时,首先检查Maven配置是否正确。接着通过“File--Invalidata Caches”清除IDEA缓存并重启。使用Maven命令`mvn dependency:purge-local-repository`和`mvn dependency:resolve`清除本地依赖缓存。最后,在Terminal中输入`mvn clean install`完成构建。
3214 1
【简单四步教你解决♥十分有效】Maven依赖报错、依赖或插件导入失败的万能解决办法