mini-spring学习记录
3.8基本的IoC内部构造
IoC容器本质上其实是一个Map<beanName, bean>
BeanDefinition:bean的定义信息(包含bean的class类型、构造参数、属性值等信息),我们需要用到BeanDefinition来进行bean的实例化
DefaultListableBeanFactory:常用的一个BeanFactory,本质是一个BeanDefinition的一个注册中心,有一个Map<beanName, beanDefinition>
DefaultSingletonBeanRegistry:单例bean对象的一个缓存池,有三个map,我们一般称为三级缓存
AbstractAutowireCapableBeanFactory:执行bean的生命周期(实例化、初始化等)
1 | //一级缓存 |
策略模式:
实例化用到了策略模式,抽象策略类InstantiationStrategy,子类实现比如无参构造实例化bean、Cglib代理实例化bean
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:某个网址的资源
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
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的生命周期)等等
接下来具体来说说bean的生命周期,也就是IoC是如何管理bean的,包括实例化、属性注入、初始化、使用、销毁。
bean的生命周期主要发生在AbstractAutowireCapableBeanFactory类的doCreateBean()方法,Spring的命名特点在于真正做事情函数都会加上do前缀,接下来我们就来看看这个doCreateBean()发生了什么:
- 实例化:根据策略选择实现方式,默认是无参构造实现、也可以使用CGLIB动态生成
- BeanPostProcessor修改bean属性值:里面是@Value以及@Autowired的解析实现,其实也就是通过反射看看每个字段上面有没有相关注解,如果有的话,@Value就是加载配置文件的k-v然后配合去除${}完成属性注入,@Autowired就是通过getBean()来获取对应的引用属性
- 设置属性:从BeanDefinition获取bean信息,通过反射填充字段值,如果是BeanReference说明是引用类型,需要先执行引用字段的生命周期
- BeanPostProcessor前置处理:如一些Aware接口的回调函数的实现
- 初始化:先执行InitializingBean接口方法,反射执行自己的init-method方法
- BeanPostProcessor后置处理:实现AOP织入,返回代理对象
- 注册销毁方法:
- 把创建好的bean加入一级缓存:
AOP总结
什么是AOP(Aspect Oriented Programming),也就是面向切面编程,把相同的代码抽出来,利用动态代理对已有方法进行增强。
对于AOP有几个重要的类或接口:
Advisor:切面,结合了 切点 和 通知,常用的实现类AspectJExpressionPointcutAdvisor
Pointcut:切点抽象接口,包括 Expression(切点表达式)、 ClassFilter(类匹配器)和 MethodMatcher(方法匹配器)
Advice:增强器(也叫做通知),执行增强方法,常用实现类是各种MethodInterceptor
AdvisedSupport:存放拦截器、源对象、代理方式等信息
MethodInvocation:执行原方法,以及反射调用拦截器增强方法,多次调用 MethodInvocation对象.proceed(),完成链式调用
事务
设计模式
单例模式
原型模式
策略模式
工厂模式
适配器模式
代理模式