《Spring源码深度解析》笔记

一、容器基础
1、DefaultListableBeanFactory
DefaultListableBeanFactory是整个bean加载的核心,是spring注册即加载bean的默认实现。继承AbstractAutowireCapableBeanFactory,实现ConfigurableListableBeanFactory, BeanDefinitionRegistry。
AbstractAutowireCapableBeanFactory:(1)Alias、SingleBean的注册及获取和FactoryBean的特殊处理;(2)提供配置Factory的各种方法;(3)提供创建bean、自动注入、初始化及应用bean的后处理器。
ConfigurableListableBeanFactory:(1)提供BeanFactory的配置清单,指定忽略类型及接口等。
BeanDefinitionRegistry:(1)定义对BeanDefinition的各种增删改操作。

2、XmlBeanFactory
XmlBeanFactory继承了DefaultListableBeanFactory,添加了XmlBeanDefinitionReader来对配置进行读取、解析和注册,包括<beans>、<bean>、<import>、<alias>和它们的字标签等。

3、Resource
Resource接口抽象了所有Spring内部使用到的底层资源:File、URL、ClassPath。

 

二、bean标签解析及注册
1、创建BeanDefinition
(1)BeanDefinition是<bean>配置信息在容器的内部表示。

2、解析各种属性

3、解析各种子元素
(1)meta:元数据,以键值对存在BeanDefinition的attribute中。
(2)lookup-method:通常称为获取器注入,是一种特殊的方法注入,配置一个方法声明的实际返回对象。记录在BeanDefinition的methodOverrides中。
(3)replaced-method:方法替换,name属性用来指定要替换的方法名称,replacer属性用来指定用来替换的Bean,这个Bean要求实现MethodReplacer接口。记录在BeanDefinition的methodOverrides中。

4、解析自定义属性和子元素
(1)通过命名空间和NamespaceHandler处理。

5、注册BeanDefinition
(1)methodOverrides属性校验;
(2)处理beanName重复;
(3)加入Map缓存:beanDefinitionMap = new ConcurrentHashMap<>(256);
(4)清除解析之前留下的对应beanName的缓存。

6、注册对应的alias
(1)与beanName相同则删除alias;
(2)alias重复处理;
(3)alias循环检查,因为别名也可以设置别名,所以如果a-b、b-c、c-a,那么别名依赖循环。

alias标签、import标签和beans标签的解析类似。

 

三、自定义标签解析

 

四、bean的加载实例化
1、基本步骤
(1)转换成真实的beanName,包括去除FactoryBean修饰符和处理alias。
(2)尝试从缓存中加载单例。spring在不等bean创建完成(初始化前)就会将创建bean的ObjectFactory提早曝光加入到缓存中,可解决单例模式下循环依赖问题。
(3)检查是否原型模式下依赖循环,是则直接抛异常。
(4)如果当前没有对应的BeanDefinition,那么尝试从parentBeanFactory中获取bean。
(5)将GernericBeanDefinition转换成RootBeanDefinition,并合并父类bean的属性。
(6)处理Bean的depends-on属性,递归实例化依赖的bean,若循环依赖则抛异常。
(7)根据不同的scope进行bean的创建,包括singleton、prototype和其它指定的scope。
(8)检查类型与类型转换。spring提供最简单转换,用户也可以自己扩展转换器。

2、单例的三级缓存
singletonObjects:存放单例对象实例的缓存。
earlySingletonObjects:存在提前曝光的bean,也就是正在创建中的bean。
singletonFactories:创建单例对象的工厂。

3、bean创建
(1)准备
    * 锁定class,根据设置的class属性或者根据className来解析Class。
    * 验证及准备覆盖的方法,即处理BeanDefinition中的methodOverride属性。
    * 新建前置处理器InstantiationAwareBeanPostProcessor,解析是否存在新建前的短路操作,如果该处理器返回的bean不为空就直接返回,不继续下面的新建操作。
