0%

Spring源码分析

思路参考:spring源码导读 SegmentFault 思否

核心上下文依赖包

1
2
3
4
5
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.12.RELEASE</version>
</dependency>

Spring内容的实现依赖于底层大量的PostProcess来对Bean的实例进行一定的修饰

IOC容器

Bean的生命周期

创建–>初始化–>销毁

创建

  1. Bean 容器找到配置文件中 Spring Bean 的定义。

  2. Bean 容器利用 Java Reflection API 创建一个 Bean 的实例。

  3. 如果涉及到一些属性值 利用 set()方法设置一些属性值。

  4. 如果 Bean 实现了 BeanNameAware 接口,调用 setBeanName()方法,传入 Bean 的名字。

    如果 Bean 实现了 BeanClassLoaderAware 接口,调用 setBeanClassLoader()方法,传入 ClassLoader对象的实例。

    如果 Bean 实现了 BeanFactoryAware 接口,调用 setBeanFactory()方法,传入 BeanFactory对象的实例。

    与上面的类似,如果实现了其他 *.Aware接口,就调用相应的方法。

  5. 如果有和加载这个 Bean 的 Spring 容器相关的 BeanPostProcessor 对象,执行postProcessBeforeInitialization() 方法

  6. 如果 Bean 实现了InitializingBean接口,执行afterPropertiesSet()方法。

  7. 如果 Bean 在配置文件中的定义包含 init-method 属性,执行指定的方法。

  8. 如果有和加载这个 Bean 的 Spring 容器相关的 BeanPostProcessor 对象,执行postProcessAfterInitialization() 方法

销毁

  1. 当要销毁 Bean 的时候,如果 Bean 实现了 DisposableBean 接口,执行 destroy() 方法。
  2. 当要销毁 Bean 的时候,如果 Bean 在配置文件中的定义包含 destroy-method 属性,执行指定的方法。

获取IOC容器底层组件

比如说容器本身

实现XXXAware接口和对应方法

1
2
3
4
5
6
7
8
9
@Component
public class Cat implements ApplicationContextAware {
private ApplicationContext applicationContext;
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
System.out.println(applicationContext);
System.out.println(applicationContext.getEnvironment().getProperty("os.name"));
}
}

XXXAware接口会由XXXAwareProcessor进行处理,这些Processor都是实现了BeanPostProcessor的后置处理器

如ApplicationContextAwareProcessor通过调用invokeAwareInterfaces方法来匹配Aware的对应类型并传入上下文

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
private void invokeAwareInterfaces(Object bean) {
if (bean instanceof EnvironmentAware) {
((EnvironmentAware)bean).setEnvironment(this.applicationContext.getEnvironment());
}

if (bean instanceof EmbeddedValueResolverAware) {
((EmbeddedValueResolverAware)bean).setEmbeddedValueResolver(this.embeddedValueResolver);
}

if (bean instanceof ResourceLoaderAware) {
((ResourceLoaderAware)bean).setResourceLoader(this.applicationContext);
}

if (bean instanceof ApplicationEventPublisherAware) {
((ApplicationEventPublisherAware)bean).setApplicationEventPublisher(this.applicationContext);
}

if (bean instanceof MessageSourceAware) {
((MessageSourceAware)bean).setMessageSource(this.applicationContext);
}

if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware)bean).setApplicationContext(this.applicationContext);
}

}

IOC容器创建过程

