Spring的那些事儿
文章平均质量分 92
spring的IOC、DI以及AOP遍布Java项目的各个角落,探索它的存在形式,是一件十分有趣的事情
sermonlizhi
行百里者半九十
展开
-
详解Spring中BeanDefinition的创建过程
Spring容器在创建Bean之前,需要扫描指定包下的文件,然后生成BeanDifinition,下面将介绍Spring是如何进行扫描,然后再生成BeanDifinition1、scan方法的入参是字符串数组,可以同时指定多个包进行扫描,调用doScan方法来进行扫描public class ClassPathBeanDefinitionScanner{ public int scan(String... basePackages) { int beanCountAtScanStart = thi原创 2021-10-05 10:30:39 · 1228 阅读 · 0 评论 -
详解Spring启动实例化非懒加载的单例Bean
一、实例化所有非懒加载的单例不论是基于注解的Spring容器,还是基于xml的Spring容器,在启动的过程中,都会调用AbstractApplicationContext的refresh(),在该方法中,通过调用finishBeanFactoryInitialization(beanFactory)来实例化所有非懒加载的单例Beanprotected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFac原创 2021-10-13 16:38:46 · 654 阅读 · 0 评论 -
详解Spring的GetBean方法
Spring容器提供了五种获取Bean的方式,可以根据beanName获取Bean,也可以根据classType来获取Bean,所有根据beanName来获取Bean的方式,底层都会通过调用下面的doGetBean()来获取Bean对象protected <T> T doGetBean( String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly原创 2021-10-13 17:17:08 · 8650 阅读 · 1 评论 -
详解Spring的CreateBean方法
在AbstractBeanFactory类的doGetBean()中,都是调用AbstractAutowireCapableBeanFactory类的createBean()来创建Bean实例,该方法参数如下:protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)第一个参数为beanName,第二个为beanName对应的RootBeanDefinition,第三个参数为原创 2021-10-13 17:20:13 · 982 阅读 · 0 评论 -
详解Spring的Bean销毁
一、注册Bean销毁逻辑Bean的生命周期中,在完成了Bean的创建之后,会注册Bean销毁的逻辑protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { …… registerDisposableBeanIfNecessary(beanName, bean, mbd); ……原创 2021-10-13 17:23:16 · 5703 阅读 · 0 评论 -
Spring依赖注入(上)
一、依赖注入方式在创建Bean过程中,当完成了Bean的实例化以后,会对Bean进行属性填充,属性填充的过程中完成依赖注入依赖注入主要有两种方式手动注入自动注入1.1 手动注入手动注入通过xml配置的方式来完成,包含set方法注入和构造方法注入两种方式:set方法注入通过set方法注入时,对应的属性必须要有set方法,同时set方法的方法名必须满足JavaBean的规范<!--set注入--><bean id="userService" class="com.l原创 2021-10-13 17:25:41 · 225 阅读 · 0 评论 -
Spring依赖注入(下)
在《依赖注入(上)》介绍了,会根据注入点来进行注入,而属性注入点和方法注入点的具体实现略有不同,但它们的核心方法都是通过ConfigurableListableBeanFactory的resolveDependency()类获取属性值,下面将先简单介绍一下属性注入点和方法注入点的逻辑,然后重点介绍resolveDependency()是如何工作一、属性注入点1.1 调用注入方法属性注入点调用的是AutowiredFieldElement.inject(),源码如下:对于原型Bean,第一次创建的时候原创 2021-10-13 17:28:49 · 322 阅读 · 0 评论 -
详解@Resource解析过程
一、Resource注解解析过程@Resource和@Autowired处理的逻辑基本相同,都是先查找注入点,然后再根据注入点进行属性注入,所不同的是@Resource的解析是由CommonAnnotationBeanPostProcessor来完成的,@Autowired解析由AutowiredAnnotationBeanPostProcessor完成,下面介绍@Resource解析的全过程1.1 寻找注入点寻找注入点的时机与@Autowired一致,都是在实例化后,调用所有实现了MergedBea原创 2021-10-21 14:31:04 · 1294 阅读 · 2 评论 -
详解Spring的循环依赖
在介绍循环依赖之前,需要简单介绍一下AOP的原理,如果Spring项目使用@EnableAspectJAutoProxy开启了AOP,那么Spring启动的过程中,会创建一个AnnotationAwareAspectJAutoProxyCreator实例,该实例同样继承于BeanPostProcessor,所以在初始化后,会调用该实例的postProcessAfterInitialization()方法,而AOP生成代理对象的实现就是在该方法中完成1、场景再现如下所示,Spring创建OrderServ原创 2021-10-24 17:58:53 · 599 阅读 · 0 评论 -
Spring推断构造方法(上)
在Bean实例的生命周期中,会调用doCreateBean()方法来创建Bean实例,其中最主要的是实例化得到一个原始Bean,后续的属性填充、循环依赖以及AOP等等操作,都是依赖于原始的实例化bean对象,而实例化的时候,需要调用合适的构造方法来创建实例,Spring提供了推断构造方法的机制来获取最合适的构造方法核心的源码位于AbstractAutowireCapableBeanFactory的createBeanInstance()中一、其他方式创建实例1.1 通过instanceSupplier原创 2021-10-27 10:46:12 · 462 阅读 · 1 评论 -
Spring推断构造方法(中)
在《推断构造方法(上)》中介绍了通过determineConstructorsFromBeanPostProcessors()获取候选的构造方法,完成构造方法的获取后,下一步就是要推断使用哪一个构造方法,并根据构造方法实例化一个bean如果候选的构造方法不为空,或者指定了注入方式为构造注入,或者通过BeanDefinition指定了构造方法的参数值,或者通过getBean()获取实例的时候传入了方法参数值,对于这些情况,都需要进行构造注入,调用autowireConstructor()完成实例化如果以上原创 2021-10-27 17:19:29 · 447 阅读 · 0 评论 -
Spring推断构造方法(下)
一、前言Spring推断构造方法的前面两篇文章已经对查找候选构造方法以及推断使用的构造方法做了详细的介绍,在最后,这边文章主要简单介绍一下@Bean的情况首先Spring在启动的过程中,会把@Bean修饰的方法解析成BeanDefinition如果方法不是static的,BeanDefinition的参数如下:factoryBeanName为@Bean方法所在类的beanName,比如下面的例子中factoryBeanName就是"appConfig"@ComponentScan("com.l原创 2021-10-28 11:02:55 · 282 阅读 · 0 评论 -
Spring容器启动(上)
在Bean的生命周期中,尤其是在初始化的过程中,会用到大量的BeanProcessor实现类的方法,对Bean实例进行一系列的操作,其中包括查找注入点、依赖注入、AOP等等,而这其中用到的BeanProcessor实现类的实例正是在Spring容器启动的过程中创建的,在启动的过程中不仅会创建BeanProcessor的实例,也会设置BeanFactory的类加载器、SpringEL表达式解析器、类型转化注册器,扫描类文件生成BeanDefinition以及初始化事件监听器,同时非懒加载单例Bean的实例化过原创 2021-11-08 17:11:33 · 817 阅读 · 0 评论 -
Spring容器启动(中)
容器刷新在构造方法的初始以及配置类的注册中,大多BeanPostProcessor都只是生成了BeanDefinition,还没有完成实例化,但在AbstractApplicationContext的refresh()方法中,会进行一系列的初始化,以及对这些BeanPostProcessor进行排序。除了进行初始化之外,还会去设置一些EL表达式解析器、类型转化注册器等。1、 刷新前工作在构造方法中,Spring容器里面只是设置了操作系统的环境变量和JVM的环境变量,对于Web类型的Spring容器,还原创 2021-11-08 17:19:15 · 701 阅读 · 0 评论 -
Spring容器启动(下)
PostProcessors扫描与实例化在《Spring容器启动(中)》的文章中,介绍了Spring容器在启动时,调用refresh()方法进行各种初始化和实例化,而其中最重要的就是BeanFactoryPostProcessor扫描、实例化、执行以及BeanPostProcessor的初始化和实例化这边文章将重点介绍refresh()中的核心方法invokeBeanFactoryPostProcessors(beanFactory)和registerBeanPostProcessors(beanFac原创 2021-11-11 14:58:00 · 991 阅读 · 0 评论 -
Spring配置类解析(上)
在《Spring容器启动(下)》中说到了,Spring启动过程中最核心的方法就是invokeBeanFactoryPostProcessors(),该方法会按照优先级去调用实现了BeanDefinitionRegistryPostProcessor接口和BeanFactoryPostProcessor接口的postProcessBeanDefinitionRegistry()和postProcessBeanFactory(),而这两个方法中,实现了配置类的扫描解析与增强,这篇文章将重点介绍配置类的扫描过程。原创 2021-11-25 17:31:33 · 653 阅读 · 0 评论 -
Spring配置类解析(下)
多轮循环解析在《配置类解析(中)》篇,介绍了解析配置类的核心流程,主要是介绍了parese()方法中的流程,那么在该方法的do-while循环中,还有哪些部分呢,这里将重点介绍刚开始进行配置类解析时,获取到的配置类只是一小部分,更多的配置类是在解析过程中新生成,而新生成的配置类,一部分在当前轮解析的时候就已经解析过了,但还有一部分却没有解析。比如第二部分中介绍到的添加到当前配置类属性中的实例或资源,其中有importBeanDefinitionRegistrars、importedResources和B原创 2021-11-25 17:35:59 · 642 阅读 · 0 评论 -
Spring配置类解析(中)
一、解析配置类核心流程获取到所有的配置类之后,对它们进行排序,按照优先级对它们进行解析// Sort by previously determined @Order value, if applicable// 通过@Order可以排序,升序排序,order越小越靠前configCandidates.sort((bd1, bd2) -> { int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition()); i原创 2021-11-25 17:40:40 · 549 阅读 · 0 评论 -
Spring AOP源码解析(上)
一、动态代理Spring AOP技术底层采用动态代理来实现,其中Java本身提供了JDK的动态,而Spring提供了CGLIB的的动态,下面简单介绍一下这种动态代理的使用。1.1 JDK动态代理public interface OrderInterface { void test();}public class OrderService implements OrderInterface { @Override public void test(){ System.out.pr原创 2021-12-10 17:16:48 · 445 阅读 · 0 评论 -
Spring AOP源码解析(中)
上一篇文章中,介绍了Spring中动态代理的使用方式,通过ProxyFactory来创建代理对象,ProxyFactory可以通过addAdvisor()来添加匹配逻辑和代理逻辑,这边文章重点介绍ProxyFactory是如何产生代理对象以及代理对象是如何执行代理逻辑的一、ProxyFactory生成代理对象使用ProxyFactory添加advisor,并创建代理对象,调用代理对象的test()方法,代码如下:BeforeAdvisor:public class LizhiBeforeAdviso原创 2021-12-13 16:22:31 · 676 阅读 · 0 评论 -
Spring AOP源码解析(下)
在《Spring AOP源码分析(上)》介绍了在Spring AOP生成代理对象并作为Bean实例,以及@Before、@Around等注解的解析都是靠@EnableAspectJAutoProxy注解来完成的,这篇文章重点介绍该注解是如何实现上述功能的一、注册AutoProxyCreator@EnableAspectJAutoProxy注解如下,该注解通过@Import来加载AspectJAutoProxyRegistrar配置类,该配置类实现了ImportBeanDefinitionRegistra原创 2021-12-13 20:18:41 · 621 阅读 · 0 评论 -
Spring 事务底层源码解析(上)
Spring事务管理是基于Spring AOP的,我们在使用Spring事务管理时,需要在配置类上添加@EnableTransactionManagement注解,然后在业务类或方法上添加一个@Transactional注解,就可以开启一个事务,那么Spring是如果通过AOP来处理事务的呢?一、加载配置类@EnableTransactionManagement注解会加载TransactionManagementConfigurationSelector配置类,而该类实现了ImportSelector接原创 2021-12-14 17:31:40 · 481 阅读 · 0 评论 -
Spring 事务底层源码解析(下)
一、Spring 事务执行流程我们在使用Spring事务机制时,需要在配置类创建一个事务管理器的实例,用于处理事务提交、回滚、关闭等操作定义一个DataSourceTransactionManager实例的事务管理器@Beanpublic PlatformTransactionManager transactionManager() { DataSourceTransactionManager transactionManager = new DataSourceTransactionMana原创 2021-12-15 15:47:02 · 825 阅读 · 2 评论 -
Spring MVC执行流程解析
一、Spring MVC的执行流程上面介绍了Spring MVC的使用,配置了一个DispatcherServlet作为所有请求的入口,DispatcherServlet继承自抽象类FrameworkServlet,而FrameworkServlet又继承自HttpServlet,所有当有请求进来时,会先进入到FrameworkServlet的service()方法中,而在该方法中又会去调用父类HttpServlet的service()方法,该类的方法在《从Servlet到Spring MVC》中已经介绍原创 2021-12-16 21:13:52 · 940 阅读 · 0 评论