程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> ApplicationContext 簡解,applicationcontext

ApplicationContext 簡解,applicationcontext

編輯:JAVA綜合教程

ApplicationContext 簡解,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);
      }
  }
}

... ...

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved