Spring源码---ApplicationContext的抽象实现

导语


接着上一篇,继续看看spring源码,再菜也要坚持看完!

ConfigurationApplicationContext


CAC接口中的属性和方法:

Selection_005


从上图可以看出,属性和方法基本都是对上下文的配置和系统自带bean 的名字,值得注意的是getBeanFactroy()方法与AC接口的方法同名,同参,返回值类型不同但具有继承关系。还有就是refresh()方法,看了看方法上的注释,大致是想我们使用这个方法通过配置文件来加载或来刷新 persistent representation (大概就是配置的bean吧)。

AbstractApplicationContext


AAC是第一个实现spring上下文接口的抽象类,由于接口中累积了大量的方法,本着单一职责的设计思路,把功能细化,然后通过代理模式分配出去,而自身主要是对CAC和AC本身的方法进行实现。我们暂且忽略被代理出去的方法,因为在本类中也无法看出其具体实现,先看看类中的属性:

Selection_006


可以看出现在spring的上下文已经具备一些实质性的东西了,也就是上面的这些属性,实现的接口也基本基于这些属性的操作方法。由于类中方法数太多,绝大部分分都是通过代理或组合模式来实现的,就不进行截图也暂且丢一边,主要看refresh()方法的实现。
            // 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);
                // 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();

上面是refresh()方法的主要代码,里面调用的方法名称跟其目的是一致的,perpareRefresh()是设置active,closed,startTime属性和初始化earlyApplicationEventj集合用于准备工作。由于BeanFactory使用是抽象代理,并没有明确到具体实例,obtainFreshBeanFactroy()则是告诉子类,要开始refresh了你得准备一下并把BeanFactory返回给我。从子类中得到BeanFactory后,perpareBeanFactory()开始对BeanFactory添加一些标准化设置及注册系统bean,截取方法中的注释。

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        // Tell the internal bean factory to use the context's class loader etc.

        // Configure the bean factory with context callbacks.

        // BeanFactory interface not registered as resolvable type in a plain factory.
        // MessageSource registered (and found for autowiring) as a bean.;

        // Register early post-processor for detecting inner beans as ApplicationListeners.

        // Detect a LoadTimeWeaver and prepare for weaving, if found.
        if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
            // Set a temporary ClassLoader for type matching.
        }
        // Register default environment beans.
    }

到这里,BeanFactory的准备工作和初始化设置基本完成了,spring的容器也就已经准备好了,对于容器这个概念,也比较抽象,我也只是简单的将其理解为里面存放了很多类的实例对象,当你需要的时候就只需要去容器中拿,显然这些对象应该是无状态的。容器存在与context中的,context则是借助容器来实现对对象实例的共享管理。
BeanFactory创建好了,我们还需要往里面注册processors,用于对bean进行操作处理,毕竟工厂是工厂,有工人之后工厂才能发挥其能力。同时,消息资源和事件监听和推送也是属于共享且无状态的对象,也可以初始化后放入容器中,这些操作便在registerBeanPostProcessors(),initMessageSource(),initApplicationEventMulticaster()。

/**
     * Modify the application context's internal bean factory after its standard
     * initialization. All bean definitions will have been loaded, but no beans
     * will have been instantiated yet. This allows for registering special
     * BeanPostProcessors etc in certain ApplicationContext implementations.
     * @param beanFactory the bean factory used by the application context
     */
    protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    }

postProcessBeanFactory()方法并没有一行代码,注释中也表明,在BeanFactory标准化后允许子类覆盖这个方法,来使BeanFactory能操作自定义或特殊的Bean。

/**
     * Template method which can be overridden to add context-specific refresh work.
     * Called on initialization of special beans, before instantiation of singletons.
     * <p>This implementation is empty.
     * @throws BeansException in case of errors
     * @see #refresh()
     */
    protected void onRefresh() throws BeansException {
        // For subclasses: do nothing by default.
    }

onfresh()方法也是空,这部分也将陪分配到子类中,具体解释看注释吧。

protected void registerListeners() {
        // Register statically specified listeners first.

        // Do not initialize FactoryBeans here: We need to leave all regular beans
        // uninitialized to let post-processors apply to them!

        // Publish early application events now that we finally have a multicaster...
    }

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
        // Initialize conversion service for this context.

        // Register a default embedded value resolver if no bean post-processor
        // (such as a PropertyPlaceholderConfigurer bean) registered any before:
        // at this point, primarily for resolution in annotation attribute values.

        // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.

        // Stop using the temporary ClassLoader for type matching.

        // Allow for caching all bean definition metadata, not expecting further changes.
    
        // Instantiate all remaining (non-lazy-init) singletons.
    }
