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 的销毁方法,用于释放资源,比如关闭数据库连接、停止线程等。