【Spring】手动实现Spring底层机制-问题的引出

这篇具有很好参考价值的文章主要介绍了【Spring】手动实现Spring底层机制-问题的引出。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

🎄欢迎来到@边境矢梦°的csdn博文🎄

🎄本文主要梳理手动实现Spring底层机制-问题的引出 🎄
🌈我是边境矢梦°,一个正在为秋招和算法竞赛做准备的学生🌈
🎆喜欢的朋友可以关注一下🫰🫰🫰,下次更新不迷路🎆

Ps: 月亮越亮说明知识点越重要 (重要性或者难度越大)🌑🌒🌓🌔🌕   

目录

🌸底层难点问题的引出🚀

🌈问题的概念解释

🎈BeanDefinition

🥝类加载器和类路径classPath


【Spring】手动实现Spring底层机制-问题的引出,Java,spring,java,后端

🌸底层难点问题的引出🚀

1. 底层如何实现依赖

2. 底层如何实现singleton (单例池)

3. 底层如何实现prototype (多例)

4. 底层如何实现IOC容器创建和初始化(之前用反射实现过, 较浅, 继续深入)

5. 底层如何实现getBean()

6. 底层如何实现BeanPostProcessor

7. Spring底层如何实现Bean后置处理器机制

8. 原生Spring底层如何实现AOP