进入refresh()方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public void refresh() throws BeansException, IllegalStateException {
synchronized(this.startupShutdownMonitor) {
this.prepareRefresh();// 1
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();// 2
this.prepareBeanFactory(beanFactory);// 3

try {
this.postProcessBeanFactory(beanFactory);// 4
this.invokeBeanFactoryPostProcessors(beanFactory);// 5
this.registerBeanPostProcessors(beanFactory);// 6
this.initMessageSource();// 7
this.initApplicationEventMulticaster();// 8
this.onRefresh();// 9
this.registerListeners();// 10
this.finishBeanFactoryInitialization(beanFactory);// 11
this.finishRefresh();// 12
} catch (BeansException var9) {
if (this.logger.isWarnEnabled()) {
this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
}

this.destroyBeans();
this.cancelRefresh(var9);
throw var9;
} finally {
this.resetCommonCaches();
}

}
}
  1. prepareRefresh()

    1. 记录启动时间,设置容器的active和close状态。
    2. initPropertySources():提供给子容器类,子容器类可覆盖该方法进行一些自定义的属性设置。
    3. getEnvironment().validateRequiredProperties():检验属性的合法性
    4. this.earlyApplicationEvents = new LinkedHashSet() :保存容器中的一些早期的事件,待事件多播器创建后执行。
  2. obtainFreshBeanFactory()

    将Bean的配置信息添加到注册中心

    1. refreshBeanFactory:如果当前容器已经有了BeanFactory就销毁原来的BeanFactory。然后创建一个DefaultListableBeanFactory();
      • 对BeanFactory并进行配置,主要配置是否允许BeanDefinition覆盖,是否允许Bean间的循环引用。
      • 加载BeanDefinition,解析XML文件和配置文件,将其转换为BeanDefinition,然后保存到DefaultListableBeanFactory的beanDefinitionMap字段中。
    2. getBeanFactory() 简单的返回beanFactory,即DefaultListableBeanFactory。
  3. prepareBeanFactory()

    1. 设置BeanFactory的类加载器、设置支持SPEL表达式的解析器。
    2. 添加ApplicationContextAwareProcessor用于处理XXXAware接口的回调。
    3. 设置忽略一些接口。并注册一些类,这些类可以在bean里直接进行自动装配。
    4. 添加ApplicationListenerDetector用于识别并保存ApplicationListener的子类。
  4. postProcessBeanFactory()

    提供给子容器类,子容器类可以覆盖该方法在BeanFactory准备工作完成后处理一些工作。

  5. invokeBeanFactoryPostProcessors()

    执行BeanFactoryPostProcessors类型的后置处理器的监听方法

    • BeanFactoryPostProcessor是beanFactory后置处理器,在整个BeanFactory标准初始化完成后进行拦截调用,
    • BeanDefinitionRegistryPostProcessor继承了BeanFactoryPostProcessor,在beanFactory解析完所有的BeanDefinition后拦截调用。
    • BeanFactoryPostProcessor来源
      • 通过ApplicationContent的addBeanFactoryPostProcessor()方法手动添加自己的拦截器
      • 系统默认了一些BeanFactoryPostProcessor。例如:ConfigurationClassPostProcessor用来处理@Configuration标注的Spring配置类。
    • 调用顺序
      1. 先调用BeanDefinitionRegistryPostProcessor类型的拦截器,
      2. 然后再依次调用实现了PriorityOrdered,Ordered接口的BeanFactoryPostProcessor
      3. 最后调用普通的BeanFactoryPostProcessor
  6. registerBeanPostProcessors()

    注册Bean的后置处理器

    1. 从beanFactory里获取所有BeanPostProcessor类型的Bean的名称。
    2. 调用beanFactory的getBean方法并传入每一个BeanPostProcesso类型的Bean名称,从容器中获取该Bean的实例。
      1. 第一步向beanFactory注册实现了PriorityOrdered的BeanPostProcessor类型的Bean实例。
      2. 第二步向beanFactory注册实现了Ordered的BeanPostProcessor类型的Bean实例。
      3. 第三步向beanFactory注册普通的BeanPostProcessor类型的Bean实例。
      4. 最后一步向beanFactory重新注册实现了MergedBeanDefinitionPostProcessor的BeanPostProcessor类型的Bean实例
    3. 向beanFactory注册BeanPostProcessor的过程就是简单的将实例保存到beanFactory的beanPostProcessors属性中。
  7. initMessageSource()

    初始化国际化相关功能

    1. 看容器中是否有id为messageSource的,类型是MessageSource的Bean实例。如果有赋值给messageSource,如果没有自己创建一个DelegatingMessageSource。
    2. 把创建好的MessageSource注册在容器中,以后获取国际化配置文件的值的时候,可以自动注入MessageSource。
  8. initApplicationEventMulticaster()

    初始化事件派发器,用于给监听器传递消息

    1. 看容中是否有名称为applicationEventMulticaster的,类型是ApplicationEventMulticaster的Bean实例。如果没有就创建一个SimpleApplicationEventMulticaster。
    2. 把创建好的ApplicationEventMulticaster添加到BeanFactory中。
  9. onRefresh()

    提供给子容器类,供子容器去实例化其他的特殊的Bean

  10. registerListeners()

    处理容器中已有的ApplicationListener

    1. 从容器中获得所有的ApplicationListener
    2. 将每个监听器添加到事件派发器(ApplicationEventMulticaster)中;
    3. 处理之前步骤产生的事件;
  11. finishBeanFactoryInitialization()

    初始化容器中剩余的单实例bean:拿到剩余的所有的BeanDefinition,依次调用getBean方法

  12. finishRefresh()

    1. 初始化和生命周期有关的后置处理器;LifecycleProcessor,如果容器中没有指定处理就创建一个DefaultLifecycleProcessor加入到容器。
    2. 获取容器中所有的LifecycleProcessor回调onRefresh()方法。
    3. 发布容器刷新完成事件ContextRefreshedEvent。

