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

相关推荐
九皇叔叔16 分钟前
Java循环结构全解析:从基础用法到性能优化
java·开发语言·性能优化
流星52112224 分钟前
GC 如何判断对象该回收?从可达性分析到回收时机的关键逻辑
java·jvm·笔记·学习·算法
csdn_aspnet24 分钟前
Java 圆台体积和表面积计算程序(Program for Volume and Surface area of Frustum of Cone)
java
杯莫停丶31 分钟前
设计模式之:外观模式
java·设计模式·外观模式
乐之者v32 分钟前
Mac常用软件
java·1024程序员节
TDengine (老段)1 小时前
TDengine 数据函数 ROUND 用户手册
java·大数据·数据库·物联网·时序数据库·tdengine·1024程序员节
TDengine (老段)1 小时前
TDengine 数学函数 RAND 用户手册
java·大数据·数据库·物联网·时序数据库·tdengine·涛思数据
從南走到北1 小时前
JAVA无人自助共享系统台球室源码自助开台约球交友系统源码小程序
java·微信·微信小程序·小程序·1024程序员节
JH30731 小时前
jvm,tomcat,spring的bean容器,三者的关系
jvm·spring·tomcat
野犬寒鸦1 小时前
从零起步学习MySQL || 第十章:深入了解B+树及B+树的性能优势(结合底层数据结构与数据库设计深度解析)
java·数据库·后端·mysql·1024程序员节