🌈问题的概念解释

  1. spring底层实现依赖注入(Dependency Injection,DI)的主要机制是通过反射和配置元数据来实现的。依赖注入是Spring框架的核心功能之一,它允许开发者将一个Bean所依赖的其他Bean(依赖项)动态地注入到该Bean中而不需要硬编码这些依赖项。以下是Spring底层如何实现依赖注入的关键步骤:
    1. Bean Definition 注册:在Spring容器初始化的过程中,所有的Bean定义(Bean的类名、属性、依赖等信息)都会被注册到容器的BeanFactory中。这些Bean定义可以通过XML配置文件、Java注解或Java配置类来定义。

    2. 依赖关系定义:在Bean定义中,可以使用不同的方式来定义Bean之间的依赖关系。最常见的方式是使用构造函数注入(Constructor Injection)或Setter方法注入(Setter Injection)。依赖关系可以通过依赖注入的标签或注解来表示。

    3. 依赖解析和注入:当容器需要创建一个Bean实例时,它会检查该Bean的定义,以确定它所依赖的其他Bean。容器会自动解析这些依赖关系,并尝试实例化或获取依赖的Bean。

    4. 依赖注入:容器会将依赖项注入到目标Bean中。这可以通过调用目标Bean的构造函数、Setter方法、字段注入等方式来实现,具体取决于依赖关系的定义方式。

    5. 依赖的生命周期管理:Spring容器负责管理依赖项的生命周期。通常,依赖项的生命周期与目标Bean的生命周期相匹配。如果依赖项是Singleton作用域的Bean,那么它只会被创建一次并在容器启动时初始化;如果是Prototype作用域的Bean,每次注入都会创建一个新的实例。

    6. 可选的AOP代理(可选):如果Bean被配置为使用AOP(面向切面编程),容器可能会为该Bean创建一个代理对象,并将代理对象注入到依赖中,以便在方法调用时应用切面逻辑。

  2. Spring框架实现Singleton模式的核心机制是通过控制Bean的创建和管理来确保在容器中只有一个实例的存在Spring框架使用了一个叫做BeanFactory的容器来管理对象,其中包括了Singleton对象。下面是Spring如何实现Singleton模式的简要说明:

    • 容器的生命周期管理:Spring容器本身也是一个Singleton对象,它负责管理所有的Bean实例。容器的生命周期通常与应用程序的生命周期相匹配。

    • 同步管理:Spring通过使用同步机制来确保在多线程环境下Singleton对象的安全创建和访问。这样可以避免并发问题。

    • 懒加载:虽然Spring默认在容器启动时就创建Singleton对象,但你也可以将Bean的懒加载标志设置为true,以延迟对象的创建直到第一次请求。这样可以节省资源,只有在需要时才会创建Singleton对象。

    • Bean的缓存:Spring使用一个叫做BeanFactory的容器来管理Bean的实例。在BeanFactory内部,Singleton对象会被缓存起来,以确保每次请求同一个Bean时,都会返回相同的实例。

    • Bean的创建和初始化:Spring容器会根据Bean定义创建实例对象。对于Singleton作用域的Bean,容器只会创建一个实例并在容器启动时进行初始化。这个实例会被缓存起来以供后续使用

    • Bean Definition:在Spring配置文件(如XML文件)或者Java配置类中,你需要定义Bean。这个Bean定义包括了Bean的类名、属性、依赖等信息。当Spring容器初始化时,它会解析这些Bean定义。

      【Spring】手动实现Spring底层机制-问题的引出,Java,spring,java,后端

  3. Spring框架底层实现Prototype作用域的Bean时,采用了一种不同的机制,与Singleton不同。在Prototype作用域下,Spring容器不会维护一个单独的缓存,每次请求Prototype类型的Bean都会创建一个新的实例。下面是Spring如何实现Prototype模式的简要说明:

    • Bean Definition:与Singleton作用域一样,你需要在Spring配置文件或Java配置类中定义Bean。Bean定义包括了Bean的类名、属性、依赖等信息。

    • Bean的创建和初始化:当请求一个Prototype作用域的Bean时,Spring容器会根据Bean定义创建一个新的实例对象,并在需要的情况下进行初始化。每次请求都会触发新的对象创建。

    • 不进行缓存:与Singleton不同,Spring容器不会维护Prototype对象的缓存。每次请求Prototype Bean时,都会创建一个全新的实例。

    • 不进行生命周期管理Spring容器不会管理Prototype对象的生命周期。因此,容器不会在Bean的销毁阶段执行任何清理操作。对象的销毁由客户端代码负责。

  4. 底层实现IOC容器的创建和初始化通常包括以下几个步骤

    • 创建容器对象:实例化一个容器对象,可以是自定义的容器类或者使用现有的容器框
    • 扫描组件:容器会扫描指定的包或者目录,查找符合条件的组件(类)。

      【Spring】手动实现Spring底层机制-问题的引出,Java,spring,java,后端

    • 注册组件:将扫描到的组件注册到容器中,可以使用反射机制创建实例
    • 解析依赖:对于需要注入的依赖,容器会解析其依赖关系并在需要时注入对应的实例。
    • 初始化组件:对于注册到容器中的组件,容器会调用其相应的初始化方法,可以是在注解上指定的初始化方法或者实现了特定接口的回调方法。
    • 提供访问接口:容器提供相应的接口,如getBean()方法来获取容器中的组件实例。
  5. Spring框架中的getBean()方法是用来从Spring容器中获取Bean实例的主要方法之一。下面是Spring框架底层如何实现getBean()方法的简要说明:

    • Bean Definition的注册:在Spring容器启动过程中,所有的Bean定义(包括Bean的名称、类名、属性等信息)都会被注册到容器的BeanFactory中。这个注册是在容器初始化阶段进行的,通常是通过XML配置文件或Java配置类来完成的。

    • Bean实例化:当调用getBean()方法时,容器首先会根据传入的Bean名称或类型信息,查找相应的Bean定义。

    • Bean的创建和初始化:如果找到了相应的Bean定义,容器会根据定义中的信息创建Bean的实例。这通常涉及到Java反射机制,它会调用Bean的构造函数来创建一个新的对象。然后,容器会应用依赖注入和初始化方法等来配置和初始化这个Bean实例。

    • Bean的缓存:Spring容器通常会维护一个Bean实例的缓存,以确保同一个Bean不会被多次创建。这样,如果之前已经创建了一个Bean实例,下次调用getBean()方法时,容器会直接返回缓存中的实例,而不会再次创建。

    • 返回Bean实例:最终,getBean()方法会返回创建或从缓存中获取的Bean实例,供调用者使用。

    • AOP代理(可选):如果该Bean被配置为使用AOP(面向切面编程),容器可能会为该Bean创建一个代理对象,以便在方法调用时应用切面逻辑。

  6. BeanPostProcessor是Spring框架提供的一个扩展点它允许开发者在Bean初始化的不同阶段插入自定义的逻辑。Spring底层通过一系列的回调方法来实现BeanPostProcessor接口,以便在Bean的初始化前后执行额外的处理。以下是Spring底层如何实现BeanPostProcessor的简要说明:

    • 接口定义BeanPostProcessor是一个接口,其中定义了两个回调方法:

      • postProcessBeforeInitialization(Object bean, String beanName): 在Bean的初始化前执行。在这个方法中,可以对Bean进行修改或者执行一些额外的初始化逻辑。

      • postProcessAfterInitialization(Object bean, String beanName): 在Bean的初始化后执行。在这个方法中,同样可以对Bean进行修改或者执行其他的操作。

    • 注册BeanPostProcessor开发者可以自定义一个或多个实现了BeanPostProcessor接口的类,然后将它们注册到Spring容器中。这可以通过XML配置文件、Java配置类或者注解方式来完成。一旦注册,这些BeanPostProcessor将会被Spring容器调用。

    • 回调方法执行:当Spring容器创建和初始化Bean时,它会在适当的时机调用已注册的BeanPostProcessor的回调方法。具体的调用时机如下:

      • 在Bean的实例化后,但在初始化方法调用之前,会调用postProcessBeforeInitialization方法。

      • 在Bean的初始化方法调用后,会调用postProcessAfterInitialization方法

    • 自定义逻辑:开发者可以在这两个回调方法中编写自己的逻辑,例如,可以在postProcessBeforeInitialization方法中进行属性设置或校验,也可以在postProcessAfterInitialization方法中执行一些清理工作。

      • 在Java中,回调方法(Callback Methods)是一种常见的编程模式,它允许一个对象(通常是一个类)将某个方法的引用传递给另一个对象,以便在特定事件发生时调用该方法。回调方法通常用于事件处理、异步编程和自定义扩展点等情况。

  7. Spring底层实现Bean后置处理器(BeanPostProcessor)机制主要依赖于接口和容器生命周期回调方法。Bean后置处理器允许在容器实例化、配置和初始化Bean之前和之后执行自定义逻辑,例如修改Bean的属性,执行代理等操作。以下是Spring底层如何实现Bean后置处理器机制的简要说明:

    • 接口定义BeanPostProcessor是Spring框架提供的接口,其中包含了两个回调方法:

      • postProcessBeforeInitialization(Object bean, String beanName): 在Bean的初始化之前调用。开发者可以在此方法中修改Bean实例的属性或执行自定义初始化逻辑。

      • postProcessAfterInitialization(Object bean, String beanName): 在Bean的初始化之后调用。开发者可以在此方法中进行清理工作或者对Bean进行后处理。

    • 注册BeanPostProcessor:开发者可以创建自定义的实现了BeanPostProcessor接口的类,并将这些后置处理器注册到Spring容器中。这通常可以通过XML配置文件、Java配置类或注解方式来完成。

    • 容器生命周期回调方法:Spring容器在不同的生命周期阶段会自动调用已注册的Bean后置处理器的回调方法。以下是典型的生命周期回调方法执行顺序:

      • 创建Bean实例。

      • 在调用Bean的构造函数之后,但在初始化方法(如果有的话)之前,调用postProcessBeforeInitialization方法。

      • 在调用Bean的初始化方法之后,调用postProcessAfterInitialization方法。

    • 自定义逻辑:开发者可以在postProcessBeforeInitializationpostProcessAfterInitialization方法中编写自己的逻辑,以根据需要修改、增强或清理Bean。

    • AOP代理(可选):在postProcessBeforeInitialization方法中,开发者可以选择创建AOP代理以包装Bean。这可以用于实现AOP切面。

  8. 原生Spring底层实现AOP(面向切面编程)主要依赖于动态代理和反射机制。Spring使用AOP实现了横切关注点(cross-cutting concerns)的模块化,允许在不改变业务逻辑的情况下,将横切关注点(如日志、事务、安全性检查等)应用于应用程序的各个部分。以下是Spring底层如何实现AOP的简要说明:

    • AOP核心概念

      • 切面(Aspect):切面是包含横切关注点的模块。它定义了何时以及在何地应用横切关注点。

      • 连接点(Join Point):连接点是在应用程序中可能被拦截的点,例如方法调用、异常抛出等。

      • 通知(Advice):通知是在连接点上执行的动作,包括"前置通知"、"后置通知"、"环绕通知"、"抛出异常通知"和"最终通知"。

      • 切点(Pointcut):切点是一组连接点的集合,它定义了哪些连接点应该被拦截。

    • AOP代理生成:Spring底层使用JDK动态代理和CGLIB两种方式生成AOP代理。具体的代理方式取决于目标Bean是否实现了接口。如果目标Bean实现了接口,Spring将使用JDK动态代理,否则将使用CGLIB代理。代理对象负责调用切面的通知方法。

    • 通知执行:当目标方法被调用时,AOP代理会根据切面定义的通知类型,在连接点上执行相应的通知。例如,前置通知会在方法执行前执行,后置通知会在方法执行后执行。

    • 切点匹配:Spring使用切点表达式(Pointcut Expressions)来确定哪些连接点应该被拦截。切点表达式可以根据方法名、包名、类名等条件来匹配连接点。

    • 通知执行顺序:通知可以按照特定的顺序来执行,这个顺序可以在切面配置中定义。通常情况下,通知的执行顺序包括前置通知、环绕通知、后置通知、抛出异常通知和最终通知。

    • XML配置或注解:Spring提供了两种方式配置AOP,一种是通过XML配置文件定义切面、切点和通知,另一种是使用注解来标注切面、切点和通知。


