深入理解Spring循环依赖
深入理解Spring循环依赖所谓循环依赖指的是:BeanA对象的创建依赖于BeanB,BeanB对象的创建也依赖于BeanA,这就造成了死循环,如果不做处理的话势必会造成栈溢出。Spring通过提前曝光机制,利用三级缓存解决循环依赖问题。本节将记录单实例Bean的创建过程,并且仅记录两种常见的循环依赖情况:普通Bean与普通Bean之间的循环依赖,普通Bean与代理Bean之间的循环依赖。
Bean创建源码我们先通过源码熟悉下Bean创建过程(源码仅贴出相关部分)。
IOC容器获取Bean的入口为AbstractBeanFactory类的getBean方法:
1234567891011public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory { ...... @Override public Object getBean(String name) throws BeansEx ...
深入理解Spring事件发布与监听
深入理解Spring事件发布与监听2020-06-22 | Visit count 1232243
在使用Spring构建的应用程序中,适当使用事件发布与监听的机制可以使我们的代码灵活度更高,降低耦合度。Spring提供了完整的事件发布与监听模型,在该模型中,事件发布方只需将事件发布出去,无需关心有多少个对应的事件监听器;监听器无需关心是谁发布了事件,并且可以同时监听来自多个事件发布方发布的事件,通过这种机制,事件发布与监听是解耦的。
本节将举例事件发布与监听的使用,并介绍内部实现原理。
事件发布监听例子新建springboot应用,boot版本2.4.0,引入如下依赖:
123456<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> &l ...
Spring声明式事务原理
Spring声明式事务原理在Spring-事务管理一节中,我们了解了在Spring中如何方便的管理数据库事务,并了解了一些和事务相关的专业术语。本节将通过一个简单的例子回顾Spring声明式事务的使用,并通过源码解读内部实现原理,最后通过列举一些常见事务不生效的场景来加深对Spring事务原理的理解。
事务例子回顾新建SpringBoot项目,Boot版本2.4.0,然后引入如下依赖:
12345678910111213141516171819<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot< ...
深入理解SpringAOP原理
AOP底层为动态代理,AOP指的是:在程序运行期间动态地将某段代码切入到指定方法指定位置进行运行的编程方式,相关设计模式为代理模式。本节将通过一个简单的例子回顾Spring AOP的使用,并且通过debug源码深入理解内部原理。hints:本节图片较多,加载较慢。
回顾Spring AOP的使用新建一个SpringBoot项目,SpringBoot版本为2.4.0,引入如下两个依赖:
12345678910<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> ...
深入理解Spring BeanPostProcessor & InstantiationAwareBeanPostProcessor
深入理解Spring BeanPostProcessor & InstantiationAwareBeanPostProcessor在深入学习Spring Bean生命周期一节中,我们学习了Bean后置处理器BeanPostProcessor,用于在Bean初始化前后插入我们自己的逻辑(Bean增强,Bean代理等)。今天偶然接触到BeanPostProcessor的子类InstantiationAwareBeanPostProcessor,用于Bean实例化前后处理。本节记录两者的区别以及简单原理分析。
两者比较Initialization为初始化的意思,Instantiation为实例化的意思。在Spring Bean生命周期中,实例化指的是创建Bean的过程,初始化指的是Bean创建后,对其属性进行赋值(populate bean)、后置处理等操作的过程,所以Instantiation执行时机先于Initialization。
类关系先来看看BeanPostProcessor的类结构:
方法解析
BeanPostProcessor
postProcessBeforeI ...
深入理解BeanFactoryPostProcessor & BeanDefinitionRegistryPostProcessor
深入理解BeanFactoryPostProcessor & BeanDefinitionRegistryPostProcessor本节主要记录BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor的方法执行时机以及简单原理分析。
BeanFactoryPostProcessor查看BeanFactoryPostProcessor源码:根据注释我们了解到postProcessBeanFactory方法的执行时机为:BeanFactory标准初始化之后,所有的Bean定义已经被加载,但Bean的实例还没被创建(不包括BeanFactoryPostProcessor类型)。该方法通常用于修改bean的定义,Bean的属性值等,甚至可以在此快速初始化Bean。
下面测试一波。
新建SpringBoot项目,Boot版本2.4.0,依赖如下:
1234<dependency> <groupId>org.springframework.boot</groupId> & ...
深入学习Spring Bean生命周期
深入学习Spring Bean生命周期所谓Spring Bean的生命周期指的是Bean从创建到初始化再到销毁的过程,这个过程由IOC容器管理。一个完整的Bean生命周期可以参考Spring Bean生命周期。这里我们主要记录一些和Bean生命周期相关的细节。
Bean的初始化和销毁在整个生命周期过程中,我们可以自定义Bean的初始化和销毁钩子函数,当Bean的生命周期到达相应的阶段的时候,Spring会调用我们自定义的Bean的初始化和销毁方法。自定义Bean初始化和销毁方法有多种方式,下面逐一介绍。
@Bean上一节中介绍了可以在配置类中通过@Bean注解来注册Bean,我们也可以通过它来指定Bean的初始化和方法。
为了演示,我们新建一个Spring Boot项目,然后创建一个User类:
1234567891011public class User { public User() { System.out.println("调用无参构造器创建User"); } public voi ...
深入学习Spring组件注册
深入学习Spring组件注册接触过Spring的同学肯定都听过IOC。在传统的Java编程中,当需要用到某个对象的时候,我们都是主动显式创建一个对象实例(new)。使用Spring后就不需要这样做了,因为Spring会帮我们在需要用到某些对象的地方自动注入该对象,而无须我们自己去创建。这种模式俗称控制反转,即IOC(Inversion of Control)。那么Spring是从什么地方获取到我们所需要的对象呢?其实Spring给我们提供了一个IOC容器,里面管理着所有我们需要的对象,组件注册就是我们去告诉Spring哪些类需要交给IOC容器管理。
这里主要记录组件注册的一些细节。
通过@Bean注册组件在较早版本的Spring中,我们都是通过XML的方式来往IOC容器中注册组件的,下面这段代码大家肯定不会陌生:
123// 返回 IOC 容器,基于 XML配置,传入配置文件的位置 ApplicationContext applicationContext = new ClassPathXmlApplicationContext("xxx.xml"); User ...
Spring Batch任务调度
Spring Batch任务调度在前面的例子中,我们配置的任务都是在项目启动的时候自动运行,我们也可以通过JobLauncher或者JobOperator手动控制任务的运行时机,这节记录下它们的用法。
框架搭建新建一个Spring Boot项目,版本为2.2.4.RELEASE,artifactId为spring-batch-launcher,项目结构如下图所示:剩下的数据库层的准备,项目配置,依赖引入和Spring Batch入门文章中的框架搭建步骤一致,这里就不再赘述。
此外,本节我们需要演示在Controller里通过JobLauncher或者JobOperator调度任务,所以我们还需在pom里引入web依赖:
1234<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
然后准备个任务,用于后续测试。 ...