Spring框架核心原理

15 阅读5分钟

IOC反转控制:IOC本质是一种思想,是根据依赖倒置原则(DIP)来实现的一种规则,其核心是通过对象的创建和依赖关系,将控制权从应用程序代码转移到容器,实现模块间的解耦。

依赖注入是IOC的核心实现手段

Spring框架的核心功能包括控制反转(IoC)、依赖注入(DI)和切面编程(AOP)

IOC

控制反转是将对象的创建和管理交给容器来实现,从而降低了代码的耦合度。在使用Spring IoC容器时,我们只需要提供Bean的定义信息,而不需要关心Bean的创建和管理过程。Spring框架通过BeanFactory和ApplicationContext这两个核心接口来实现IoC容器。

Spring框架通过BeanDefinition接口来封装Bean的定义信息,它包括Bean的类名、构造函数参数、属性值和其他元数据等信息。在IoC容器启动时,解析配置文件或注解,并对BeanDefinition进行解析和注册,创建BeanDefinition对象并添加到BeanFactory中。当程序员需要使用某个Bean时,IoC容器会根据BeanDefinition创建相应的Bean对象并返回。

Spring框架中,BeanFactory接口和它的实现类 DefaultListableBeanFactory 是IoC容器的核心组件。DefaultListableBeanFactory中维护了一个 ConcurrentHashMap<String, BeanDefinition> 类型的 beanDefinitionMap,用于保存Bean的定义信息。当程序员需要获取某个Bean时,通过调用DefaultListableBeanFactory的getBean方法,根据Bean的名称从beanDefinitionMap中获取相应的BeanDefinition,并调用createBean方法创建相应的Bean对象

DI

依赖注入(DI)是指在Bean创建时,自动将Bean所需的依赖关系注入到Bean中,从而降低了Bean之间的耦合度。Spring框架通过DI实现了Bean之间的解耦。

在实现DI时,Spring框架通过反射机制来实现属性的注入。在创建Bean对象时,IoC容器通过BeanDefinition获取Bean的构造函数或工厂方法,并通过反射机制创建Bean的实例。然后,IoC容器会递归遍历Bean的所有属性,并在容器中查找相应的依赖关系,最后通过反射机制将依赖关系设置到Bean的属性中。

在Spring框架中,Bean的依赖关系通过@Autowired、@Qualifier和@Resource等注解实现,其中@Autowired是最为常用的注解。在实现@Autowired时,Spring框架通过 AutowiredAnnotationBeanPostProcessor 类实现了对@Autowired注解的解析和处理,并通过反射机制完成属性的注入。

AOP

切面编程(AOP)是指通过在运行时自动将特定代码段插入到系统运行流程中,从而实现横向功能的抽象和复用。Spring框架通过AOP模块来实现系统逻辑的分离和管理。

Spring框架通过动态代理字节码增强两种方式来实现AOP。在动态代理方式中,Spring框架通过JDK动态代理或CGLIB动态代理生成代理对象,并通过代理对象在执行目标方法前后切入横切关注点。在字节码增强方式中,Spring框架通过修改字节码文件,在编译时将横切代码嵌入到目标类中

在Spring框架中,AOP的实现主要依赖于 AopProxyFactory、ProxyFactoryBean 和 AbstractAutoProxyCreator 等核心类。当程序员使用@Aspect注解标记某个类时,Spring框架会根据切面类生成相应的代理对象,并将横切代码插入到代理对象的相关方法中。

Spring Bean 生命周期

Spring 中 Bean 的创建是在 createBean 方法中完成的。具体位置在 AbstractAutowireCapableBeanFactory#doCreateBean,Spring Bean 的生命周期就是 doCreateBean 方法的执行逻辑。

  • Bean 的实例化
    • 通过反射创建出来 Bean 实例的过程
  • Bean 属性填充
  • Bean 初始化
    • 调用一些回调函数进行 Bean 的一些预处理如下:
    • 如果当前 Bean 实现了 Aware 接口,那么 Aware 接口相关的方法就在 invokeAwareMethods 方法中被触发
    • applyBeanPostProcessorsBeforeInitialization 中执行 BeanPostProcessor#postProcessBeforeInitialization 方法
    • invokeInitMethods:如果 Bean 实现了 InitializingBean 接口,那么该接口中的 afterPropertiesSet 方法就在这里被触发;另一方面通过配置文件 Bean 的初始化方法(XML 文件中的 init-method 属性),那么也会在这里被触发
    • applyBeanPostProcessorsAfterInitialization 是执行 BeanPostProcessor#postProcessAfterInitialization 方法
    • 初始化完成之后,还有一个关于循环依赖的处理和判断
  • Bean 销毁方法注册
    • 使用 @PreDestroy 注解
    • XML 文件进行配置 destroy-method="",通过该属性指定 Bean 销毁时候需要执行的方法
    • 通过实现 DisposableBean 接口,并重写该接口中的 destroy 方法

Spring Bean 的生命周期涵盖了从 Bean 的创建到销毁的整个过程,主要包括以下几个阶段:

1. 实例化(Instantiation) :Spring 容器创建 Bean 的实例对象。

2. 属性赋值(Populate properties) :将配置文件中定义的属性值注入到 Bean 实例中。

3. 初始化前(Before initialization) :在 Bean 属性赋值完成后,初始化方法调用之前执行的操作。

4. 初始化(Initialization) :调用 Bean 的初始化方法,用于执行一些必要的初始化逻辑,比如连接数据库、加载资源等。

5. 初始化后(After initialization) :在初始化方法调用之后执行的操作。

6. 使用(In use) :Bean 已经准备好,可以被应用程序的其他部分使用。

7. 销毁前(Before destruction) :在 Bean 即将被销毁之前执行的操作。

9. 销毁(Destruction) :调用 Bean 的销毁方法,用于释放资源,比如关闭数据库连接、停止线程等。