🎈BeanDefinition

在Spring框架中,BeanDefinition是Spring容器中的一个抽象概念,当Spring容器初始化时,它会解析配置文件或者注解,并生成相应的BeanDefinition对象。BeanDefinition是用于描述和定义一个Bean的元数据(数据的数据, 类属性的属性)信息的对象它包含了一个Bean的类名、作用域、属性值、构造函数参数、初始化方法、销毁方法等相关信息。它的主要作用是为容器提供创建和管理Bean实例的必要信息

通过BeanDefinition,Spring容器了解了如何实例化、配置和管理一个Bean对象。它允许我们对Bean进行灵活的配置和定制化可以设置不同的作用域(如单例、原型等),设置属性值,指定构造函数参数等。

BeanDefinition可以通过不同的方式进行定义,包括XML配置文件、注解和Java代码等。无论使用哪种方式,最终都会被解析为BeanDefinition对象,然后由容器根据该对象来创建和管理相应的Bean实例。

Spring的BeanDefinition提供了一个统一的模型来管理和控制Bean的生命周期和行为它使得Spring容器能够根据配置信息动态地创建和管理Bean对象,同时也提供了强大的扩展和定制化能力。

🥝类加载器和类路径classPath

java的类加载器3种

  • Bootstrap类加载器--—----—--—---对应路径jre/lib
  • Ext类加载器---------—----------对应路径jre/lib/ext
  • App类加载器--—-------------—--对应路径classpath

