JAVA面试之spring篇

(搜索总结)该篇总结的不多,还会继续添加!


Spring

什么是三级缓存

Spring 使用三级缓存来解决循环依赖问题。三级缓存分别是:

一级缓存(Singleton Objects)

1、存储已经完全初始化完成的单例 Bean。

2、数据结构:Map<String, Object>,键是 Bean 的名称,值是对应的 Bean 实例。

3、作用:当一个 Bean 已经完全初始化后,它会被放入一级缓存,供后续使用。

二级缓存(Early Singleton Objects)

1、存储提前暴露的、尚未完全初始化的 Bean 实例(即“早期引用”)。

2、数据结构:Map<String, Object>,键是 Bean 的名称,值是 Bean 的早期引用。

3、作用:在 Bean 初始化过程中,如果其他 Bean 需要依赖当前 Bean,Spring 会将当前 Bean 的“早期引用”放入二级缓存,以供其他 Bean 使用。

三级缓存(Singleton Factories)

1、存储用于创建早期引用的工厂对象(ObjectFactory)。

2、数据结构:Map<String, ObjectFactory<?>>,键是 Bean 的名称,值是一个工厂对象。

3、作用:当一个 Bean 尚未完全初始化,但需要被其他 Bean 依赖时,Spring 会通过三级缓存中的工厂对象生成一个“早期引用”,并将其放入二级缓存

Spring如何解决循环依赖问题

Spring使用了三级缓存解决了循环依赖的问题。在populateBean()给属性赋值阶段里面Spring会解析你的属性,并且赋值,当发现,A对象里面依赖了B,此时又会走getBean方法,但这个时候,你去缓存中是可以拿的到的。因为我们在对createBeanInstance对象创建完成以后已经放入了缓存当中,所以创建B的时候发现依赖A,直接就从缓存中去拿,此时B创建完,A也创建完,一共执行了4次。至此Bean的创建完成,最后将创建好的Bean放入单例缓存池中。(非单例的实例作用域是不允许出现循环依赖)

BeanFactory和ApplicationContext的区别

1. BeanFactory是Spring里面最低层的接口,提供了最简单的容器的功能,只提供了实例化对象和拿对象的功能。

2. ApplicationContext应用上下文,继承BeanFactory接口,它是Spring的一各更高级的容器,提供了更多的有用的功能。如国际化,访问资源,载入多个(有继承关系)上下文 ,使得每一个上下文都专注于一个特定的层次,消息发送、响应机制,AOP等。

3. BeanFactory在启动的时候不会去实例化Bean,中有从容器中拿Bean的时候才会去实例化。ApplicationContext在启动的时候就把所有的Bean全部实例化了。它还可以为Bean配置lazy-init=true来让Bean延迟实例化

动态代理的实现方式,AOP的实现方式

1. JDK动态代理:利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。

2. CGlib动态代理:利用ASM(开源的Java字节码编辑库,操作字节码)开源包,将代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。

3. 区别:JDK代理只能对实现接口的类生成代理;CGlib是针对类实现代理,对指定的类生成一个子类,并覆盖其中的方法,这种通过继承类的实现方式,不能代理final修饰的类。

@Transactional错误使用失效场景

1. @Transactional 在private上:当标记在protected、private、package-visible方法上时,不会产生错误,但也不会表现出为它指定的事务配置。可以认为它作为一个普通的方法参与到一个public方法的事务中。

2. @Transactional 的事务传播方式配置错误。

3. @Transactional 注解属性 rollbackFor 设置错误:Spring默认抛出了未检查unchecked异常(继承自 RuntimeException 的异常)或者 Error才回滚事务;其他异常不会触发回滚事务。

4. 同一个类中方法调用,导致@Transactional失效:由于使用Spring AOP代理造成的,因为只有当事务方法被当前类以外的代码调用时,才会由Spring生成的代理对象来管理。

5. 异常被 catch 捕获导致@Transactional失效。

6. 数据库引擎不支持事务。

Spring中的事务传播机制

1. REQUIRED(默认,常用):支持使用当前事务,如果当前事务不存在,创建一个新事务。eg:方法B用REQUIRED修饰,方法A调用方法B,如果方法A当前没有事务,方法B就新建一个事务(若还有C则B和C在各自的事务中独立执行),如果方法A有事务,方法B就加入到这个事务中,当成一个事务。

2. SUPPORTS:支持使用当前事务,如果当前事务不存在,则不使用事务。

3. MANDATORY:强制,支持使用当前事务,如果当前事务不存在,则抛出Exception。

4. REQUIRES_NEW(常用):创建一个新事务,如果当前事务存在,把当前事务挂起。eg:方法B用REQUIRES_NEW修饰,方法A调用方法B,不管方法A上有没有事务方法B都新建一个事务,在该事务执行。

