当前位置: 首页 > news >正文

Spring相关的面试题

1、spring中bean的生命周期

spring bean的生命周期主要分为三大类 ,分别是创建-》使用-〉销毁。

在三大类下面又可以分为5个小类。分别是  实列化-〉初始化-》组册destruction回调-〉使用-〉销毁

这这其中 初始化也可以细分为 设置属性值,前置处理,后置处理 这些

1. 实例化Bean:
•Spring容器首先创建Bean实例。
 在AbstractAutowireCapableBeanFactory类中的createBeanlnstance方法中实现
2. 设置属性值:
 Spring容器注入必要的属性到Bean中。
•在AbstractAutowireCapableBeanFactory的populateBean方法中处理
3. 检查Aware:
如果Bean实现了BeanNameAware、BeanClassLoaderAware等这些Aware接口,Spring容器会调用它们。
在AbstractAutowireCapableBeanFactory的initializeBean方法中调用
4. 调用BeanPostProcessor的前置处理方法:
在Bean初始化之前,允许自定义的BeanPostProcessor对Bean实例进行处理,如修改Bean的状态。BeanPostProcessor的postProcessBeforelnitialization方法会在此时被调用。
由AbstractAutowireCapableBeanFactory的applyBeanPostProcessorsBeforelnitialization方法执行。
5. 调用InitializingBean的afterPropertiesSet方法:
提供一个机会,在所有Bean属性设置完成后进行初始化操作。如果Bean实现了InitializingBean接口,afterPropertiesSet方法会被调用。
在AbstractAutowireCapableBeanFactory的invokelnitMethods方法中调用。

6. 调用自定义init-method方法:

提供一种配置方式,在XML配置中指定Bean的初始化方法。如果Bean在配置文件中定义了初始化方法,那么该方法会被调用。
在AbstractAutowireCapableBeanFactory的invokelnitMethods方法中调用。
7. 调用BeanPostProcessor的后置处理方法:
在Bean初始化之后,再次允许BeanPostProcessor对Bean进行处理。BeanPostProcessor的postProcessAfterinitialization方法会在此时被调用。
由AbstractAutowireCapableBeanFactory的applyBeanPostProcessorsAfterlnitialization方法执行
8. 注册Destruction回调:
如果Bean实现了DisposableBean接口或在Bean定义中指定了自定义的销毁方法,Spring容器会为这些
Bean注册一个销毁回调,确保在容器关闭时能够正确地清理资源。
在AbstractAutowireCapableBeanFactory类中的registerDisposableBeanlfNecessary方法中实现
9.Bean准备就绪:
此时,Bean已完全初始化,可以开始处理应用程序的请求了。
10. 调用DisposableBean的destroy方法:
当容器关闭时,如果Bean实现了DisposableBean接口,destroy方法会被调用。
在DisposableBeanAdapter的destroy方法中实现
11. 调用自定义的destory-method
如果Bean在配置文件中定义了销毁方法,那么该方法会被调用。
在DisposableBeanAdapter的destroy方法中实现


可以看到,整个Bean的创建的过程都依赖于AbstractAutowireCapableBeanFactory这个类,而销毁主要依赖DisposableBeanAdapter这个类。

AbstractAutowireCapableBeanFactory 的入口处,doCreateBean的核心代码如下,其中包含了实例化、设置属性值、初始化Bean以及注册销毁回调的几个核心方法。

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {//实列化beanBeanWrapper instanceWrapper = null;if (mbd.isSingleton()) {instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);}if (instanceWrapper == null) {instanceWrapper = this.createBeanInstance(beanName, mbd, args);}//。。。。。。。Object exposedObject = bean;try {//设置属性值this.populateBean(beanName, mbd, instanceWrapper);//初始化beanexposedObject = this.initializeBean(beanName, exposedObject, mbd);} catch (Throwable var18) {Throwable ex = var18;if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException)ex).getBeanName())) {throw (BeanCreationException)ex;}throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);}//。。。。。try {//注册bean的销毁回调this.registerDisposableBeanIfNecessary(beanName, bean, mbd);return exposedObject;} catch (BeanDefinitionValidationException var16) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", var16);}}

2、使用Aop可以实现哪些功能?

2.1、通过ioc实现策略模式

很多时候,我们需要对不同的场景进行不同的业务逻辑处理,举个例子,譬如不同的场景需要不同支付方式,普通
的逻辑是使用if-else,如下所示:

public void use(String code) {
if(code .equals("weixin")) {
doWeiXinPay () ;
} else if (code .equals("alipay")) {
doAlipay();
} else {
doDothing();
}

如果code越来越多,这种if-else显然非常不合适,就需要我们借助Spring来完成策略模式

package com.hellobike.moon.api.pay;import org.springframework.beans.factory.InitializingBean;
import java.util.HashMap;
import java.util.Map;/*** @author 马震* @date 2024/7/11 16:40*/
public interface PayFacade extends InitializingBean {void pay();String getCode();@Overridedefault void afterPropertiesSet() throws Exception{PayFactory.register(getCode(),this);};class WeiXinPay implements PayFacade{@Overridepublic void pay() {// by WeiXin}@Overridepublic String getCode() {return "winxin";}}class AliPay implements PayFacade{@Overridepublic void pay() {// by AliPay}@Overridepublic String getCode() {return "alipay";}}class PayFactory {private static final Map<String,PayFacade> payFacadeMap = new HashMap<>();public static void register(String scene,PayFacade payFacade){payFacadeMap.put(scene,payFacade);}public static PayFacade get(String scene){return payFacadeMap.get(scene);}}}

这样子,调用方只需要调用PayFactory#get即可,不需要感知内部的实现细节和逻辑。
需要说明的是,这里使用了InitializingBean只是实现方式之一,还有其他的实现方式,如通过Autowired注解,
BeanPostProcess等,这里不做过多赘述。

2.2、通过Aop实现拦截

很多时候,我们一般是通过注解和AOP相结合。大概的实现思路就是先定义一个注解,然后通过AOP去发现使用过该注解的类,对该类的方法进行代理处理,增加额外的逻辑,譬如参数校验,缓存,日志打印等等,如下代码所示:

@Target({ElementType.METHOD,ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ParamsCheck {boolean ignore() default false;
}
@Aspect
@Component
@Slf4j
public class ValidateAspect {/*** 定义切点* @param paramsCheck*/@Pointcut("@annotation(ParamsCheck)")public void validate(ParamsCheck paramsCheck) {}/*** 环绕通知* @param pjp* @param paramsCheck* @return*/@Around("validate(paramsCheck)")public Object ParamsCheckAround(ProceedingJoinPoint pjp,ParamsCheck paramsCheck) throws Throwable {MethodSignature methodSignature = (MethodSignature) pjp.getSignature();Method method = methodSignature.getMethod();ParamsCheck annotation = method.getAnnotation(paramsCheck.getClass());if(annotation != null && annotation.ignore()){return pjp.proceed();}Object[] args = pjp.getArgs();for (Object arg : args) {if(arg == null){break;}//参数校验,失败抛出异常}return null;}
}

根据这个思路可以做一些日志拦截,缓存逻辑等等。

3、Spring的Aop在什么场景会失效

1、私有方法调用
2、静态方法调用
3、final方法调用
4、类内部自调用
5、内部类方法调用

4、Spring事物的传播机制有哪些

Spring的事务规定了7种事务的传播级别,默认的传播机制是REQUIRED


•REQUIRED,如果不存在事务则开启一个事务,如果存在事务则加入之前的事务,总是只有一个事务在执行
•REQUIRES_NEW,每次执行新开一个事务,如果当前存在事务,则把当前事务挂起
•SUPPORTS,有事务则加入事务,没有事务则普通执行
• NOT_SUPPORTED,有事务则暂停该事务,没有则普通执行
• MANDATORY,强制有事务,没有事务则报异常
•NEVER,有事务则报异常
• NESTED,如果之前有事务,则创建嵌套事务,嵌套事务回滚不影响父事务,反之父事务影响嵌套事务

 rollbackFor
rollbackFor是Spring事务中的一个属性,用于指定哪些异常会触发事务回滚。
在一个事务方法中,如果发生了rollbackFor属性指定的异常或其子类异常,则事务会回滚。如果不指定
rollbackFor,则默认情况下只有RuntimeException和Error会触发事务回滚。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • vue3中使用 tilwindcss报错 Unknown at rule @tailwindcss
  • QT之嵌入外部第三方软件到本窗体中
  • Java面试八股之Redis有哪些数据类型?底层实现分别是什么
  • 基于ssm的图书管理系统的设计与实现
  • jenkins打包java项目报错Error: Unable to access jarfile tlm-admin.jar
  • 部署大语言模型并对话
  • Docker 安装字体文件
  • 暑假第一次作业
  • wps 将列的内容转换为一个单元格内容,并以逗号分隔
  • python编程实例 计算字符串中空格、英文、数字、其它字符的数量 两种方式实现
  • 检索 Postgres 不同版本功能差异的神器
  • Docker Dockerfile:构建与优化
  • uniapp实现光标闪烁(配合自己的键盘)
  • 数据结构——考研笔记(一)绪论
  • 百日筑基第十八天-一头扎进消息队列1
  • 【399天】跃迁之路——程序员高效学习方法论探索系列(实验阶段156-2018.03.11)...
  • JavaScript 无符号位移运算符 三个大于号 的使用方法
  • jquery cookie
  • JSONP原理
  • k8s如何管理Pod
  • php ci框架整合银盛支付
  • Python学习之路16-使用API
  • Sublime text 3 3103 注册码
  • Tornado学习笔记(1)
  • Vue2.x学习三:事件处理生命周期钩子
  • vue和cordova项目整合打包,并实现vue调用android的相机的demo
  • Vue全家桶实现一个Web App
  • yii2权限控制rbac之rule详细讲解
  • 从零开始的webpack生活-0x009:FilesLoader装载文件
  • 计算机在识别图像时“看到”了什么?
  • 学习Vue.js的五个小例子
  • 一些css基础学习笔记
  • 用quicker-worker.js轻松跑一个大数据遍历
  • PostgreSQL之连接数修改
  • Spark2.4.0源码分析之WorldCount 默认shuffling并行度为200(九) ...
  • 带你开发类似Pokemon Go的AR游戏
  • 完善智慧办公建设,小熊U租获京东数千万元A+轮融资 ...
  • ​HTTP与HTTPS:网络通信的安全卫士
  • ​Kaggle X光肺炎检测比赛第二名方案解析 | CVPR 2020 Workshop
  • #include<初见C语言之指针(5)>
  • (k8s)Kubernetes 从0到1容器编排之旅
  • (k8s)Kubernetes本地存储接入
  • (php伪随机数生成)[GWCTF 2019]枯燥的抽奖
  • (补充)IDEA项目结构
  • (差分)胡桃爱原石
  • (第8天)保姆级 PL/SQL Developer 安装与配置
  • (附源码)php投票系统 毕业设计 121500
  • (附源码)springboot美食分享系统 毕业设计 612231
  • (九)c52学习之旅-定时器
  • (十八)SpringBoot之发送QQ邮件
  • (一)项目实践-利用Appdesigner制作目标跟踪仿真软件
  • (转)Google的Objective-C编码规范
  • (转)详解PHP处理密码的几种方式
  • (转)真正的中国天气api接口xml,json(求加精) ...
  • (轉貼) 蒼井そら挑戰筋肉擂台 (Misc)