Spring ApplicationContext 简介

ApplicationContext是对BeanFactory的扩展,实现BeanFactory的所有功能,并添加了事件传播,国际化,资源文件处理等。
 
configure locations:(CONFIG_LOCATION_DELIMITERS = ",; \t\n" )分割多个配置文件。
 
refresh()执行所有逻辑。
@Override
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();
      }

      catch (BeansException ex) {
        if (logger.isWarnEnabled()) {
            logger.warn("Exception encountered during context initialization - " +
                  "cancelling refresh attempt: " + ex);
        }

        // Destroy already created singletons to avoid dangling resources.
        destroyBeans();

        // Reset 'active' flag.
        cancelRefresh(ex);

        // Propagate exception to caller.
        throw ex;
      }

      finally {
        // Reset common introspection caches in Spring's core, since we
        // might not ever need metadata for singleton beans anymore...
        resetCommonCaches();
      }
  }
}

prepareRefresh():准备需要刷新的资源。

/**
* Prepare this context for refreshing, setting its startup date and
* active flag as well as performing any initialization of property sources.
*/
protected void prepareRefresh() {
  this.startupDate = System.currentTimeMillis(); //启动日期
  this.closed.set(false); //激活标志
  this.active.set(true); //激活标志

  if (logger.isInfoEnabled()) {
      logger.info("Refreshing " + this);
  }

  // Initialize any placeholder property sources in the context environment
  initPropertySources(); //供扩展使用

  // Validate that all properties marked as required are resolvable
  // see ConfigurablePropertyResolver#setRequiredProperties
  getEnvironment().validateRequiredProperties(); 

  // Allow for the collection of early ApplicationEvents,
  // to be published once the multicaster is available...
  this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
}
 
initPropertySources()扩展使用如下:
class MyACTX extends ClassPathXmlApplicationContext {

    @Override
    protected void initPropertySources() {
        super.initPropertySources();
        //TODO
    }
}
一般不直接实现ApplicationContext(过多接口),可以继承ClassPathXmlApplicationContext类,然后重写相应的方法。做相关操作。
 
加载BeanFactory:ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(),(原有功能==配置读取,解析...)。
 
prepareBeanFactory():
/**
* Configure the factory's standard context characteristics,
* such as the context's ClassLoader and post-processors.
* @param beanFactory the BeanFactory to configure
*/
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
  // Tell the internal bean factory to use the context's class loader etc.
  beanFactory.setBeanClassLoader(getClassLoader());
  //表达式语言处理器,Spring3 SpEL表达式,#{xx.xx}支持。
  beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
  //属性编辑器支持 如处理Date注入
  beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

  // Configure the bean factory with context callbacks. 
  beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
  //忽略自动装配的接口
  beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
  beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
  beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
  beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
  beanFactory.ignoreDependencyInterface(EnvironmentAware.class);

  // BeanFactory interface not registered as resolvable type in a plain factory.
  // MessageSource registered (and found for autowiring) as a bean.
  //设置自动装配规则
  beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
  beanFactory.registerResolvableDependency(ResourceLoader.class, this);
  beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
  beanFactory.registerResolvableDependency(ApplicationContext.class, this);

  // Detect a LoadTimeWeaver and prepare for weaving, if found.
  //AspectJ支持
  if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
      beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
      // Set a temporary ClassLoader for type matching.
      beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
  }

  // Register default environment beans.
  if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
      beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
  }
  if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
      beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
  }
  if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
      beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
  }
}

SpEL:Spring Expression Language,运行时构造复杂表达式,存取对象图属性,对象方法调用等。SpEL为单独模块,只依赖于core模块。

<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
      <property name="driverClassName" value="${dataSource.driverClassName}"/>
      <property name="url" value="${dataSource.url}"/>
      <property name="username" value="${dataSource.username}"/>
      <property name="password" value="${dataSource.password}"/>
      <property name="maxActive" value="${dataSource.maxActive}"/>
      <property name="minIdle" value="${dataSource.minIdle}" />
      <property name="initialSize" value="${dataSource.initialSize}"></property>
      <property name="validationQuery" value="${dataSource.validationQuery}"/>