protected void finishRefresh() {
        // Clear context-level resource caches (such as ASM metadata from scanning).

        // Initialize lifecycle processor for this context.

        // Propagate refresh to lifecycle processor first.

        // Publish the final event.

        // Participate in LiveBeansView MBean, if active.
    }

终于,在这个时候知道注释有多么的重要,特别是在大型的应用中,功能将被拆到多个类,多个方法中,真的无法凭记忆去感觉。在子类的onRefresh()执行之后,BeaFactory的工作也收尾了。也许还记得earlyApplicationEvent这个属性,因为在创建前没有消息的发布者(muticaster),context创建前的事件都被存到该集合,直到registerListener()后,再将其发布。finishBeanFactoryInitialization()则是开始实例话bean了,finishRefresh()则是清空resource case,classLoader等缓存。最后发布一个ContextRefreshedEvent事件,宣布上下文创建或刷新已经完成了。。(掌声!!)

AbstractRefreshableApplicationContext


ARAC继承自AAC,对一个R,也代表了它多一个Refreshable属性。但是在AAC中也有refresh,只不过AAC中的refresh只是对context的标准化,而ARAC是刷新BeanFactroy。

Selection_007


从上图看,ARAC完成了一个关键的操作,创建了BeanFactory,终于看到了BeanFactory的真身了,还为期定义了两个allow属性:
protected DefaultListableBeanFactory createBeanFactory() {
        return new DefaultListableBeanFactory(getInternalParentBeanFactory());
    }

有了BeanFactory后,ARAC就得完成其父亲AAC的叮嘱,为AAC先刷新好BeanFactory(还记得// Tell the subclass to refresh the internal bean factory. 这个注释吗?)。

@Override
    protected final void refreshBeanFactory() throws BeansException {
        if (hasBeanFactory()) {
            destroyBeans();
            closeBeanFactory();
        }
        try {
            DefaultListableBeanFactory beanFactory = createBeanFactory();
            beanFactory.setSerializationId(getId());
            customizeBeanFactory(beanFactory);
            loadBeanDefinitions(beanFactory);
            synchronized (this.beanFactoryMonitor) {
                this.beanFactory = beanFactory;
            }
        }
        catch (IOException ex) {
            throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
        }
    }

以上便是刷新BeanFactory的操作,里面没有注释是不是说这很j简单?确实,就连核心操作loadBeanDefinition都是抽象方法。好吧,我们也跳过这个类,感谢它带来的BeanFactoy和定义的几个刷新方法,还有两个allowsh属性。

AbstractRefreshableConfigApplicationContext


Selection_008


好吧,现在的context可以有自定义的配置文件了。
但还是注意一下,ARCAC还实现了BeanNameAware,InitializingBean两个接口。
/**
     * Triggers {@link #refresh()} if not refreshed in the concrete context's
     * constructor already.
     */
    @Override
    public void afterPropertiesSet() {
        if (!isActive()) {
            refresh();
        }
    }

上面是InitializingBean中的方法,大致是触发自动刷新,目前还没看见具体触发机制的实现。

AbstractXmlApplicationContext


AXAC是对context的最后一层抽象,实现了其父类最后一个为实现的抽象方法:
@Override
    protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
        // Create a new XmlBeanDefinitionReader for the given BeanFactory.
        XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

        // Configure the bean definition reader with this context's
        // resource loading environment.
        beanDefinitionReader.setEnvironment(this.getEnvironment());
        beanDefinitionReader.setResourceLoader(this);
        beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

        // Allow a subclass to provide custom initialization of the reader,
        // then proceed with actually loading the bean definitions.
        initBeanDefinitionReader(beanDefinitionReader);
        loadBeanDefinitions(beanDefinitionReader);
    }

因为配置文件加载的次数有限,loadBeanFactory()也是直接new 一个对象来完成使命。现在的AXAC中并没有任何抽象方法,按理可以写成一个普通类,依旧定义成抽象类也决定了AXAC无法被实例化,设计的目的为何?

结尾


到此,从定义的接口到全部的实现,context这个巨大的角色框架基本已经清楚了,我们也看到了巨型角色构建的设计艺术。大致上从AAC对职责的划分,分配到各个代理中,再定义了一个总体的refresh对策,把核心的自定义配置加载(obtainFreshBeanFactory()),自定义刷新BeanFactory (onRefresh())功能抽象出去,分别让ARCAC和ARAC实现,最后由AXAC统一大业,不得不佩服AAC抽象类的设计。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值