• spring源码深度解析-2功能扩展


    容器功能的扩展
    ApplicationContext用于扩展BeanFactory中现有的功能。究竟多出了哪些功能,进一步探索。写法上:
    BeanFactory bf = new XmlBeanFactory(new ClassPathResource("beanFactoryTest.xml"));

    ApplicationContext bf = new ClassPahtApplicationContext("beanFactoryTest.xml");
    还是以ClassPahtApplicationContext作为切入点:
    public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
    this(new String[] {configLocation}, true, null);
    }

    public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException {
    super(parent);
    setConfigLocations(configLocations);
    if (refresh) {
    refresh();
    }
    }

    ClassPahtApplicationContext可以对数据进行解析并进行加载,而对于解析及功能实现都是在refresh()中实现

    setConfigLocations(String... locations):设置配置路径
    用于解析给定的路径数组,如果数组中包含特殊符号如$(var),那么resolvePath中会搜索匹配的变量并替换

    refresh();扩展功能
    public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
    // Prepare this context for refreshing.
    prepareRefresh();

    // Tell the subclass to refresh the internal bean factory.
    ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

    // Prepare the bean factory for use in this context.
    prepareBeanFactory(beanFactory);

    try {
    // Allows post-processing of the bean factory in context subclasses.
    postProcessBeanFactory(beanFactory);

    // Invoke factory processors registered as beans in the context.
    invokeBeanFactoryPostProcessors(beanFactory);

    // Register bean processors that intercept bean creation.
    registerBeanPostProcessors(beanFactory);

    // Initialize message source for this context.
    initMessageSource();

    // Initialize event multicaster for this context.
    initApplicationEventMulticaster();

    // Initialize other special beans in specific context subclasses.
    onRefresh();

    // Check for listener beans and register them.
    registerListeners();

    // Instantiate all remaining (non-lazy-init) singletons.
    finishBeanFactoryInitialization(beanFactory);

    // Last step: publish corresponding event.
    finishRefresh();
    }
    }
    }
    1_ prepareRefresh()初始化的准备工作,例如对系统属性或者环境变量进行准备及验证。
    2_ obtainFreshBeanFactory 初始化BeanFactory,并进行XML文件读取
    ClassPathXmlApplicationContext包含着BeanFactory所提供的一切特征,在这一步中将会复用BeanFactory中的配置文件读取解析及其它功能,这一步之后,ClassPathXmlApplicationContext实际上就包含了BeanFactory所提供的功能,也就是可以进行Bean的提取等基础操作了
    3_ prepareBeanFactory() 对BeanFactory进行各种功能填充
    @Qualifier与@Autowired正式在这一步骤中提供的支持
    4_ postProcessBeanFactory() 子类覆盖方法做额外处理
    postProcessBeanFactory是一个空函数,需要自己重写子类,覆盖方法来方便在业务上进行扩展
    5_ invokeBeanFactoryPostProcessors(beanFactory) 激活各种BeanFactory处理器
    6_ registerBeanPostProcessors(beanFactory) 注册拦截bean创建的bean处理器,这里只是注册,真正的调用在getBean的时候。
    7_ initMessageSource() 为上下文初始化Message源,即对不同语言的消息体进行国际化处理。
    8_ initApplicationEventMulticaster() 初始化应用消息广播器,并犯法如“applicationEventMuliticaster”bean中。
    9_ onRefresh()留个子类初始化其他的bean
    10_ registerListeners() 在所有注册的bean中查找listener bean,注册到消息广播器中
    11_ finishBeanFactoryInitialization(beanFactory) 初始化剩下的单实例(非惰性的)。
    12_ finishRefresh()完成刷新功能,通知生命周期处理器lifecycleProcessor刷新过程,同时发出ContextRefreshEvent通知别人。

    1__ prepareRefrsh 主要做些准备工作,例如对系统属性和环境变量的初始化及验证
    里边两个主要的方法initPropertySources(),validateRequiredProperties()。
    initPropertySources,用户根据自己的需要重写initPropertySources()方法,并在方法进行个性化的属性处理及设置
    validateRequiredProperties,对属性验证。如:工程需要某个设置(VAR)从系统环境变量中获取,如果用户没配这个变量,那么系统不能工作。这一要求在spring就可以自定义一个类集成ClassPathXmlApplicationContext,在initPropertySources()里用getEnviroment().setRequiredProperties("VAR")设置这个属性,那么在验证的就是验证这个属性,没有就会报错。当然也要在使用的时候替换掉原有的ClassPathXmlApplicationContext:ApplicationContext bf = new MyApplicationPathApplicationContext("test.xml");
    2__ obtainFreshBeanFactory
    加载BeanFactory,经过这个函数后,ApplicationContext就有了BeanFactory的全部功能。这个方法里的步骤:
    1.创建DefaultListableBeanFactory
    前面用的BeanFactory bf = new XmlBeanFactory("text.xml")中的XmlBeanFactory继承自DefaultListenBeanFactory,并提供了XmlBeanDefinitionReader属性,也就是说DefaultListenBeanFactory是容器的基础。必须首先实例化。
    2.是定序列化ID
    3.定制BeanFactory
    customizeBeanFactory(beanFactory)
    4.加载BeanDefinition
    5.使用全局变量记录BeanFactory类实例。因为DefaultListenBeanFactory类型的变量beanFacotory是函数内的局部变量,所有要用全局变量来记录解析结果。
    3_ customizeBeanFactory(beanFactory)
    这里已经开始了对BeanFactory的扩展,在基本容器的基础上,增加了是否允许覆盖是否允许扩展的设置并提供了@Qualifier和@Autowired的支持。允许覆盖允许扩展只是判断了是否为空,为空就进行设置,但是在此之前哪个地方来设置它并没有看见,还是在子类的customizeBeanFactory覆盖方法中进行设置。接下来就是加载BeanDefinition,需要XmlBeanDefinitionReader来读取xml,这里首先初始化它,调用loadBeanDefinitions方法,和前面说的Beanfactory的加载一模一样。
    这里还有很多细节。(书的135页)
    3__ prepareBeanFactory() 功能扩展
    1增加SPEL语言的支持
    2增加属性注册编辑器
    spring在DI的时候类似于Date这种属性无法识别,会报错,可以有两种方法解决
    1:使用自定义属性编辑器
    2:注册spring自带的属性编辑器CustomDateEditor
    3添加ApplicationContextAwareProcessor处理器
    对于beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this))的主要目的就是注册个BeanPostProcessor。真正的逻辑还在ApplicationContextAwareProcessor中。ApplicationContextAwareProcessor实现BeanPostProcessor接口。之前在bean实例化的时候,也就是spring激活bean的init-method的前后,会调用BeanPostProcessor的postProcessBeforeInitialization方法和postProcessAfterInitialization方法,同样对于ApplicationContextAwareProcessor我们也看这两个方法。
    postProcessAfterInitialization方法没有做过多逻辑处理
    postProcessBeforeInitialization方法,其中主要的逻辑是调用了invokeAwareInterfaces,从这个方法代码中能看出主要是实现这些Aware接口在被初始化的后,可以获得一些对应的资源。
    4.设置忽略依赖。将ApplicationContextAwareProcessor注册后,invokeAwareInterfaces方法中间接调用的Aware已经不是普通的bean了,需要在spring做bean的依赖注入的时候忽略他们。
    5.注册依赖。当注册了依赖解析后,例如当注册了对BeanFactory.Class的解析依赖后,当bean的属性注入的时候,一旦检测属性为BeanFactory类型便会将实例beanFactory注入进去。
    4_ postProcessBeanFactory BeanFactory的后处理
    11_ finishBeanFactoryInitialization(beanFactory)
    完成BeanFactory的初始化工作,其中包括ConversionService的设置、配置冻结以及非延迟加载的bean的初始化工作。
    1.ConversionService的设置。之前说过用自定义类型转化器可以从String转Date,spring中还提供了另外一种转换方式:使用Converter。
    2.冻结配置。冻结所有的bean定义说明注册的bean定义将不能被修改或进行任何进一步处理。
    3.初始化非延迟加载。ApplicationContext实现的默认方式就是在启动的时候将所有的单例bean提前实例化,通常只是好事,因为这样在配置的中的错误能马上就发现。这个实例化的过程是在finishBeanFactoryInitialization中完成的。
    12_ finishRefresh
    在spring中还提供了Lifecycle接口,包好start/stop方法,实现此接口后Spring会保证在启动的时候调用其start方法开始生命周期,并在关闭的时候调用stop方法接受生命周期,通常用来配置后台程序,在启动后一直运行(如对MQ进行轮询)。
    1.initLifecycleProcessor:当ApplicationContext启动或停止时,会通过LifecycleProcessor来与所有的bean的周期做状态更新,而在使用前需要初始化
    2.onRefresh:启动所有实现了Lifecycle接口的bean
    3.publishEvent:当完成ApplicationContext初始化的时候,要通过Spring中的时间发布机制来发出ContextRefreshEvent事件,保证对应的监听器可以进一步的逻辑处理。

  • 相关阅读:
    Oracle中使用游标详解
    arc140 vp 记录
    CF1710D Recover theTree
    2022.8 做题记录
    21noip赛前20天 day10 简要题解
    2022.7.22 AGC028F&CF1463F&P7740
    arc141 vp 记录
    2022.7.25 AGC027F&AGC032F&AGC013F
    2022.7.21 AGC046D&P6790&AGC041F
    2022.7.20 AGC052D&P4338&AGC033E
  • 原文地址:https://www.cnblogs.com/badboyf/p/6042485.html
Copyright © 2020-2023  润新知