AOP

1
2
3
4
5
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.2.12.RELEASE</version>
</dependency>

在程序运行期间,动态的将某段代码切入到指定位置的编程方式

底层:动态代理

@EnableAspectJAutoProxy的作用

@EnableAspectJAutoProxy

  • @EnableAspectJAutoProxy 通过@Import(AspectJAutoProxyRegistrar.class)给spring容器中导入了一个AnnotationAwareAspectJAutoProxyCreator。
  • AnnotationAwareAspectJAutoProxyCreator实现了InstantiationAwareBeanPostProcessor,InstantiationAwareBeanPostProcessor是一个BeanPostProcessor。它可以拦截spring的Bean初始化(Initialization)前后和实例化(Initialization)前后。

总结

  1. @EnableAspectJAutoProxy

    向容器中注册组件AnnotationAwareAspectJAutoProxyCreator后置处理器

  2. 容器创建流程:

    1. registerBeanPostProcessors()注册后置处理器,创建AnnotationAwareAspectJAutoProxyCreator对象

    2. finishBeanFactoryInitialization()初始化剩下的单实例Bean

      1. 创建业务逻辑组件和切面组件

      2. AnnotationAwareAspectJAutoProxyCreator会拦截组建的创建过程

      3. 组件创建完后,判断组件是否需要增强

        如果是,将切面的通知方法包装秤增强器,给业务逻辑组件创建一个代理对象

  3. 执行目标方法:

    1. 代理对象执行目标方法

    2. CglibAopProxy.intercept()

      1. 得到目标方法的拦截器链(将增强器包装成MethodInterceptor)

      2. 利用拦截器的链式机制,依次进入每个拦截器进行执行

        由于每个拦截器会先放行执行它的下一个拦截器,因此排在最后的前置通知拦截器会最先执行

      3. 执行顺序:

        • 正常执行:前置通知-目标方法->后置通知->返回通知
        • 出现异常:前置通知-目标方法->后置通知->异常通知

声明式事务原理

注解使用方式

  • 配置数据源DataSource

  • 主类上添加@EnableTransactionManagement

  • 需要转为事务操作的方法上添加@Transactional

  • 配置事务管理器来管理事务

    1
    2
    3
    4
    5
    @Bean
    public PlatformTransactionManager transactionManager(){
    //这里传入配置好的数据源
    return new DataSourceTransactionManager(datasource());
    }