(2)新建bean实例
    * 检查RootBeanDefinition中的factory-method属性,若有则通过factory-method来创建实例。
    * 解析构造函数,因为存在不同的构造函数,解析过程比较消耗性能,所以采用了缓存机制,存在RootBeanDefinition的resolvedConstructorOrFactoryMethod属性。
    * 构造函数的实例化,通过不同的实例化策略进行实例化。
(3)记录创建bean的ObjectFactory
    * 解决sington模式下依赖循环问题。
(4)属性依赖注入
    * autowireByName()
    * autowireByType()
    * applyPropertyValues()
(5)初始化bean
    * 激活Aware的特定方法,如BeanFactoryAware、ApplicationContextAware等。
    * BeanPostProcessor的postProcessBeforeInitialization方法实现bean初始化的前处理。
    * 激活自定义的init方法,如实现InitializingBean的afterPropertiesSet方法、配置的init-method方法。
    * BeanPostProcessor的postProcessAfterInitialization方法实现bean初始化的后处理,这里可把AOP动态织入进去,生成bean的代理对象。
(6)注册DisposeableBean

4、FactoryBean
FactoryBean是工厂类接口、是一种特殊的bean,根据该bean的id从BeanFactory中获取的实际上是FactoryBean的getObject()返回的对象,而不是FactoryBean本身,如果要获取FactoryBean对象,需要在id前面加一个&符号来获取。
无论是从缓存中还是通过不同的scope策略加载的bean都只是最原始的bean状态,不一定是我们最终想要的bean,其实就是在得到bean实例后的第一步检测是否是FactoryBean类型的bean,好做相应的处理。

5、问题总结
问题1:AbstractAutowireCapableBeanFactory中,创建单例bean时提前暴露的ObjectFactory内部是调用getEarlyBeanReference()方法,通过该方法可以获得当前正创建的bean,这个bean也可能是不完整的,那为什么不直接暴露一个不完整的bean?getEarlyBeanReference()方法中其它一些判断处理的意义?

 

五、容器的功能扩展
ClassPathXmlApplicationContext的初始化步骤
1、环境准备prepareRefresh()
(1)initPropertySources(),用户可以根据自身需要重写,进行个性化的属性处理及设置。
(2)getEnvironment().validateRequiredProperties(),若设置了某些属性是必要的,这里就会验证。

2、BeanFactory的加载obtainFreshBeanFactory()
(1)创建DefaultListableBeanFactory
(2)指定序列化ID
(3)定制BeanFactory
    * 设置是否允许BeanDefinition同名覆盖。
    * 设置是否允许bean之间存在依赖循环。
    * 提供注解@Qualifier和@Autowired的支持。
(4)加载BeanDefinition
    * 初始化XmlBeanDefinitionReader来读取xml。
    * 使用XmlBeanDefinitionReader读取配置文件,并把读取的BeanDefinitionHolder注册到DefaultListableBeanFactory中。
(5)使用全局变量记录BeanFactory类实例

3、功能扩展prepareBeanFactory(beanFactory)
(1)增加对SPEL语言的支持
(2)增加属性编辑器的支持
    * 自定义属性编辑器,通过继承PropertyEditorSupport并重写setAsText方法实现,再注册到CustomEditorConfigurer.customEditors中。
    * 自定义属性编辑器,通过实现PropertyEditorRegistrar的registerCustomEditors方法,再注册到CustomEditorConfigurer.PropertyEditorRegistrar中。
(3)激活一些Aware的特定方法
(4)设置依赖功能可忽略的接口
(5)注册一些固定依赖的属性
(6)增加AspectJ的支持
(7)将相关环境变量及属性以单例模式注册

4、提供子类覆盖方法postProcessBeanFactory(beanFactory)来注册BeanFactory的后处理器

5、激活BeanFactory的后处理器invokeBeanFactoryPostProcessors(beanFactory)
(1)处理器分为普通BeanFactoryPostProcessor与BeanDefinitionRegistry
    * 都要考虑通过硬编码和通过配置注册的后处理器。
    * 硬编码主要是通过AbstractApplicationContext的addBeanFactoryPostProcessor方法添加后处理器。