5. NOT_SUPPORTED:无事务执行,如果当前事务存在,把当前事务挂起。

6. NEVER:无事务执行,如果当前有事务则抛出Exception。

7. NESTED:嵌套事务,如果当前事务存在,那么在嵌套的事务中执行。如果当前事务不存在,则表现跟REQUIRED一样。

Spring中Bean的生命周期

Spring框架中,Bean的生命周期指的是从Bean的创建到销毁的一系列过程。这个过程通常涉及到几个关键的步骤,包括Bean的实例化、属性设置、初始化、使用以及销毁。下面详细介绍Spring中Bean的生命周期的主要阶段和相关的配置方法。

1. Bean的创建

当Spring容器启动时,它会根据配置文件(如XML配置、注解配置等)创建并初始化Bean。

2. Bean的实例化

通过构造器创建:当你在类中定义了构造器,并且Spring的配置文件中使用了<bean>标签或者使用了@Component、@Service、@Repository等注解时,Spring会调用这个类的构造器来创建Bean的实例。

通过静态工厂方法:可以通过配置<bean>标签的class属性指定一个静态工厂方法,该方法返回Bean的实例。

通过实例工厂方法:可以通过配置<bean>标签的factory-bean属性指定一个工厂Bean,然后通过factory-method属性指定一个工厂方法。

3. Bean的属性设置

一旦Bean被实例化,Spring会通过依赖注入(Dependency Injection, DI)来设置Bean的属性。这可以通过构造器注入、Setter方法注入或者字段注入等方式实现。

4. Bean的初始化

在Bean的属性被设置之后,Spring会调用一些特定的方法来进行初始化。这可以通过以下几种方式实现:

实现InitializingBean接口:实现afterPropertiesSet()方法。

使用@PostConstruct注解:在方法上添加@PostConstruct注解,该方法将在依赖注入完成后执行。

自定义初始化方法:可以在XML配置文件中使用init-method属性指定一个初始化方法,或者在类上使用@Bean(initMethod="methodName")指定初始化方法名。

5. Bean的使用

一旦Bean被初始化,它就可以被应用程序中的其他组件使用了。

6. Bean的销毁

当Spring容器关闭时,它会管理Bean的销毁过程。这可以通过以下方式实现:

实现DisposableBean接口:实现destroy()方法。

使用@PreDestroy注解:在方法上添加@PreDestroy注解,该方法将在容器销毁Bean之前执行。

自定义销毁方法:可以在XML配置文件中使用destroy-method属性指定一个销毁方法,或者在类上使用@Bean(destroyMethod="methodName")指定销毁方法名。

如下图可以增深理解

Spring的后置处理器

1. BeanPostProcessor:Bean的后置处理器,主要在bean初始化前后工作。(before和after两个回调中间只处理了init-method)

2. InstantiationAwareBeanPostProcessor:继承于BeanPostProcessor,主要在实例化bean前后工作(TargetSource的AOP创建代理对象就是通过该接口实现)

3. BeanFactoryPostProcessor:Bean工厂的后置处理器,在bean定义(bean definitions)加载完成后,bean尚未初始化前执行。

4. BeanDefinitionRegistryPostProcessor:继承于BeanFactoryPostProcessor。其自定义的方法postProcessBeanDefinitionRegistry会在bean定义(bean definitions)将要加载,bean尚未初始化前真执行,即在BeanFactoryPostProcessor的postProcessBeanFactory方法前被调用。

相关文章

java高级用法之:JNA中的回调

简介什么是callback呢?简单点说callback就是回调通知,当我们需要在某个方法完成之后,或者某个事件触发之后,来通知进行某些特定的任务就需要用到callback了。最有可能看到callbac...

从 Java 程序员到架构师:技术进阶与能力跃迁的完整路径(深度版)

#程序员如何进阶为架构师?#从 Java 程序员到架构师:技术进阶与能力跃迁的完整路径(深度版)一、架构师的核心能力模型架构师是技术与业务的桥梁,需要具备以下核心能力:1.1 系统设计能力案例解析:...

Java 8新特性全面详解:让编程更优雅的“黑科技”集锦

Java 8新特性全面详解:让编程更优雅的“黑科技”集锦1. Lambda表达式:从“命令式”到“声明式”的华丽转身大家还记得那些令人头大的匿名内部类吗?在Java 8之前,实现简单的功能往往需要写一...

使用Mockito测试Callback回调

概述在这个简短的教程中,我们将重点介绍如何使用流行的测试框架Mockito测试回调。我们将探索两种解决方案,首先使用ArgumentCaptor,然后使用直观的doAnswer()方法。Callbac...

Java CompletableFuture原理及应用场景详解

Java CompletableFuture原理及应用场景详解首先,原理部分。用户可能想知道CompletableFuture是如何工作的,内部机制是怎样的。我记得CompletableFuture基...