Spring源码复习

简介: Spring源码复习

一、Spring源码


1.1 spring 依赖注入的方式有几种?


1.手动注入:通过XML进行配置bean属性

1.1Set方法


f0967690df8146d29b3ba03f138a08ac.png可以通过ByType,ByName进行赋值


1.2.构造方法注入

9f1fd9c7e8ff41ffb891eb3daef19338.png

2.自动注入


2.1通过XML自动注入【set和构造方法】

2.2通过@Autowired自动注入

注入点:属性、构造方法、普通方法

遍历所有的注入点【方法—>注入点】

静态属性无法自动注入进去,源码会爆出非法异常


1.2 启动spring的两种方式


1.ClassPathXmlApplicationContext

2.AnniocationConfigApplication.getBean

启动spring的过程为:

bean生命周期

1.启动spring
ClassPathXmlApplicationContext  
AnniocationConfigApplication.getBean    
2.扫描
从配置类Appconfig中得到路径
得到Componment注解,得到类
3.懒加载单例bean
扫描出来的信息,进行保存BeanDefination到 CounrrentHashMap<BeanName【@Componment注解中的Value】,Bean对象> 中进行过滤
根据BeanDefination得到Bean是否是单例Bean,如果原型,每次创建Bean,如果单例Bean,去单例池中拿
BeanDefination【类型,Scope[prototype原型Bean,Singleton单例Bean],lazy懒加载机制】 
4.创建Bean---> doCreateBean(beanName,BeanDefination)  
先看看单例中有没有吗,没有则创建然后放入到单例池中  
创建单例池的Bean---> CounrrentHashMap(bean,beanDefination)
5.一、实例化
beanDefination.getBeanClass()
反射得到Bean,返回对象。
Bean容器利用java 反射机制实例化Bean
6.二、属性赋值
beanClass.getDeclaredFields()遍历属性,看看有什么属性
field.set()赋值
  若Bean实现了BeanNameAware接口,调用setBeanName()方法
  若Bean实现了BeanClassLoderAware接口,调用setBeanClassLoder()方法
  若Bean实现了BeanFactoryAware接口,则执行setBeanFactory方法
  如果Bean实现了ApplicationContextAware接口,则执行setApplicationContext方法;
    // 相当于切面,初始化之前,初始化之后  做什么事情
    如果加载了BeanPostProcessor相关实现类,则执行postProcessBeforeInitialization方法;
7.如果Bean实现了InitializingBean接口,则执行afterPropertiesSet方法;
    如果Bean定义初始化方法(PostConstruct注解或者配置的init-method),则执行定义的初始化方法;
    如果加载了BeanPostProcessor相关实现类,则执行postProcessAfterInitialization方法;
8.当要销毁这个Bean时,如果Bean实现了DisposableBean接口,则执行destroy方法。

c277c3b67f2c41a8a87c80a605c10c99.png

54c52d0d4c8e4a3d88603987703d34a3.png

1.3 Spring循环依赖


文章核心:spring循环依赖细节总结

循环依赖细节总结


fc987ec47e9f4c77b6213a75901f2460.png

e2e797321d5544028d2dad782c3230e4.png

一级缓存:缓存最终的单例池对象: 
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
二级缓存:缓存初始化的对象:
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);
三级缓存:缓存对象的ObjectFactory: 
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

1.4 二级缓存就已经解决了循环依赖了,为神魔需要三级缓存?


一个缓存其实就是两个Map,A B 就能解决问题了

正常的场景一般没有问题,有什么特殊场景会有问题?


  在上面第5步里面,Bean的后置处理器BeanPostProcessor,可能会进行AOP
      1.如果配置了切面AOP才会进行AOP,AOP底层是采用动态代理实现的【JDK CGLIB】
      2.AOP会生成一个代理对象,一个原始对象,一个代理对象,肯定会把代理对象放入到单例池中
      3.在原始对象赋值的时候,执行完毕后,代理对象放入后会发生冲突,而B属性是原始对象  
  问题解决:
      1.一个原始对象,一个代理对象,AOP提前进行,在原始对象之后就进行生成代理对象,全部都是代理对象了
      原始对象--->AOP--->代理对象--->放入缓存Map    没有问题了

1.5 Bean对象和创建的对象有什么区别?

// UserService 里面有一个User属性
UserService userService = context.getBean("userService",UserService.class); // 单例决定
UserService userService2 = new UserService();


1.引用地址不同

2.Bean里面的User是有值的【自动填充属性】,而new出来的是没有的


1.6 BeanDefination是什么?


BeanDefination【ByType、ByName类型,Scope[prototype原型Bean,Singleton单例Bean], lazy懒加载机制】

3.懒加载单例bean
扫描出来的信息,进行保存BeanDefination到 CounrrentHashMap<BeanName【@Componment注解中的Value】,Bean对象> 中进行过滤
根据BeanDefination得到Bean是否是单例Bean,如果原型,每次创建Bean,如果单例Bean,去单例池中拿
4.创建Bean---> doCreateBean(beanName,BeanDefination)  
先看看单例中有没有吗,没有则创建然后放入到单例池中  
创建单例池的Bean---> CounrrentHashMap(bean,beanDefination)

1.7 什么是 BeanPostProcessor 后置处理器?


等待组件初始化完成,后置处理器才会工作

1.如BeanFactoryPostProcessor 操作BeanFactory

2.包扫描,扫到@Component后,就会生成BeanDefination定义

如 BeanFactoryPostProcessor
BeanFactory级别的处理,是针对整个Bean的⼯⼚进⾏处理,典型应⽤:PropertyPlaceholderConfigurer(属性替换符),此接⼝只提供了⼀个⽅法
1.其中有个⽅法名为getBeanDefinition的⽅法,我们可以根据此⽅法,找到我们定义bean 的BeanDefinition对象。然后我们可以对定义的属性进⾏修改,以下是BeanDefinition中的⽅法
2.⽅法名字类似我们bean标签的属性,setBeanClassName对应bean标签中的class属性,所以当我们拿到BeanDefinition对象时,我们可以⼿动修改bean标签中所定义的属性值。

1.8 BeanFactory与ApplicationContext的区别?


ApplicationContext是BeanFactory的一种实现

通常情况,BeanFactory 的实现是使用懒加载的方式,这意味着 beans 只有在我们通过 getBean() 方法直接调用它们时才进行实例化实现 BeanFactory 最常用的 API 是 XMLBeanFactory


public class HelloWorldApp {
        public static void main(String[] args) {
            XmlBeanFactory factory = new XmlBeanFactory(new ClassPathResource("beans.xml"));
            HelloWorld obj = (HelloWorld) factory.getBean("helloWorld");
            obj.getMessage();
        }
    }

ApplicationContext 接口


ApplicationContext 是 Spring 应用程序中的中央接口,用于向应用程序提供配置信息它继承了 BeanFactory 接口,所以 ApplicationContext 包含 BeanFactory 的所有功能以及更多功能!它的主要功能是支持大型的业务应用的创建特性:

Bean instantiation/wiring


Bean 的实例化/串联


自动的 BeanPostProcessor 注册


自动的 BeanFactoryPostProcessor 注册


方便的 MessageSource 访问(i18n)


ApplicationEvent 的发布与 BeanFactory 懒加载的方式不同,它是预加载,所以,每一个 bean 都在 ApplicationContext 启动之后实例化

public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        HelloWorld obj = (HelloWorld) context.getBean("helloWorld");
        obj.getMessage();
    }

1.9 BeanFactory 与 FactoryBean的区别??


BeanFactory

这个其实是所有Spring Bean的容器根接口,给Spring 的容器定义一套规范,给IOC容器提供了一套完整的规范,比如我们常用到的getBean方法等

getBean(String name): Spring容器中获取对应Bean对象的方法,如存在,则返回该对象
containsBean(String name):Spring容器中是否存在该对象
isSingleton(String name):通过beanName是否为单例对象
isPrototype(String name):判断bean对象是否为多例对象
isTypeMatch(String name, ResolvableType typeToMatch):判断name值获取出来的bean与typeToMath是否匹配
getType(String name):获取Bean的Class类型
getAliases(String name):获取name所对应的所有的别名


使用ClassPathXmlApplicationContext读取对应的xml文件实例对应上下文对象

FactoryBean


该类是SpringIOC容器是创建Bean的一种形式,这种方式创建Bean会有加成方式,融合了简单的工厂设计模式于装饰器模式

T getObject():返回实例
Class<?> getObjectType();:返回该装饰对象的Bean的类型
default boolean isSingleton():Bean是否为单例

区别:


BeanFactory:负责生产和管理Bean的一个工厂接口,提供一个Spring Ioc容器规范,
FactoryBean: 一种Bean创建的一种方式,对Bean的一种扩展。对于复杂的Bean对象初始化创建使用其


目录
相关文章
|
2月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
114 2
|
2月前
|
数据采集 监控 前端开发
二级公立医院绩效考核系统源码,B/S架构,前后端分别基于Spring Boot和Avue框架
医院绩效管理系统通过与HIS系统的无缝对接,实现数据网络化采集、评价结果透明化管理及奖金分配自动化生成。系统涵盖科室和个人绩效考核、医疗质量考核、数据采集、绩效工资核算、收支核算、工作量统计、单项奖惩等功能,提升绩效评估的全面性、准确性和公正性。技术栈采用B/S架构,前后端分别基于Spring Boot和Avue框架。
114 5
|
15天前
|
监控 JavaScript 数据可视化
建筑施工一体化信息管理平台源码,支持微服务架构,采用Java、Spring Cloud、Vue等技术开发。
智慧工地云平台是专为建筑施工领域打造的一体化信息管理平台,利用大数据、云计算、物联网等技术,实现施工区域各系统数据汇总与可视化管理。平台涵盖人员、设备、物料、环境等关键因素的实时监控与数据分析,提供远程指挥、决策支持等功能,提升工作效率,促进产业信息化发展。系统由PC端、APP移动端及项目、监管、数据屏三大平台组成,支持微服务架构,采用Java、Spring Cloud、Vue等技术开发。
|
1月前
|
存储 缓存 Java
Spring面试必问:手写Spring IoC 循环依赖底层源码剖析
在Spring框架中,IoC(Inversion of Control,控制反转)是一个核心概念,它允许容器管理对象的生命周期和依赖关系。然而,在实际应用中,我们可能会遇到对象间的循环依赖问题。本文将深入探讨Spring如何解决IoC中的循环依赖问题,并通过手写源码的方式,让你对其底层原理有一个全新的认识。
65 2
|
2月前
|
前端开发 Java 开发者
Spring生态学习路径与源码深度探讨
【11月更文挑战第13天】Spring框架作为Java企业级开发中的核心框架,其丰富的生态系统和强大的功能吸引了无数开发者的关注。学习Spring生态不仅仅是掌握Spring Framework本身,更需要深入理解其周边组件和工具,以及源码的底层实现逻辑。本文将从Spring生态的学习路径入手,详细探讨如何系统地学习Spring,并深入解析各个重点的底层实现逻辑。
79 9
|
4月前
|
缓存 安全 Java
Spring框架中Bean是如何加载的?从底层源码入手,详细解读Bean的创建流程
从底层源码入手,通过代码示例,追踪AnnotationConfigApplicationContext加载配置类、启动Spring容器的整个流程,并对IOC、BeanDefinition、PostProcesser等相关概念进行解释
388 24
|
4月前
|
缓存 Java 开发工具
Spring是如何解决循环依赖的?从底层源码入手,详细解读Spring框架的三级缓存
三级缓存是Spring框架里,一个经典的技术点,它很好地解决了循环依赖的问题,也是很多面试中会被问到的问题,本文从源码入手,详细剖析Spring三级缓存的来龙去脉。
240 24
|
3月前
|
Java Spring
Spring底层架构源码解析(三)
Spring底层架构源码解析(三)
216 5
|
3月前
|
XML Java 数据格式
Spring底层架构源码解析(二)
Spring底层架构源码解析(二)
|
3月前
|
Java Spring 容器
Spring IOC、AOP与事务管理底层原理及源码解析
【10月更文挑战第1天】Spring框架以其强大的控制反转(IOC)和面向切面编程(AOP)功能,成为Java企业级开发中的首选框架。本文将深入探讨Spring IOC和AOP的底层原理,并通过源码解析来揭示其实现机制。同时,我们还将探讨Spring事务管理的核心原理,并给出相应的源码示例。
163 9