Xml代码
- <listener>
- <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
- </listener>
- <context-param>
- <param-name>contextConfigLocation</param-name>
- <param-value>classpath*:applicationContext-struts.xml,classpath*:spring/applicationContext.xml</param-value>
- </context-param>
Java代码
- /**
- * Create the ContextLoader to use. Can be overridden in subclasses.
- * @return the new ContextLoader
- */
- protected ContextLoader createContextLoader() {
- return new ContextLoader();
- }
Java代码
- /**
- * Initialize the root web application context.
- */
- public void contextInitialized(ServletContextEvent event) {
- this.contextLoader = createContextLoader();
- this.contextLoader.initWebApplicationContext(event.getServletContext());
- }
Java代码
- /**
- * Initialize Spring's web application context for the given servlet context,
- * according to the "{@link #CONTEXT_CLASS_PARAM contextClass}" and
- * "{@link #CONFIG_LOCATION_PARAM contextConfigLocation}" context-params.
- * @param servletContext current servlet context
- * @return the new WebApplicationContext
- * @throws IllegalStateException if there is already a root application context present
- * @throws BeansException if the context failed to initialize
- * @see #CONTEXT_CLASS_PARAM
- * @see #CONFIG_LOCATION_PARAM
- */
- public WebApplicationContext initWebApplicationContext(ServletContext servletContext)
- throws IllegalStateException, BeansException {
- if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) {
- throw new IllegalStateException(
- "Cannot initialize context because there is already a root application context present - " +
- "check whether you have multiple ContextLoader* definitions in your web.xml!");
- }
- try {
- // Determine parent for root web application context, if any.
- ApplicationContext parent = loadParentContext(servletContext);
- // Store context in local instance variable, to guarantee that
- // it is available on ServletContext shutdown.
- this.context = createWebApplicationContext(servletContext, parent);
- servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
- currentContextPerThread.put(Thread.currentThread().getContextClassLoader(), this.context);
- return this.context;
- } catch (RuntimeException ex) {
- logger.error("Context initialization failed", ex);
- servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, ex);
- throw ex;
- } catch (Error err) {
- logger.error("Context initialization failed", err);
- servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, err);
- throw err;
- }
- }
Java代码
- ApplicationContext parent = loadParentContext(servletContext);
Java代码
- protected ApplicationContext loadParentContext(ServletContext servletContext) throws BeansException {
- ApplicationContext parentContext = null;
- // 从web.xml中读取父工厂的配置文件,默认为:"classpath*:beanRefContext.xml"
- String locatorFactorySelector = servletContext.getInitParameter(LOCATOR_FACTORY_SELECTOR_PARAM);
- // 从web.xml中读取父类工厂的名称
- String parentContextKey = servletContext.getInitParameter(LOCATOR_FACTORY_KEY_PARAM);
- if (parentContextKey != null) {
- // locatorFactorySelector may be null, indicating the default "classpath*:beanRefContext.xml"
- BeanFactoryLocator locator = ContextSingletonBeanFactoryLocator.getInstance(locatorFactorySelector);
- this.parentContextRef = locator.useBeanFactory(parentContextKey);
- parentContext = (ApplicationContext) this.parentContextRef.getFactory();
- }
- return parentContext;
- }
Java代码
- ContextSingletonBeanFactoryLocator.getInstance(locatorFactorySelector);
Java代码
- this.parentContextRef = locator.useBeanFactory(parentContextKey);
Java代码
- public BeanFactoryReference useBeanFactory(String factoryKey) throws BeansException {
- synchronized (this.bfgInstancesByKey) {
- BeanFactoryGroup bfg = (BeanFactoryGroup) this.bfgInstancesByKey.get(this.resourceLocation);
- if (bfg != null) {
- bfg.refCount++;
- } else {
- // Create the BeanFactory but don't initialize it.
- BeanFactory groupContext = createDefinition(this.resourceLocation, factoryKey);
- // Record its existence now, before instantiating any singletons.
- bfg = new BeanFactoryGroup();
- bfg.definition = groupContext;
- bfg.refCount = 1;
- this.bfgInstancesByKey.put(this.resourceLocation, bfg);
- this.bfgInstancesByObj.put(groupContext, bfg);
- // Now initialize the BeanFactory. This may cause a re-entrant invocation
- // of this method, but since we've already added the BeanFactory to our
- // mappings, the next time it will be found and simply have its
- // reference count incremented.
- try {
- initializeDefinition(groupContext);
- } catch (BeansException ex) {
- this.bfgInstancesByKey.remove(this.resourceLocation);
- this.bfgInstancesByObj.remove(groupContext);
- throw new BootstrapException("Unable to initialize group definition. " +
- "Group resource name [" + this.resourceLocation + "], factory key [" + factoryKey + "]", ex);
- }
- }
- try {
- BeanFactory beanFactory = null;
- if (factoryKey != null) {
- beanFactory = (BeanFactory) bfg.definition.getBean(factoryKey, BeanFactory.class);
- } else if (bfg.definition instanceof ListableBeanFactory) {
- beanFactory = (BeanFactory) BeanFactoryUtils.beanOfType((ListableBeanFactory) bfg.definition, BeanFactory.class);
- } else {
- throw new IllegalStateException(
- "Factory key is null, and underlying factory is not a ListableBeanFactory: " + bfg.definition);
- }
- return new CountingBeanFactoryReference(beanFactory, bfg.definition);
- } catch (BeansException ex) {
- throw new BootstrapException("Unable to return specified BeanFactory instance: factory key [" +
- factoryKey + "], from group with resource name [" + this.resourceLocation + "]", ex);
- }
- }
- }
Java代码
- BeanFactoryLocator locator = ContextSingletonBeanFactoryLocator.getInstance(locatorFactorySelector);
Xml代码
- <beans>
- <bean id="factoryBeanId" class="org.springframework.context.support.ClassPathXmlApplicationContext">
- <constructor-arg>
- <list>
- <value>sharebean.xml</value>
- </list>
- </constructor-arg>
- </bean>
- <bean id="factoryBeanId2" class="org.springframework.context.support.ClassPathXmlApplicationContext">
- <constructor-arg>
- <list>
- <value>sharebean2.xml</value>
- </list>
- </constructor-arg>
- </bean>
- </beans>
- <!—========================= web.xml ========================= -->
- <context-param>
- <param-name>locatorFactorySelector</param-name>
- <param-value>beanRefFactory.xml</param-value>
- </context-param>
- <context-param>
- <param-name>parentContextKey</param-name>
- <param-value>factoryBeanId</param-value>
- </context-param>
Java代码
- beanFactory = (BeanFactory) bfg.definition.getBean(factoryKey, BeanFactory.class);
Java代码
- BeanFactoryLocator locator = ContextSingletonBeanFactoryLocator.getInstance(locatorFactorySelector);
Java代码
- this.parentContextRef = locator.useBeanFactory(parentContextKey);
Java代码
- if (parentContextKey != null) {
- // locatorFactorySelector may be null, indicating the default "classpath*:beanRefContext.xml"
- BeanFactoryLocator locator = ContextSingletonBeanFactoryLocator.getInstance(locatorFactorySelector);
- this.parentContextRef = locator.useBeanFactory(parentContextKey);
- parentContext = (ApplicationContext) this.parentContextRef.getFactory();
- }
- BeanFactoryLocator locator = ContextSingletonBeanFactoryLocator.getInstance(locatorFactorySelector);
Java代码
- BeanFactoryLocator bfl = (BeanFactoryLocator) instances.get(resourceLocation);
- if (bfl == null) {
- // 仅仅只是设置了ContextSingletonBeanFactoryLocator里的resourceLocation属性的值,并没有初始化工厂。
- bfl = new ContextSingletonBeanFactoryLocator(resourceLocation);
- instances.put(resourceLocation, bfl);
- }
Java代码
- BeanFactoryLocator bfl = (BeanFactoryLocator) instances.get(resourceLocation);
- if (bfl == null) {
- bfl = new ContextSingletonBeanFactoryLocator(resourceLocation);
- // 下面这句可能换成 initBeanFactory 类似语句,这里只是打个比方
- bfl.useBeanFactory(parentContextKey);
- instances.put(resourceLocation, bfl);
- }
Java代码
- // 返回BeanFactoryLocator方便定位某个配置文件。
- BeanFactoryLocator locator = ContextSingletonBeanFactoryLocator.getInstance(“classpath*: parentBeanFactory.xml”);
- parentContextRef1 = locator.useBeanFactory("parent1Key");
- parentContextRef2 = locator.useBeanFactory("parent2Key");
Java代码
- parentContextRef1 = ContextSingletonBeanFactoryLocator.getInstance("parentBeanFactory.xml", "parent1Key");
- parentContextRef2 = ContextSingletonBeanFactoryLocator.getInstance("parentBeanFactory.xml", "parent2Key");
Java代码
- public interface BeanFactoryLocator {
- BeanFactoryReference useBeanFactory(String factoryKey) throws BeansException;
- }
- this.context = createWebApplicationContext(servletContext, parent);
Java代码
- protected WebApplicationContext createWebApplicationContext(
- ServletContext servletContext, ApplicationContext parent) throws BeansException {
- // 获得需要实例化的CONTEXT类名,确定ContextClass的类型。如果在web.xml中配置了contextClass这个parameter,
- // 使用这个指定的类作为ContextClass,会抛出ClassNotFound的异常。反之,使用默认的XmlWebApplicationContext
- Class contextClass = determineContextClass(servletContext);
- // 所有的WebApplicationContext必须实现ConfigurableWebApplicationContext接口
- if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {
- throw new ApplicationContextException("Custom context class [" + contextClass.getName() +
- "] is not of type [" + ConfigurableWebApplicationContext.class.getName() + "]");
- }
- ConfigurableWebApplicationContext wac =
- (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
- // 设置父环境
- wac.setParent(parent);
- // 设置Servlet上下文环境
- wac.setServletContext(servletContext);
- // 设置Spring配置文件路径
- wac.setConfigLocation(servletContext.getInitParameter(CONFIG_LOCATION_PARAM));
- customizeContext(servletContext, wac);
- wac.refresh();
- return wac;
- }
- protected Class determineContextClass(ServletContext servletContext) throws ApplicationContextException {
- // 获得需要实例化的CONTEXT类名,在web.xml中有设置,如果没有设置,那么为空
- String contextClassName = servletContext.getInitParameter(CONTEXT_CLASS_PARAM);
- if (contextClassName != null) {
- try {
- return ClassUtils.forName(contextClassName);
- } catch (ClassNotFoundException ex) {
- throw new ApplicationContextException("Failed to load custom context class.", ex);
- }
- } else {
- //如果在spring web.xml中没有设置context类位置,那么取得默认context
- //取得defaultStrategies配置文件中的WebApplicationContext属性
- contextClassName = defaultStrategies.getProperty(WebApplicationContext.class.getName());
- try {
- return ClassUtils.forName(contextClassName, ContextLoader.class.getClassLoader());
- } catch (ClassNotFoundException ex) {
- throw new ApplicationContextException("Failed to load default context class.", ex);
- }
- }
- }
- private static final String DEFAULT_STRATEGIES_PATH = "ContextLoader.properties";
- static {
- // Load default strategy implementations from properties file.
- // This is currently strictly internal and not meant to be customized
- // by application developers.
- try {
- ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, ContextLoader.class);
- defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);
- } catch (IOException ex) {
- throw new IllegalStateException("Could not load 'ContextLoader.properties': " + ex.getMessage());
- }
- }
- // 在ContextLoader.properties里定义如下
- org.springframework.web.context.WebApplicationContext=org.springframework.web.context.support.XmlWebApplicationContext
Java代码
- 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) {
- // Destroy already created singletons to avoid dangling resources.
- beanFactory.destroySingletons();
- // Reset 'active' flag.
- cancelRefresh(ex);
- // Propagate exception to caller.
- throw ex;
- }
- }
- }
Java代码
- servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
- currentContextPerThread.put(Thread.currentThread().getContextClassLoader(), this.context);
Java代码
- String ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class.getName() + ".ROOT";