3.8基本的IoC内部构造

IoC容器本质上其实是一个Map<beanName, bean>

BeanDefinition:bean的定义信息(包含bean的class类型、构造参数、属性值等信息),我们需要用到BeanDefinition来进行bean的实例化

image-20240308171123736

DefaultListableBeanFactory:常用的一个BeanFactory,本质是一个BeanDefinition的一个注册中心,有一个Map<beanName, beanDefinition>

DefaultSingletonBeanRegistry:单例bean对象的一个缓存池,有三个map,我们一般称为三级缓存

AbstractAutowireCapableBeanFactory:执行bean的生命周期(实例化、初始化等)

1
2
3
4
5
6
7
8
//一级缓存
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

// 二级缓存
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

// 三级缓存
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

策略模式:

实例化用到了策略模式,抽象策略类InstantiationStrategy,子类实现比如无参构造实例化bean、Cglib代理实例化bean

image-20240308172335401

3.9属性注入

PropertyValues:k-v结构,存储bean的字段以及对应的值

BeanReference:表示bean某个字段的值是一个引用类型(xml文件的ref或者@Autowire、在属性赋值的时候会特殊判断先加载这个引用的bean)

3.10读取xml文件

ResourceLoader:把资源(一般是文件,如bean的xml文件)加载到容器中

Resource:资源,我们通过资源获取其InputStream,再把InputStream转成Document操作dom树读取xml标签,共有三种资源:

  • ClassPathResource:类路径(clasthpath)下的文件
  • FileSystemResource:某个路径下的文件
  • UrlResource:某个网址的资源

image-20240310161725365

3.11PostProcessor拓展

BeanFactoryPostProcessor:实例化前修改BeanDefinition

BeanPostProcessor:初始化前后修改Bean

3.14ApplicationContext和初始化、销毁方法

ApplicationContext:也是一个IoC容器,有着比BeanFactory更加丰富的功能(自动识别BeanFactoryPostProcessor、BeanPostProcessor,自动装配xml文件里面的bean、监听器、国际化等),适合我们开发者使用,有两个重要的实现类,以及一个重要方法refresh():

  • ClassPathXmlApplicationContext:从xml加载bean
  • AnnotationConfigApplicationContext:从注解中加载bean

初始化、销毁方法:

  • 在xml文件中制定init-method和destroy-method
  • 继承自InitializingBean和DisposableBean
  • 在方法上加注解PostConstruct和PreDestroy(未做)

初始化方法在初始化过程的invokeInitMethods()执行,并且初始化方法还会注册销毁方法、注册一个钩子函数registerShutdownHook()在虚拟机进程关闭之前执行销毁方法

3.15Aware接口

Aware接口:常用的有 ApplicationContextAware 、BeanFactoryAware

image-20240315153626768

prototype:不是单例的bean,主要就是在doCreateBean()的时候没有加入到一级缓存。

FactoryBean:较为复杂的bean,在createBean()结束之后,可以更改返回自定义的factoryBean。

监听器:在事件发布者ApplicationEventMulticaster注册所有的监听器ApplicationListener,当发布事件的时候publishEvent,会循环遍历所有的监听器,取得监听器的泛型的类和事件类对比,监听器处理感兴趣的事件。

3.17切点表达式、JDK动态代理和Cglib动态代理

切点表达式:类匹配或者是类匹配同时方法匹配

JDK动态代理:基于接口,通过Proxy生成代理类,在MethodInterceptor执行invoke(),实现增强

Cglib动态代理:不基于接口,基于字节码,通过Enhancer生成代理类,在MethodInterceptor执行invoke(),实现增强

method和methodProxy的区别是methodProxy不会使用反射,直接生成了字节码

3.18动态代理融入bean生命周期

doCreateBean()之前先判断是否需要代理对象,一般不在这里去做

3.20替换配置文件的${}

PropertyPlaceholderConfigurer:一个BeanFactoryPostProcessor,在bean实例化之前修改BeanDefinition,通过加载properties文件的k-v值,来替代有${}的BeanDefinition里的某一个PropertyValue的value值。

ClassPathBeanDefinitionScanner:完成componentScan包扫描,扫描包里面的用了@Component注解的bean,并把他们加入到注册表DefaultListableFactory的BeanDefinitionMap

3.21@Value和@Autowired

在bean实例化之后,初始化之前,调用BeanPostProcessor对bean进行修改,通过反射获取字段上的注解,@Value就获取配置文件的值,@Autowired就通过beanType来getBean()。

AOP移动到初始化之后的BeanPostProcessor处理

类型转换:

三种类型转换器接口:Converter、ConverterFactory、GenericConverter。可以自定义转换器实现以上接口实现自定义的转换

  • Converter<S,T>接口适合一对一的类型转换
  • ConverterFactory<S, R>接口则适合一对多的类型转换
    • GenericConverter接口适合所有类型转换

