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

81 篇文章 0 订阅
36 篇文章 0 订阅
正如你所疑惑的那样,BeanFactory我们已经束之高阁多年啦,我们正在使用威力更加强大的ApplicationContext为我们服务,我们来看下这个新东西,到底如何为我们提供面貌一新的服务;

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



从这里我们可以看出来,我们的ApplicationContext比BeanFactory多实现了这两个接口
  1. public interface MessageSource {
  2.     String getMessage(String code, Object[] args, String defaultMessage, Locale locale);
  3.     
  4.     String getMessage(String code, Object[] args, Locale locale) throws NoSuchMessageException;
  5.     
  6.     String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException;
  7. }
这个接口可以通过参数从特定的多语言文件中获取信息;
其中:
code:消息键;
args[]:参数;
defaultMessage:默认消息;
locale:语言区域;


  1. public interface ApplicationEventPublisher {
  2.     
  3.     
  4.     void publishEvent(ApplicationEvent event);
  5. }

应用信息广播接口,广播信息;
我们看一下具体的实现:
  1.     public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh) throws BeansException {
  2.         this.configLocations = configLocations;
  3.         if (refresh) {
  4.             refresh();
  5.         }
  6.     }
这是ClassPathXmlApplicationContext的初始化函数,在refresh函数里面,调用了refreshBeanFactory();这个函数如下:



  1.     protected final void refreshBeanFactory() throws BeansException {
  2.         // Shut down previous bean factory, if any.
  3.         if (this.beanFactory != null) {
  4.             this.beanFactory.destroySingletons();
  5.             this.beanFactory = null;
  6.         }
  7.         // Initialize fresh bean factory.
  8.         try {
  9.             DefaultListableBeanFactory beanFactory = createBeanFactory();
  10.             loadBeanDefinitions(beanFactory);
  11.             this.beanFactory = beanFactory;
  12.             if (logger.isInfoEnabled()) {
  13.                 logger.info("Bean factory for application context [" + getDisplayName() + "]: " + beanFactory);
  14.             }
  15.         }
  16.         catch (IOException ex) {
  17.             throw new ApplicationContextException(
  18.                     "I/O error parsing XML document for application context [" + getDisplayName() + "]", ex);
  19.         }
  20.     }
将一个BeanFactory设定ApplicationContext的属性,然后,我们可见:
ApplicationContext将原来BeanFactory接口的方法全部委托给BeanFacroty,在这里我们可以把这个看做适配器和装饰模式的一种结合应用;这样,既复用了以前遗留的功能,有将现有系统的功能得到了扩展;


  1. public Object getBean(String name) throws BeansException {
  2.         return getBeanFactory().getBean(name);
  3.     }
  4.     public Object getBean(String name, Class requiredType) throws BeansException {
  5.         return getBeanFactory().getBean(name, requiredType);
  6.     }
  7.     public boolean containsBean(String name) {
  8.         return getBeanFactory().containsBean(name);
  9.     }
  10.     public boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
  11.         return getBeanFactory().isSingleton(name);
  12.     }
  13.     public Class getType(String name) throws NoSuchBeanDefinitionException {
  14.         return getBeanFactory().getType(name);
  15.     }
  16.     public String[] getAliases(String name) throws NoSuchBeanDefinitionException {
  17.         return getBeanFactory().getAliases(name);
  18.     }


  1.     protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws IOException {
  2.         // Create a new XmlBeanDefinitionReader for the given BeanFactory.
  3.         XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
  4.         // Configure the bean definition reader with this context's
  5.         // resource loading environment.
  6.         beanDefinitionReader.setResourceLoader(this);
  7.         if (getClassLoader() != null) {
  8.             beanDefinitionReader.setBeanClassLoader(getClassLoader());
  9.         }
  10.         beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
  11.         // Allow a subclass to provide custom initialization of the reader,
  12.         // then proceed with actually loading the bean definitions.
  13.         initBeanDefinitionReader(beanDefinitionReader);
  14.         loadBeanDefinitions(beanDefinitionReader);
  15.     }
同时,MessageSource功能的实现也是委托给配置的MessageSource文件的;

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

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

  1.             // Invoke factory processors registered as beans in the context.
  2.             invokeBeanFactoryPostProcessors();
  3.             // Register bean processors that intercept bean creation.
  4.             registerBeanPostProcessors();
  5.             // Initialize message source for this context.
  6.             initMessageSource();
  7.             // Initialize event multicaster for this context.
  8.             initApplicationEventMulticaster();
  9.             // Initialize other special beans in specific context subclasses.
  10.             onRefresh();
  11.             // Check for listener beans and register them.
  12.             registerListeners();
  13.             // Instantiate singletons this late to allow them to access the message source.
  14.             beanFactory.preInstantiateSingletons();
  15.             // Last step: publish corresponding event.
  16.             publishEvent(new ContextRefreshedEvent(this));
  17.         }
  18.     }
在这段refresh代码中,我们可以看见:

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


  1. public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {

  2.     public void multicastEvent(ApplicationEvent event) {
  3.         for (Iterator it = getApplicationListeners().iterator(); it.hasNext();) {
  4.             ApplicationListener listener = (ApplicationListener) it.next();
  5.             listener.onApplicationEvent(event);
  6.         }
  7.     }

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

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

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


如在refresh最后,我们调用了:
 publishEvent( new  ContextRefreshedEvent( this ));
通知系统中的监听者对象;


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值