@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); } } }
... ...