运行过程:

  1. @EnableTransactionManagement利用TransactionManagementConfigurationSelector给spring容器中导入两个组件:AutoProxyRegistrar和ProxyTransactionManagementConfiguration
  2. AutoProxyRegistrar给spring容器中注册一个InfrastructureAdvisorAutoProxyCreator,InfrastructureAdvisorAutoProxyCreator实现了InstantiationAwareBeanPostProcessor,InstantiationAwareBeanPostProcessor是一个BeanPostProcessor。它可以拦截spring的Bean初始化(Initialization)前后和实例化(Initialization)前后。利用后置处理器机制在被拦截的bean创建以后包装该bean并返回一个代理对象代理对象执行方法利用拦截器链进行调用(同springAop的原理)
  3. ProxyTransactionManagementConfiguration:是一个spring的配置类,它为spring容器注册了一个BeanFactoryTransactionAttributeSourceAdvisor,是一个事务事务增强器。它有两个重要的字段:AnnotationTransactionAttributeSource和TransactionInterceptor。
    1. AnnotationTransactionAttributeSource:用于解析事务注解的相关信息
    2. TransactionInterceptor:事务拦截器,在事务方法执行时,都会调用TransactionInterceptor的invoke->invokeWithinTransaction方法,这里面通过配置的PlatformTransactionManager控制着事务的提交和回滚。

扩展原理

  1. BeanFactoryPostProcessor:beanFactory后置处理器,的拦截时机:所有Bean的定义信息已经加载到容器,但还没有被实例化。可以对beanFactory进行一些操作。
  2. BeanPostProcessor:bean后置处理器,拦截时机:bean创建对象初始化前后进行拦截工作。可以对每一个Bean进行一些操作。
  3. BeanDefinitionRegistryPostProcessor:是BeanFactoryPostProcessor的子接口,拦截时机:所有Bean的定义信息已经加载到容器,但还没有被实例化,可以对每一个Bean的BeanDefinition进行一些操作。
  4. 监听器原理:EventListenerMethodProcessor是一个SmartInitializingSingleton,当所有的单例bean都初始化完以后, 容器会回调该接口的方法afterSingletonsInstantiated(),该方法里会遍历容器中所有的bean,并判断每一个bean里是否带有@EventListener注解的Method,然后创建ApplicationListenerMethodAdapter存储并包装该Method,最后将ApplicationListenerMethodAdapter添加到spring容器中。
  5. 事件派发器ApplicationEventMulticaster给EventListener传递消息

使用监听器

  1. 监听对象

    • 实现并注册ApplicationListener接口

      1
      2
      3
      4
      5
      6
      @Component
      public class MyListener implements ApplicationListener<ApplicationEvent> {
      public void onApplicationEvent(ApplicationEvent applicationEvent) {
      System.out.println("监听到了事件:" + applicationEvent);
      }
      }
    • 或者直接使用@EventListener()接口来为普通的方法指定监听对象

  2. 可以自己发布事件

    1
    applicationContext.publishEvent(new ApplicationEvent(new String("我发布的事件")){});

bean的循环依赖问题

A 依赖 B B 依赖 A 产生闭环,称为循环依赖

·Spring 默认允许单例对象的属性注入 所产生的循环依赖

单例对象的循环依赖 Spring通过3级缓存来解决

比如一个类A中有一个属性是B类,B类中有一个属性是A类,这时看Spring是怎么解决他们的相互依赖的。Spring注入一个类的大体步骤分为两部分,一是先完成对类的构造工作,二是会对类的属性进行设置和填充。首先Spring构造A类,通过AbstractAutowireCapableBeanFactory的doCreateBean方法中调用addSingletonFactory方法将A类曝光到singletonFactories中。这时完成A的构造后,需要填充B属性,继续第二步,发现B还没有构造,于是开始B流程的构造过程,构造的时候发现需要填充A,从第三层缓存singletonFactories中找到A(此时的A还没有完全构造完成,但是可以拿到A的一个引用),B拿到A的引用后,完成B自己的填充属性工作,完成初始化工作,把自己放到第一层缓存singletonObjects中。这时回到A的这边,在拿到B对象后,完成自己的填充属性工作。

源码 级别 描述
singletonObjects 一级缓存 用于存放完全初始化好的 bean,从该缓存中取出的 bean 可以直接使用
earlySingletonObjects 二级缓存 存放原始的 bean 对象(尚未填充属性),用于解决循环依赖
singletonFactories 三级缓存 存放 bean 工厂对象,用于解决循环依赖

二级缓存就能解决缓存依赖,三级缓存解决的是AOP代理问题