ConversionService是类型转换体系的核心接口,将以上三种类型转换器整合到一起。GenericConverterService有点类似于DefaultListableBeanFactory也是个注册表,只不过ConversionService保存的是转换器

3.22循环依赖

二级缓存解决没有代理bean的循环依赖:把实例化后的bean加入二级缓存earlySingletonObjects,这样就可以在属性注入之前拿到不完整的bean,避免再次属性注入,从而避免了循环依赖。

三级缓存解决有代理bean的循环依赖:把生成代理bean的时间提前到实例化之后生成代理bean,多加了一级缓存,可以存放代理bean。

总结

IoC总结

什么是IoC(Inversion of Control),也就是控制反转,把bean的控制权交给了BeanFactory管理,而不是由程序员管理,程序员想使用某个bean,从BeanFactory调用getBean()获取就可以。

和IoC经常有个词会放在一起,DI(Dependency Injection),也就是依赖注入,也可以理解为bean的属性注入,发生在bean的生命周期中的实例化之后、初始化之前。

对于IoC来说有几个比较重要的类或者接口:

BeanDefinition:bean定义信息(包括类信息beanClass、属性信息propertyValues、作用域scope、等等),我们需要根据BeanDefinition来完成bean的创建。// TODO:BeanDefinition在真正的Spring中还有许多子类等待探究,这里只是简单的使用了BeanDefinition

Resource:资源总接口,包括ClassPathResource、URLResource、FileResource

BeanDefinitionReader:读取BeanDefinition的总接口,需要ResourceLoader以及BeanDefinitionRegistry两个属性,通过ResourceLoader读取xml文件(操作Document接口、DOM文件树),把BeanDefinition保存到BeanDefinitionRegistry

接下来介绍一些常见的BeanFactory,// TODO:以下的图并不完整,和真正的Spring还有较大的差别

DefaultListableBeanFactory⭐:底层Spring项目启动的时候默认的BeanFactory,继承了一些重要的类或者实现了一些重要的接口,如AbstractAutowireCapableBeanFactory,用以自动装配完成bean的生命周期、或者是BeanDefinitionRegistry,用以保存BeanDefinition、或者是DefaultSingletonBeanRegistry,用以保存单例bean或是解决循环依赖问题、等等

ClassPathXmlApplicationContext或者是AnnotationConfigApplicationContext:拥有BeanFactory基本的功能,并且还有一些拓展功能,如继承了DefaultResourceLoader用来读取BeanDefinition、实现了ApplicationEventPublisher,用以设置监听器监听事件、以及一些国际化的操作(未实现),最重要的是ApplicationContext实现了自动装配功能,不论是使用xml或者是注解,在refresh()方法中完成了创建BeanFactory、使用BeanFactoryPostProcessor、注册BeanPostProcessor、设置监听器、提前实例化不是懒加载的bean(bean的生命周期)等等

image-20240322090615961 image-20240322094026291

接下来具体来说说bean的生命周期,也就是IoC是如何管理bean的,包括实例化、属性注入、初始化、使用、销毁。

bean的生命周期主要发生在AbstractAutowireCapableBeanFactory类的doCreateBean()方法,Spring的命名特点在于真正做事情函数都会加上do前缀,接下来我们就来看看这个doCreateBean()发生了什么:

  1. 实例化:根据策略选择实现方式,默认是无参构造实现、也可以使用CGLIB动态生成
  2. BeanPostProcessor修改bean属性值:里面是@Value以及@Autowired的解析实现,其实也就是通过反射看看每个字段上面有没有相关注解,如果有的话,@Value就是加载配置文件的k-v然后配合去除${}完成属性注入,@Autowired就是通过getBean()来获取对应的引用属性
  3. 设置属性:从BeanDefinition获取bean信息,通过反射填充字段值,如果是BeanReference说明是引用类型,需要先执行引用字段的生命周期
  4. BeanPostProcessor前置处理:如一些Aware接口的回调函数的实现
  5. 初始化:先执行InitializingBean接口方法,反射执行自己的init-method方法
  6. BeanPostProcessor后置处理:实现AOP织入,返回代理对象
  7. 注册销毁方法
  8. 把创建好的bean加入一级缓存

AOP总结

什么是AOP(Aspect Oriented Programming),也就是面向切面编程,把相同的代码抽出来,利用动态代理对已有方法进行增强。

对于AOP有几个重要的类或接口:

Advisor:切面,结合了 切点 和 通知,常用的实现类AspectJExpressionPointcutAdvisor

Pointcut:切点抽象接口,包括 Expression(切点表达式)、 ClassFilter(类匹配器)和 MethodMatcher(方法匹配器)

Advice:增强器(也叫做通知),执行增强方法,常用实现类是各种MethodInterceptor

AdvisedSupport:存放拦截器、源对象、代理方式等信息

MethodInvocation:执行原方法,以及反射调用拦截器增强方法,多次调用 MethodInvocation对象.proceed(),完成链式调用

事务

设计模式

单例模式

原型模式

策略模式

工厂模式

适配器模式

代理模式