Spring面试题二

1、Spring框架中的Bean的作用域

  • singleton:Spring只会为该bean对象创建唯一实例,Spring中的bean默认都是单例
  • prototype:每次获取bean,Spring会创建一个新的实例
  • requset:每一次HTTP请求,Spring会创建一个新的bean实例
  • session:不同的HTTP会话,Spring会创建不同的的bean实例
XML 复制代码
#通过XML方式设置bean的作用域

<bean id="demoDaoBean" class="com.apesource.dao.DemoDAOImpl" scope="singleton"/>
XML 复制代码
//通过注解方式设置bean的作用域

@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class DemoDAOImpl implements IDemoDAO{ }

2、Spring框架中Bean的线程安全

  • 对于 prototype 作用域的 Bean,每次都创建一个新对象 ,也就是线程之间不存在Bean共享,因此不会有线程安全问题
  • 对于 singleton 作用域的 Bean,所以的线程都共享一个单例状态的Bean,存在资源竞争,因此时存在线程安全的
  • 解决办法
    • 对于 singleton 作用域的单例Bean,他的线程安全问题,有常见的两种解决办法
      • 在bean 中尽量避免定义可变的成员变量(用于保存数据的成员变量);
      • 在类中定义一个ThreadLocal成员变量,将需要可变的成员变量保存在ThreadLocal中;

3、Spring框架中的Bean声生命周期

Spring Bean的生命周期总体分为四个阶段:实例化=>属性化=>初始化=>销毁

1、实例化Bean:

根据配置文件中Bean的定义,利用Java Reflection反射技术创建Bean的实例

2、注入对象的属性值(或对象)
3、处理各种Aware接口:

Spring会检测Bean是否实现了xxxAware接口,通过Aware类型的接口,可以让Spring框架为当前Bean注入响应的内容

  • 如果 Bean 实现 BeanNameAware 接口,会调用它实现的 setBeanName(String beanId)方法,注入 Bean 的名字;
  • 如果 Bean 实现 BeanClassLoaderAware 接口,调用 setBeanClassLoader()方法,注入ClassLoader 对象的实例;
  • 如果 Bean 实现 BeanFactoryAware 接口,会调用它实现的setBeanFactory()方法,注入的是 Spring 工厂;
  • 如果 Bean 实现 ApplicationContextAware 接口,会调用 setApplicationContext()方法,注入 Spring 上下文;

4 、执行BeanPostProcessor前置处理:

如果想对 Bean进行一些自定义的前置处理,那么可以让 Bean 实现了BeanPostProcessor 接口,将会在该阶段调用 postProcessBeforeInitialization(Object obj, String s)方法。

5、 执行InitializingBean初始化方法:

如果 Bean 实现了InitializingBean 接口,执行 afeterPropertiesSet()方法。

6、执行init-method自定义初始化方法:

如果 Bean 在 Spring 配置文件中配置了init-method 属性,则会自动调用其配置的初始化方法。

7、执行BeanPostProcessor后置处理:

如果这个 Bean 实现了BeanPostProcessor接口,将会调用 postProcessAfterInitialization(Object obj,String s)方法,由于这个方法是在 Bean初始化结束后调用

8、执行DisposableBean销毁Bean:

当 Bean 不再需要时,会经过清理阶段,如果 Bean 实现了 DisposableBean 这个接口,会调用其实现的destroy()方法执行销毁;

9、执行destroy-method自定义销毁方法:

如果这个Bean的Spring 配置中配置了 destroy-method 属性,会自动调用其配置的自定义销毁方法。

4、Sprng框架如何解决循环依赖

循环依赖问题是指:类与类之间的依赖关系形成了闭环,就会导致循环依赖问题的产生。例如A类依赖了B类,B类依赖了C类,而最后C类又依赖了A类,这样就形成了循环依赖问题。

为了解决循环依赖问题,Spring容器采用了以下几种策略:

三级缓存:Spring容器使用三级缓存来解决属性循环依赖。

  • 第一级缓存是SingletonObjects,用于存储完全初始化的bean;
  • 第二级缓存是earlySingletonObjects,用于存储已经创建但尚未初始化的bean;
  • 第三级缓存是singletonFactories,用于存储用于创建bean的ObjectFatory
  • 当容器遇到循环依赖时,它会尝试从第二级或第三级缓存中获取bean,而不是直接实例化它。

延迟初始化 :Spring容器允许延迟初始化bean,这意味着在需要时才创建和初始化bean。这有助于避免在循环依赖的情况下过早地实例化bean。

代理对象 :对于通过AOP增强的bean,Spring容器会创建一个代理对象来替代原始bean。这个代理对象负责处理循环依赖,同时保留原始bean的行为。

5、Spring框架中有那些注解

  • 用于声明的注解:
  1. @Component:通用Bean的注解,可标注任意类为Bean如果一个Bean不知道属于哪个层,可以使用@Component注解标注。
  2. @Repository:定义数据访问层Bean的注解。
  3. @Service:定义业务层Bean的注解。
  4. @Controller:定义控制器Bean的注解。
  • 用于注入的注解:
  1. @Autowired:按类型自动注入
  2. @Qualifier::按名称自动注入
  • 声明配置、扫描、启用特性的注解:
  • @Configuration:声明配置类
  • @ComponentScan:组件扫描
  • @EnableScheduling:任务调度
  • @EnableAspectJAutoProxy:启动自动代理工程、

6、Spring框架中用到的设计模式

  • 工厂模式:Spring 使用工厂模式,通过 BeanFactory 或 ApplicationContext 来创建对象;
  • 单例模式:Bean 默认作用域为单例,按照单例设计模式进行设计实现;
  • 策略模式: Resource 的实现类,针对不同的资源文件,实现了不同方式的资源获取策略;
  • 代理模式: Spring 的 AOP 的实现依靠动态代理(JDK的反射和CGLIB);
  • 模板方法: Spring 提供了 JdbcTemplate,RedisTemplate 等模板对象,将相同的操作步骤进行了封装;
  • 适配器模式:Spring AOP 的增强或通知(Advice)使用到了适配器模式, Spring MVC 中也用到了适配器模式适配 Controller;

7、Spring 框架中AOP的基本理解

关键字:AOP名词解释,AOP实现原理(动态代理)

  • AOP(Aspect-Oriented Programming:面向切面编程):将那些与业务无关,但为业务模块所共同调用的逻辑(例如事务处理、日志管理、权限控制等)封装抽取成一个可重用的模块,这个模块被命名为"切面"(Aspect),便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性。
  • Spring AOP 基于动态代理实现:
    • 如果被代理的对象,已经实现某个接口,则 Spring AOP 会使用 JDK Proxy(反射),基于接口的方式,创建代理对象( JDK 动态代理的核心是 InvocationHandler接口和 Proxy类);
    • 如果被代理的对象,没有实现某个接口,就无法使用 JDK Proxy去进行代理了,这时侯SpringAOP会使用使用Cglib,基于继承的方式,生成一个被代理对象的子类来作为代理(Cglib 动态代理的核心是 MethodInterceptor 接口和 Enhancer类);

8、Spring AOP和AspectJ AOP有什么区别?

关键字:增强方式的差异(运行时、编译时),实现方式的差异(动态代理、字节码操作)

  • Spring AOP 已经集成了 AspectJ, Aspect] 是一个 Java 技术生态系统中实现 AOP 编程思想的独立框架; AspectJ 相比于 Spring AOP 功能更加强大,但是 Spring AOP 相对来说更简单更容易;
  • Spring AOP 属于运行时增强,而 AspectJ是编译时增强;
  • Spring AOP 基于动态代理( Proxying),而 AspectJ基于字节码操作( Bytecode Manipulation );

9、Spring AOP有哪些通知类型?