</bean>
PropertyEditor:自定义属性编辑器。
Spring中Date类型无法注入,需要注册相应的属性编辑器来做处理。Spring处理自定义属性编辑器类
org.springframework.beans.factory.config.CustomEditorConfigurer
/**
* {@link BeanFactoryPostProcessor} implementation that allows for convenient
* registration of custom {@link PropertyEditor property editors}.
* 注册
*
*/
public class CustomEditorConfigurer implements BeanFactoryPostProcessor, Ordered {

  protected final Log logger = LogFactory.getLog(getClass());

  private int order = Ordered.LOWEST_PRECEDENCE;  // default: same as non-Ordered

  private PropertyEditorRegistrar[] propertyEditorRegistrars;

  private Map<Class<?>, Class<? extends PropertyEditor>> customEditors;

  ... ...
通过注册propertyEditorRegistrars或者customEditors。
 
customEditors(推荐):
自定义Date属性编辑器MyDateEditor:

class MyDateEditor extends PropertyEditorSupport {

    private String format = "yyyy-MM-dd";

    public void setFormat(String format){
        this.format = format;
    }

    @Override
    public void setAsText(String text) throws IllegalArgumentException {
        SimpleDateFormat sp = new SimpleDateFormat(format);
        try{
            this.setValue(sp.parse(text));
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }
}

配置:
<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
  <property name="customEditors">
    <map>
      <entry key="java.util.Date">
        <bean class="com.xxx.MyDateEditor">
          <property name="format" value="yyyy-MM-dd HH:mm:ss"/>
        </bean>
      </entry>
    </map>
  </property>
</bean>

propertyEditorRegistrars:

自定义Date EditorRegister:

class MyDateRegister implements PropertyEditorRegistrar{
    private String format = "yyyy-MM-dd";

    public void setFormat(String format){
        this.format = format;
    }

    @Override
    public void registerCustomEditors(PropertyEditorRegistry registry) {
        registry.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat(format), true));
    }
}

配置:
<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
  <property name="propertyEditorRegistrars">
    <list>
      <bean class="com.xxx.MyDateRegister">
        <property name="format" value="yyyy-MM-dd HH:mm:ss"/>
      </bean>
    </list>
  </property>
</bean>
属性编辑器应用于Bean实例化属性填充阶段。
 
invokeBeanFactoryPostProcessors():容器级别的bean后置处理。
 
典型应用:PropertyPlaceholderConfigure。
 
PlaceholderConfigurerSupport extends PropertyResourceConfigurer .. implements BeanFactoryPostProcessor,间接实现BeanFactoryPostProcessor,会在BeanFacty载入bean配置之后进行属性文件的处理 :mergeProperties、convertProperties、processProperties,供后续bean的实例化使用。
 
可以注册自定义的BeanFactoryPostProcessor。
 
initMessageSource():初始化消息资源,国际化应用。
 
两个message资源文件message_en.properties, message_zh_CN.properties。
添加Spring配置:messageSource id固定。
<!-- 国际化资源文件 -->
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
    <property name="basenames">
        <value>lang/message</value>
    </property>
</bean>

读取:

ApplicationContext ctx = new ClassPathXmlApplicationContext("spring/lang-resource.xml");
String msg = ctx.getMessage("xxx", null, Locale.CHINA);
System.out.println(msg);

nitApplicationEventMulticaster():

/**
* Add beans that implement ApplicationListener as listeners.
* Doesn't affect other listeners, which can be added without being beans.
*/
protected void registerListeners() {
  // Register statically specified listeners first.
  for (ApplicationListener<?> listener : getApplicationListeners()) {
      getApplicationEventMulticaster().addApplicationListener(listener);
  }

  // Do not initialize FactoryBeans here: We need to leave all regular beans
  // uninitialized to let post-processors apply to them!
  String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
  for (String listenerBeanName : listenerBeanNames) {
      getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
  }

  // Publish early application events now that we finally have a multicaster...
  Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
  this.earlyApplicationEvents = null;
  if (earlyEventsToProcess != null) {
      for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
        getApplicationEventMulticaster().multicastEvent(earlyEvent);
      }
  }
}

... ...

posted @ 2016-11-11 16:25  WindWant  阅读(1809)  评论(0编辑  收藏  举报
文章精选列表