(2)典型应用PropertyPlaceholderConfigurer
    * mergeProperties方法得到配置。
    * convertProperties方法将配置转换为合适的类型。
    * processProperties方法将配置内容告知BeanFactory。
(3)自定义实现BeanFactoryPostProcessor接口

6、BeanPostProcessor的注册registerBeanPostProcessors(beanFactory)

7、初始化消息资源即国际化资源initMessageSource()
(1)定义不同的国际化文件properties
(2)配置MessageSource,且Bean的ID必须为messageSource

8、初始化事件广播器initApplicationEventMulticaster()
(1)默认使用SimpleApplicationEventMulticaster广播器

9、提供子类覆盖onRefresh()

10、注册监听器registerListeners()
(1)把监听器注册到使用的广播器中,这里也都考虑了通过硬编码与配置文件添加的监听器
(2)可通过实现ApplicationListener接口自定义监听器

11、初始化非延迟加载单例finishBeanFactoryInitialization(beanFactory)

12、finishRefresh()
(1)初始化LifecycleProcessor并激活其onRefresh方法
(2)发出ContextRefreshedEvent事件

 

六、AOP
1、基本概念
● Aspect表示切面。切入业务流程的一个独立模块。例如,前面案例的VerifyUser类,一个应用程序可以拥有任意数量的切面。
● JoinPoint表示连接点。也就是业务流程在运行过程中需要插入切面的具体位置。例如,前面案例的AopEmailNotice类的setTeacher方法就是一个连接点。
● Advice表示通知。是切面的具体实现方法。可分为前置通知(Before)、后置通知(AfterReturning)、异常通知(AfterThrowing)、最终通知(After)和环绕通知(Around)五种。实现方法具体属于哪类通知,是在配置文件和注解中指定的。例如,VerifyUser类的beforeAdvice方法就是前置通知。
● Pointcut表示切入点。用于定义通知应该切入到哪些连接点上,不同的通知通常需要切入到不同的连接点上。例如,前面案例配置文件的<aop:pointcut>标签。
● Target表示目标对象。被一个或者多个切面所通知的对象。例如,前面案例的AopEmailNotice类。
● Proxy表示代理对象。将通知应用到目标对象之后被动态创建的对象。可以简单地理解为,代理对象为目标对象的业务逻辑功能加上被切入的切面所形成的对象。
● Weaving表示切入,也称为织入。将切面应用到目标对象从而创建一个新的代理对象的过程。这个过程可以发生在编译期、类装载期及运行期。

2、自动代理创建器AnnotationAwareAspectJAutoProxyCreator
(1)使用AspectJAutoProxyBeanDefinitionParser解析<aop:aspectj-autoproxy>标签
    * proxy-target-class属性设置为true,则强制使用CGLIB代理生成目标类扩展的子类,JDK动态代理的对象必须是某个接口的实现。
    * expose-proxy属性设置为true,则可以在代理的目标对象中通过AopContext.currentProxy()方法获取当前代理来调用内部方法,已达到内部方法调用增强。
(2)注册或升级自动代理创建器
    * 根据优先级确定使用哪个自动代理创建器。
    
3、创建AOP代理
(1)获取增强器Advisor
    * 遍历所有beanName找出声明Aspect注解的类。
    * 解析注解类中的增强方法并加入缓存。
(2)寻找匹配的增强器
(3)创建代理
    * 代理中获取目标对象当前方法的拦截器链并封装成ReflectiveMethodInvocation。
    * ReflectiveMethodInvocation中维护拦截器调用计数器,记录当前调用链位置,以便链可以有序地进行下去。
    * 通过ReflectiveMethodInvocation.proceed方法实现拦截器有序递归调用。

4、创建AOP静态代理
(1)java1.5引入java.lang.instrument,可以由此实现一个java agent
(2)编写ClassFileTransformer和agent类,打包agent。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值