你的位置:首页 > Java教程

[Java教程]ApplicationContext 简解


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

一般不直接实现ApplicationContext(过多接口),可以继承ClassPath 
加载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 ClassPath);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);   } }}

... ...