App类加载器常用, classpath 类路径,就是 java.exe 执行时,指定的路径,比如

【Spring】手动实现Spring底层机制-问题的引出,Java,spring,java,后端

"C:\Program Files\Java\jdk1.8.0_181\bin\java.exe" "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2023.1.2\lib\idea_rt.jar=55328:C:\Program Files\JetBrains\IntelliJ IDEA 2023.1.2\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_181\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\rt.jar;D:\NewExecllction\exicesecode\lxb-spring\target\classes;C:\Users\Administrator\.m2\repository\org\springframework\spring-context\5.3.8\spring-context-5.3.8.jar;C:\Users\Administrator\.m2\repository\org\springframework\spring-aop\5.3.8\spring-aop-5.3.8.jar;C:\Users\Administrator\.m2\repository\org\springframework\spring-beans\5.3.8\spring-beans-5.3.8.jar;C:\Users\Administrator\.m2\repository\org\springframework\spring-core\5.3.8\spring-core-5.3.8.jar;C:\Users\Administrator\.m2\repository\org\springframework\spring-jcl\5.3.8\spring-jcl-5.3.8.jar;C:\Users\Administrator\.m2\repository\org\springframework\spring-expression\5.3.8\spring-expression-5.3.8.jar;C:\Users\Administrator\.m2\repository\org\springframework\spring-aspects\5.3.8\spring-aspects-5.3.8.jar;C:\Users\Administrator\.m2\repository\org\aspectj\aspectjweaver\1.9.6\aspectjweaver-1.9.6.jar" com.lxb.spring.AppMain

🌰ClassLoader的getResource方法

【Spring】手动实现Spring底层机制-问题的引出,Java,spring,java,后端文章来源地址https://www.toymoban.com/news/detail-707651.html

到了这里,关于【Spring】手动实现Spring底层机制-问题的引出的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 手动开发-实现SpringMVC底层机制--小试牛刀

    在这里说的底层机制的实现主要是指:前端控制器、Controller、Service注入容器、对象自动装配、控制器方法获取参数、视图解析、返回json数据。 前端控制器就是核心控制器。在这里我们可以设计一个Servlet来充当核心控制器: LingDispatcherServlet.java .这个控制器的作用主要是接收

    2024年02月08日
    浏览(48)
  • 手写Spring底层机制

    加入到createBean()中 加入到createBean()中 AOP需要在后置处理器的before方法中实现 1.单例/多例怎么实现的?@scope为什么可以实现? 回答:@scope 的value属性可以设置为singleton /prototype 通过getBean()方法 如果bean中的属性scope为singleton 就从单例池直接拿,如果是prototype 就调用createB

    2024年04月09日
    浏览(38)
  • SpringBoot 底层机制分析【Tomcat 启动+Spring 容器初始化+Tomcat 如何关联Spring 容器】【下】

    😀前言 本篇博文是关于SpringBoot 底层机制分析实现,希望能够帮助你更好的了解SpringBoot 😊 🏠个人主页:晨犀主页 🧑个人简介:大家好,我是晨犀,希望我的文章可以帮助到大家,您的满意是我的动力😉😉 💕欢迎大家:这里是CSDN,我总结知识的地方,欢迎来到我的博客

    2024年02月13日
    浏览(42)
  • 【Spring】Spring的手动实现

    🎄欢迎来到@边境矢梦°的csdn博文🎄 🎄本文主要梳理手动实现Spring底层机制🎄 🌈我是边境矢梦°,一个正在为秋招和算法竞赛做准备的学生🌈 🎆喜欢的朋友可以关注一下 🫰🫰🫰 ,下次更新不迷路🎆 Ps: 月亮越亮说明知识点越重要 (重要性或者难度越大)🌑🌒🌓🌔🌕

    2024年02月07日
    浏览(29)
  • Spring Boot 整合kafka:生产者ack机制和消费者AckMode消费模式、手动提交ACK

    Kafka 生产者的 ACK 机制指的是生产者在发送消息后,对消息副本的确认机制。ACK 机制可以帮助生产者确保消息被成功写入 Kafka 集群中的多个副本,并在需要时获取确认信息。 Kafka 提供了三种 ACK 机制的配置选项,分别是: acks=0:生产者在成功将消息发送到网络缓冲区后即视

    2024年02月04日
    浏览(51)
  • Spring IOC:IOC在Spring底层中如何实现?

    编译软件:IntelliJ IDEA 2019.2.4 x64 操作系统:win10 x64 位 家庭版 Maven版本:apache-maven-3.6.3 Mybatis版本:3.5.6 spring版本:5.3.1 第一章:初识Spring:如何在Maven工程上搭建Spring框架? 第二章:Spring IOC:IOC在Spring底层中如何实现? IOC ,英文全称为Inversion of Control,意为 反转控制 。不

    2024年02月03日
    浏览(35)
  • Spring IOC底层原理实现过程

    Spring IOC(Inversion of Control,控制反转)是 Spring 框架的核心,它的实现原理是基于反射和配置文件实现的。 在 Spring IOC 中,控制权被反转了。传统的应用程序开发中,对象的创建、管理、销毁等全部由应用程序自己来控制,这个过程称为主动管理(Active Management)。而在 Spr

    2024年02月03日
    浏览(40)
  • 【深入浅出Spring原理及实战】「源码调试分析」深入源码探索Spring底层框架的的refresh方法所出现的问题和异常

    阅读Spring官方文档,了解Spring框架的基本概念和使用方法。 下载Spring源码,可以从官网或者GitHub上获取。 阅读Spring源码的入口类,了解Spring框架的启动过程和核心组件的加载顺序。 阅读Spring源码中的注释和文档,了解每个类和方法的作用和用法。 调试Spring源码,可以通过

    2023年04月23日
    浏览(49)
  • Spring之CGLIB和JDK动态代理底层实现

    目录 CGLIB 使用示例-支持创建代理对象,执行代理逻辑 使用示例-多个方法,走不同的代理逻辑 JDK动态代理 使用示例-支持创建代理对象,执行代理逻辑 ProxyFactory 如何自动在CGLIB和JDK动态代理转换 使用示例-使用CGLIB代理方式 使用示例-使用JDK动态代理方式 Spring会自动在JDK动态

    2024年04月25日
    浏览(29)
  • Spring Data Redis切换底层Jedis 和 Lettuce实现

    Spring Data Redis是 Spring Data 系列的一部分,它提供了Spring应用程序对Redis的轻松配置和使用。它不仅提供了对Redis操作的高级抽象,还支持Jedis和Lettuce两种连接方式。 可通过简单的配置就能连接Redis,并且可以切换Jedis和Lettuce两个连接方式。下面先来看看我们该如何使用它。 使

    2024年02月05日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包