关键字: 分别介绍每种通知的实现接口,执行方式

  • 前置通知:实现 MethodBeforeAdvice 接口,在目标方法调用前,执行通知;
  • 环绕通知:实现 MethodInterceptor 接口,是一个包围目标方法的通知。环绕通知可以在方法调用前后完成自定义的行为。
  • 后置通知:实现 AfterReturningAdvice 接口,在在目标方法调用后,执行通知(如果方法抛出异(=常,则不执行通知);
  • 异常通知:实现 ThrowsAdvice 接口,在方法抛出异常时,执行通知;

10、Spring 管理事务的方式有几种?

  • 编程式事务:在代码中硬编码(不推荐使用):通过TransactionTemplate或者TransactionManager手动个管理事物实际应用中很少使用,用于理解 Spring 事务管理。
  • 声明式事物:在 XML 配置文件或者基于注解@Transactional (推荐使用),通过 AOP实现。

11、Spring 事务中有哪几种事务传播行为?

事务传播行为是为了解决业务层方法之间互相调用时,产生事务问题。

当事务方法被另一个事务方法调用时,必须指定事务应该如何传播。例如:方法可能继续在现有事务中运行,也可能开启一个新事务,并在自己的事务中运行。

事务传播行为有如下分类:

  1. TransactionDefinition.PROPAGATION_REQUIRED

如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。 @Transactional

注解默认使用的事物传播行为

  1. TransactionDefinition.PROPAGATION_REQUIRES_NEW

创建一个新的事务,如果当前存在事务,则把当前事务挂起。也就是说不管外部方法是否开启事务,Propagation.REQUIRES_NEW修饰的内部方法会新开启自己的事务,且开启的事务相互独立,互不干扰。

  1. TransactionDefinition.PROPAGATION NESTED

如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取

值等价于TransactionDefinition.PROPAGATION_REQUIRED。

  1. TransactionDefinition.PROPAGATIÓN_MANDATORY

如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。(mandatory:代表强制性)

  1. TransactionDefinition.PROPAGATION_SUPPORTS

如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。

  1. TransactionDefinition.PROPAGATION_NOT_SUPPORTED

以非事务方式运行,如果当前存在事务,则把当前事务挂起。

  1. TransactionDefinition.PROPAGATION_NEVER

以非事务方式运行,如果当前存在事务,则抛出异常。

12、Spring 事务中有哪几种事务隔离级别?

  1. TransactionDefinition.ISOLATION_DEFAULT 默认隔离级别

使用当前数据库的默认隔离级别,MySQL 默认采用的是可重复读 REPEATABLE_READ 隔离级

别。Oracle 默认采用的是读已提交 READ_COMMITTED 隔离级别.

2.TransactionDefinition.ISOLATION_READ_UNCOMMITTED 读未提交

最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读

  1. TransactionDefinition.ISOLATION_READ_COMMITTED 读已提交

允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生

  1. TransactionDefinition.ISOLATION_REPEATABLE_READ 可重复读

对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。

  1. TransactionDefinition.ISOLATION_SERIALIZABLE 串行化

最高的隔离级别,完全服从 ACID 的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读,不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。

相关推荐
成富4 分钟前
文本转SQL(Text-to-SQL),场景介绍与 Spring AI 实现
数据库·人工智能·sql·spring·oracle
Re.不晚11 分钟前
Java入门15——抽象类
java·开发语言·学习·算法·intellij-idea
雷神乐乐17 分钟前
Maven学习——创建Maven的Java和Web工程,并运行在Tomcat上
java·maven
码农派大星。21 分钟前
Spring Boot 配置文件
java·spring boot·后端
顾北川_野28 分钟前
Android 手机设备的OEM-unlock解锁 和 adb push文件
android·java
江深竹静,一苇以航30 分钟前
springboot3项目整合Mybatis-plus启动项目报错:Invalid bean definition with name ‘xxxMapper‘
java·spring boot
confiself1 小时前
大模型系列——LLAMA-O1 复刻代码解读
java·开发语言
Wlq04151 小时前
J2EE平台
java·java-ee
XiaoLeisj1 小时前
【JavaEE初阶 — 多线程】Thread类的方法&线程生命周期
java·开发语言·java-ee
杜杜的man1 小时前
【go从零单排】go中的结构体struct和method
开发语言·后端·golang