您的位置:首页 > 移动开发

Spring源代码分析(8)---ClassPathXmlApplicationContext(工厂换新颜)

2008-09-23 20:23 375 查看
正如你所疑惑的那样,BeanFactory我们已经束之高阁多年啦,我们正在使用威力更加强大的ApplicationContext为我们服务,我们来看下这个新东西,到底如何为我们提供面貌一新的服务;

要了解ApplicationContext比BeanFactory功能强大在哪里,我们就必须来分析ApplicationContext接口的实现,因为功能及方法是通过interface来设定的,我们来看一下ApplicationContext的接口类图;



从这里我们可以看出来,我们的ApplicationContext比BeanFactory多实现了这两个接口
public interface MessageSource {

    String getMessage(String code, Object[] args, String defaultMessage, Locale locale);

    
    String getMessage(String code, Object[] args, Locale locale) throws NoSuchMessageException;

    
    String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException;

}
这个接口可以通过参数从特定的多语言文件中获取信息;
其中:
code:消息键;
args[]:参数;
defaultMessage:默认消息;
locale:语言区域;

public interface ApplicationEventPublisher {
    
    
    void publishEvent(ApplicationEvent event);

}

应用信息广播接口,广播信息;
我们看一下具体的实现:
    public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh) throws BeansException {
        this.configLocations = configLocations;
        if (refresh) {
            refresh();
        }
    }

这是ClassPathXmlApplicationContext的初始化函数,在refresh函数里面,调用了refreshBeanFactory();这个函数如下:

    protected final void refreshBeanFactory() throws BeansException {
        // Shut down previous bean factory, if any.
        if (this.beanFactory != null) {
            this.beanFactory.destroySingletons();
            this.beanFactory = null;
        }

        // Initialize fresh bean factory.
        try {
            DefaultListableBeanFactory beanFactory = createBeanFactory();
            loadBeanDefinitions(beanFactory);
            this.beanFactory = beanFactory;
            if (logger.isInfoEnabled()) {
                logger.info("Bean factory for application context [" + getDisplayName() + "]: " + beanFactory);
            }
        }
        catch (IOException ex) {
            throw new ApplicationContextException(
                    "I/O error parsing XML document for application context [" + getDisplayName() + "]", ex);
        }
    }
将一个BeanFactory设定ApplicationContext的属性,然后,我们可见:
ApplicationContext将原来BeanFactory接口的方法全部委托给BeanFacroty,在这里我们可以把这个看做适配器和装饰模式的一种结合应用;这样,既复用了以前遗留的功能,有将现有系统的功能得到了扩展;



public Object getBean(String name) throws BeansException {
        return getBeanFactory().getBean(name);
    }

    public Object getBean(String name, Class requiredType) throws BeansException {
        return getBeanFactory().getBean(name, requiredType);
    }

    public boolean containsBean(String name) {
        return getBeanFactory().containsBean(name);
    }

    public boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
        return getBeanFactory().isSingleton(name);
    }

    public Class getType(String name) throws NoSuchBeanDefinitionException {
        return getBeanFactory().getType(name);
    }

    public String[] getAliases(String name) throws NoSuchBeanDefinitionException {
        return getBeanFactory().getAliases(name);
    }

    protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws 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.setResourceLoader(this);
        if (getClassLoader() != null) {
            beanDefinitionReader.setBeanClassLoader(getClassLoader());
        }
        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);
    }
同时,MessageSource功能的实现也是委托给配置的MessageSource文件的;

    public String getMessage(String code, Object args[], String defaultMessage, Locale locale) {
        return getMessageSource().getMessage(code, args, defaultMessage, locale);
    }

    public String getMessage(String code, Object args[], Locale locale) throws NoSuchMessageException {
        return getMessageSource().getMessage(code, args, locale);
    }

    public String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException {
        return getMessageSource().getMessage(resolvable, locale);
    }
这是策略模式的应用;通过MessageSource之间的组合关系,实现了算法之间的更换,可以在配置文件中更换MessageSource的实现,从而利用不同的NessageSource之间的功能切换;

现在,我们再来看看事件发布的实现代码:

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

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

            // 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 singletons this late to allow them to access the message source.
            beanFactory.preInstantiateSingletons();

            // Last step: publish corresponding event.
            publishEvent(new ContextRefreshedEvent(this));
        }
    }
在这段refresh代码中,我们可以看见:

initApplicationEventMulticaster();private void initApplicationEventMulticaster() throws BeansException {
        if (containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
            this.applicationEventMulticaster = (ApplicationEventMulticaster)
                    getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
            if (logger.isDebugEnabled()) {
                logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
            }
        }
        else {
            this.applicationEventMulticaster = new SimpleApplicationEventMulticaster();
            if (logger.isDebugEnabled()) {
                logger.debug("Unable to locate ApplicationEventMulticaster with name '" +
                        APPLICATION_EVENT_MULTICASTER_BEAN_NAME +
                        "': using default [" + this.applicationEventMulticaster + "]");
            }
        }
    }
在ApplicationContext中存在ApplicationEventMulticaster,这其实是一个典型的观察者模式的运用,对于事件的广播我们都很容易的联想到了观察着,对!ApplicationEventMulticaster这里就是一个主题,在这段代码中,我们可见,我们可以在配置文件中重写这个ApplicationEventMulticaster类,如果我们没有配置这个类的话,那么就会默认实现一个:

public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {

    public void multicastEvent(ApplicationEvent event) {
        for (Iterator it = getApplicationListeners().iterator(); it.hasNext();) {
            ApplicationListener listener = (ApplicationListener) it.next();
            listener.onApplicationEvent(event);
        }
    }

}
这是一个notifyAll的方法,调用所有监听者的onApplicationEvent()方法;

我们来看看这个multicastEvent方法是在什么时候调用的:

    public void publishEvent(ApplicationEvent event) {
        Assert.notNull(event, "Event must not be null");
        if (logger.isDebugEnabled()) {
            logger.debug("Publishing event in context [" + getDisplayName() + "]: " + event);
        }
        getApplicationEventMulticaster().multicastEvent(event);
        if (this.parent != null) {
            this.parent.publishEvent(event);
        }
    }
可见,我们的真正的主题类是ApplicationContext类,只是他把管理监听者队列和消息广播的功能委托给了SimpleApplicationEventMulticaster,然后再在ApplicationContext里面实现setChange()方法,这是对观察着模式的灵活运用,他很好的符合了单一职责原则,方便了SimpleApplicationEventMulticaster的复用,很好,很强大!

如在refresh最后,我们调用了:
 publishEvent(new ContextRefreshedEvent(this));
通知系统中的监听者对象;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