zoukankan      html  css  js  c++  java
  • Spring源码(一)

    <listener>
      <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    
    
    ContextLoaderListener.java
    public class ContextLoaderListener extends ContextLoader implements ServletContextListener {
        public ContextLoaderListener() {
        }
    
        public ContextLoaderListener(WebApplicationContext context) {
            super(context);
        }
      // 应用启动会触发此方法,ServletContextListener中会进行监听触发
        public void contextInitialized(ServletContextEvent event) {
            this.initWebApplicationContext(event.getServletContext());
        }
    
        public void contextDestroyed(ServletContextEvent event) {
            this.closeWebApplicationContext(event.getServletContext());
            ContextCleanupListener.cleanupAttributes(event.getServletContext());
        }
    }
    ContextLoader.java
    public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
            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!");
            } else {
                Log logger = LogFactory.getLog(ContextLoader.class);
                servletContext.log("Initializing Spring root WebApplicationContext");
                if (logger.isInfoEnabled()) {
                    logger.info("Root WebApplicationContext: initialization started");
                }
    
                long startTime = System.currentTimeMillis();
    
                try {
                    if (this.context == null) {
                        this.context = this.createWebApplicationContext(servletContext);
                    }
    
                    if (this.context instanceof ConfigurableWebApplicationContext) {
                        ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext)this.context;
                        if (!cwac.isActive()) {
                            if (cwac.getParent() == null) {
                                ApplicationContext parent = this.loadParentContext(servletContext);
                                cwac.setParent(parent);
                            }
    
                            this.configureAndRefreshWebApplicationContext(cwac, servletContext);
                        }
                    }
    
                    servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
                    ClassLoader ccl = Thread.currentThread().getContextClassLoader();
                    if (ccl == ContextLoader.class.getClassLoader()) {
                        currentContext = this.context;
                    } else if (ccl != null) {
                        currentContextPerThread.put(ccl, this.context);
                    }
    
                    if (logger.isDebugEnabled()) {
                        logger.debug("Published root WebApplicationContext as ServletContext attribute with name [" + WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE + "]");
                    }
    
                    if (logger.isInfoEnabled()) {
                        long elapsedTime = System.currentTimeMillis() - startTime;
                        logger.info("Root WebApplicationContext: initialization completed in " + elapsedTime + " ms");
                    }
    
                    return this.context;
                } catch (RuntimeException var8) {
                    logger.error("Context initialization failed", var8);
                    servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, var8);
                    throw var8;
                } catch (Error var9) {
                    logger.error("Context initialization failed", var9);
                    servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, var9);
                    throw var9;
                }
            }
        }
      protected WebApplicationContext createWebApplicationContext(ServletContext sc) {
            Class<?> contextClass = this.determineContextClass(sc);
            if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {
                throw new ApplicationContextException("Custom context class [" + contextClass.getName() + "] is not of type [" + ConfigurableWebApplicationContext.class.getName() + "]");
            } else {
    // 日后的开发中可以借鉴这个方法,利用工具类去生成对象,避免重复造车
    return (ConfigurableWebApplicationContext)BeanUtils.instantiateClass(contextClass); } }
    ContextLoader.java的静态代码块加载解析property
     static {
            try {
                ClassPathResource resource = new ClassPathResource("ContextLoader.properties", ContextLoader.class);
                defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);
            } catch (IOException var1) {
                throw new IllegalStateException("Could not load 'ContextLoader.properties': " + var1.getMessage());
            }
    
            currentContextPerThread = new ConcurrentHashMap(1);
        }
    org.springframework.web.context.WebApplicationContext=org.springframework.web.context.support.XmlWebApplicationContext
    
    
    protected Class<?> determineContextClass(ServletContext servletContext) {
            String contextClassName = servletContext.getInitParameter("contextClass");
            if (contextClassName != null) {
                try {
                    return ClassUtils.forName(contextClassName, ClassUtils.getDefaultClassLoader());
                } catch (ClassNotFoundException var4) {
                    throw new ApplicationContextException("Failed to load custom context class [" + contextClassName + "]", var4);
                }
            } else {
                contextClassName = defaultStrategies.getProperty(WebApplicationContext.class.getName());
    
                try {
                    return ClassUtils.forName(contextClassName, ContextLoader.class.getClassLoader());
                } catch (ClassNotFoundException var5) {
                    throw new ApplicationContextException("Failed to load default context class [" + contextClassName + "]", var5);
                }
            }
        }


    protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) {
    String configLocationParam;
    if (ObjectUtils.identityToString(wac).equals(wac.getId())) {
    configLocationParam = sc.getInitParameter("contextId");
    if (configLocationParam != null) {
    wac.setId(configLocationParam);
    } else {
    wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX + ObjectUtils.getDisplayString(sc.getContextPath()));
    }
    }

    wac.setServletContext(sc);
    configLocationParam = sc.getInitParameter("contextConfigLocation");
    if (configLocationParam != null) {
    wac.setConfigLocation(configLocationParam);
    }

    ConfigurableEnvironment env = wac.getEnvironment();
    if (env instanceof ConfigurableWebEnvironment) {
    ((ConfigurableWebEnvironment)env).initPropertySources(sc, (ServletConfig)null);
    }

    this.customizeContext(sc, wac);
    wac.refresh();
    }

    public void refresh() throws BeansException, IllegalStateException {
    synchronized(this.startupShutdownMonitor) {
    this.prepareRefresh();
    ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
    this.prepareBeanFactory(beanFactory);

    try {
    this.postProcessBeanFactory(beanFactory);
    this.invokeBeanFactoryPostProcessors(beanFactory);
    this.registerBeanPostProcessors(beanFactory);
    this.initMessageSource();
    this.initApplicationEventMulticaster();
    this.onRefresh();
    this.registerListeners();
    this.finishBeanFactoryInitialization(beanFactory);
    this.finishRefresh();
    } catch (BeansException var9) {
    if (this.logger.isWarnEnabled()) {
    this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
    }

    this.destroyBeans();
    this.cancelRefresh(var9);
    throw var9;
    } finally {
    this.resetCommonCaches();
    }

    }
    }


    protected void prepareRefresh() {
    this.startupDate = System.currentTimeMillis();
    this.closed.set(false);
    this.active.set(true);
    if (this.logger.isInfoEnabled()) {
    this.logger.info("Refreshing " + this);
    }

    this.initPropertySources();
    this.getEnvironment().validateRequiredProperties();
    this.earlyApplicationEvents = new LinkedHashSet();
    }
    protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    this.refreshBeanFactory();
    ConfigurableListableBeanFactory beanFactory = this.getBeanFactory();
    if (this.logger.isDebugEnabled()) {
    this.logger.debug("Bean factory for " + this.getDisplayName() + ": " + beanFactory);
    }

    return beanFactory;
    }
    protected final void refreshBeanFactory() throws BeansException {
    if (this.hasBeanFactory()) {
    this.destroyBeans();
    this.closeBeanFactory();
    }

    try {
    DefaultListableBeanFactory beanFactory = this.createBeanFactory();
    beanFactory.setSerializationId(this.getId());
    this.customizeBeanFactory(beanFactory);
    this.loadBeanDefinitions(beanFactory);
    synchronized(this.beanFactoryMonitor) {
    this.beanFactory = beanFactory;
    }
    } catch (IOException var5) {
    throw new ApplicationContextException("I/O error parsing bean definition source for " + this.getDisplayName(), var5);
    }
    }
    -----------------------------------------------------------------------------------------------------------------------
    XmlWebApplicationContext.java
    @Override
    protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
    // Create a new XmlBeanDefinitionReader for the given BeanFactory.
    XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

    // Configure the bean definition reader with this context's
    // resource loading environment.
    beanDefinitionReader.setEnvironment(getEnvironment());
    beanDefinitionReader.setResourceLoader(this);
    beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

    // Allow a subclass to provide custom initialization of the reader,
    // then proceed with actually loading the bean definitions.
    initBeanDefinitionReader(beanDefinitionReader);
    loadBeanDefinitions(beanDefinitionReader);
    }

    /**
    * Load the bean definitions with the given XmlBeanDefinitionReader.
    * <p>The lifecycle of the bean factory is handled by the refreshBeanFactory method;
    * therefore this method is just supposed to load and/or register bean definitions.
    * <p>Delegates to a ResourcePatternResolver for resolving location patterns
    * into Resource instances.
    * @throws IOException if the required XML document isn't found
    * @see #refreshBeanFactory
    * @see #getConfigLocations
    * @see #getResources
    * @see #getResourcePatternResolver
    */
    protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws IOException {
    String[] configLocations = getConfigLocations();
    if (configLocations != null) {
    for (String configLocation : configLocations) {
    reader.loadBeanDefinitions(configLocation);
    }
    }
    }

    /**
    * Load bean definitions from the specified resource location.
    * <p>The location can also be a location pattern, provided that the
    * ResourceLoader of this bean definition reader is a ResourcePatternResolver.
    * @param location the resource location, to be loaded with the ResourceLoader
    * (or ResourcePatternResolver) of this bean definition reader
    * @param actualResources a Set to be filled with the actual Resource objects
    * that have been resolved during the loading process. May be {@code null}
    * to indicate that the caller is not interested in those Resource objects.
    * @return the number of bean definitions found
    * @throws BeanDefinitionStoreException in case of loading or parsing errors
    * @see #getResourceLoader()
    * @see #loadBeanDefinitions(org.springframework.core.io.Resource)
    * @see #loadBeanDefinitions(org.springframework.core.io.Resource[])
    */
    public int loadBeanDefinitions(String location, Set<Resource> actualResources) throws BeanDefinitionStoreException {
    ResourceLoader resourceLoader = getResourceLoader();
    if (resourceLoader == null) {
    throw new BeanDefinitionStoreException(
    "Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
    }

    if (resourceLoader instanceof ResourcePatternResolver) {
    // Resource pattern matching available.
    try {
    Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
    int loadCount = loadBeanDefinitions(resources);
    if (actualResources != null) {
    for (Resource resource : resources) {
    actualResources.add(resource);
    }
    }
    if (logger.isDebugEnabled()) {
    logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");
    }
    return loadCount;
    }
    catch (IOException ex) {
    throw new BeanDefinitionStoreException(
    "Could not resolve bean definition resource pattern [" + location + "]", ex);
    }
    }
    else {
    // Can only load single resources by absolute URL.
    Resource resource = resourceLoader.getResource(location);
    int loadCount = loadBeanDefinitions(resource);
    if (actualResources != null) {
    actualResources.add(resource);
    }
    if (logger.isDebugEnabled()) {
    logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");
    }
    return loadCount;
    }
    }

    /**
    * Load bean definitions from the specified XML file.
    * @param encodedResource the resource descriptor for the XML file,
    * allowing to specify an encoding to use for parsing the file
    * @return the number of bean definitions found
    * @throws BeanDefinitionStoreException in case of loading or parsing errors
    */
    public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
    Assert.notNull(encodedResource, "EncodedResource must not be null");
    if (logger.isInfoEnabled()) {
    logger.info("Loading XML bean definitions from " + encodedResource.getResource());
    }

    Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
    if (currentResources == null) {
    currentResources = new HashSet<EncodedResource>(4);
    this.resourcesCurrentlyBeingLoaded.set(currentResources);
    }
    if (!currentResources.add(encodedResource)) {
    throw new BeanDefinitionStoreException(
    "Detected cyclic loading of " + encodedResource + " - check your import definitions!");
    }
    try {
    InputStream inputStream = encodedResource.getResource().getInputStream();
    try {
    InputSource inputSource = new InputSource(inputStream);
    if (encodedResource.getEncoding() != null) {
    inputSource.setEncoding(encodedResource.getEncoding());
    }
    return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
    }
    finally {
    inputStream.close();
    }
    }
    catch (IOException ex) {
    throw new BeanDefinitionStoreException(
    "IOException parsing XML document from " + encodedResource.getResource(), ex);
    }
    finally {
    currentResources.remove(encodedResource);
    if (currentResources.isEmpty()) {
    this.resourcesCurrentlyBeingLoaded.remove();
    }
    }
    }


    /**
    * Actually load bean definitions from the specified XML file.
    * @param inputSource the SAX InputSource to read from
    * @param resource the resource descriptor for the XML file
    * @return the number of bean definitions found
    * @throws BeanDefinitionStoreException in case of loading or parsing errors
    * @see #doLoadDocument
    * @see #registerBeanDefinitions
    */
    protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
    throws BeanDefinitionStoreException {
    try {
    Document doc = doLoadDocument(inputSource, resource);
    return registerBeanDefinitions(doc, resource);
    }
    catch (BeanDefinitionStoreException ex) {
    throw ex;
    }
    catch (SAXParseException ex) {
    throw new XmlBeanDefinitionStoreException(resource.getDescription(),
    "Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex);
    }
    catch (SAXException ex) {
    throw new XmlBeanDefinitionStoreException(resource.getDescription(),
    "XML document from " + resource + " is invalid", ex);
    }
    catch (ParserConfigurationException ex) {
    throw new BeanDefinitionStoreException(resource.getDescription(),
    "Parser configuration exception parsing XML from " + resource, ex);
    }
    catch (IOException ex) {
    throw new BeanDefinitionStoreException(resource.getDescription(),
    "IOException parsing XML document from " + resource, ex);
    }
    catch (Throwable ex) {
    throw new BeanDefinitionStoreException(resource.getDescription(),
    "Unexpected exception parsing XML document from " + resource, ex);
    }
    }
    /**
    * Register the bean definitions contained in the given DOM document.
    * Called by {@code loadBeanDefinitions}.
    * <p>Creates a new instance of the parser class and invokes
    * {@code registerBeanDefinitions} on it.
    * @param doc the DOM document
    * @param resource the resource descriptor (for context information)
    * @return the number of bean definitions found
    * @throws BeanDefinitionStoreException in case of parsing errors
    * @see #loadBeanDefinitions
    * @see #setDocumentReaderClass
    * @see BeanDefinitionDocumentReader#registerBeanDefinitions
    */
    public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
    BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
    int countBefore = getRegistry().getBeanDefinitionCount();
    documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
    return getRegistry().getBeanDefinitionCount() - countBefore;
    }
    
    
    /**
    * Register each bean definition within the given root {@code <beans/>} element.
    */
    protected void doRegisterBeanDefinitions(Element root) {
    // Any nested <beans> elements will cause recursion in this method. In
    // order to propagate and preserve <beans> default-* attributes correctly,
    // keep track of the current (parent) delegate, which may be null. Create
    // the new (child) delegate with a reference to the parent for fallback purposes,
    // then ultimately reset this.delegate back to its original (parent) reference.
    // this behavior emulates a stack of delegates without actually necessitating one.
    BeanDefinitionParserDelegate parent = this.delegate;
    this.delegate = createDelegate(getReaderContext(), root, parent);

    if (this.delegate.isDefaultNamespace(root)) {
    String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
    if (StringUtils.hasText(profileSpec)) {
    String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
    profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
    if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
    if (logger.isInfoEnabled()) {
    logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +
    "] not matching: " + getReaderContext().getResource());
    }
    return;
    }
    }
    }

    preProcessXml(root);
    parseBeanDefinitions(root, this.delegate);
    postProcessXml(root);

    this.delegate = parent;
    }

    /**
    * Parse the elements at the root level in the document:
    * "import", "alias", "bean".
    * @param root the DOM root element of the document
    */
    protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
    if (delegate.isDefaultNamespace(root)) {
    NodeList nl = root.getChildNodes();
    for (int i = 0; i < nl.getLength(); i++) {
    Node node = nl.item(i);
    if (node instanceof Element) {
    Element ele = (Element) node;
    if (delegate.isDefaultNamespace(ele)) {
    parseDefaultElement(ele, delegate);
    }
    else {
    delegate.parseCustomElement(ele);
    }
    }
    }
    }
    else {
    delegate.parseCustomElement(root);
    }
    }


    --------------------------------------------------------------------------------------------------------------------------
    AnnotationConfigWebApplicationContext.java
    @Override
    protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) {
    AnnotatedBeanDefinitionReader reader = getAnnotatedBeanDefinitionReader(beanFactory);
    ClassPathBeanDefinitionScanner scanner = getClassPathBeanDefinitionScanner(beanFactory);

    BeanNameGenerator beanNameGenerator = getBeanNameGenerator();
    if (beanNameGenerator != null) {
    reader.setBeanNameGenerator(beanNameGenerator);
    scanner.setBeanNameGenerator(beanNameGenerator);
    beanFactory.registerSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR, beanNameGenerator);
    }

    ScopeMetadataResolver scopeMetadataResolver = getScopeMetadataResolver();
    if (scopeMetadataResolver != null) {
    reader.setScopeMetadataResolver(scopeMetadataResolver);
    scanner.setScopeMetadataResolver(scopeMetadataResolver);
    }

    if (!this.annotatedClasses.isEmpty()) {
    if (logger.isInfoEnabled()) {
    logger.info("Registering annotated classes: [" +
    StringUtils.collectionToCommaDelimitedString(this.annotatedClasses) + "]");
    }
    reader.register(this.annotatedClasses.toArray(new Class<?>[this.annotatedClasses.size()]));
    }

    if (!this.basePackages.isEmpty()) {
    if (logger.isInfoEnabled()) {
    logger.info("Scanning base packages: [" +
    StringUtils.collectionToCommaDelimitedString(this.basePackages) + "]");
    }
    scanner.scan(this.basePackages.toArray(new String[this.basePackages.size()]));
    }

    String[] configLocations = getConfigLocations();
    if (configLocations != null) {
    for (String configLocation : configLocations) {
    try {
    Class<?> clazz = getClassLoader().loadClass(configLocation);
    if (logger.isInfoEnabled()) {
    logger.info("Successfully resolved class for [" + configLocation + "]");
    }
    reader.register(clazz);
    }
    catch (ClassNotFoundException ex) {
    if (logger.isDebugEnabled()) {
    logger.debug("Could not load class for config location [" + configLocation +
    "] - trying package scan. " + ex);
    }
    int count = scanner.scan(configLocation);
    if (logger.isInfoEnabled()) {
    if (count == 0) {
    logger.info("No annotated classes found for specified class/package [" + configLocation + "]");
    }
    else {
    logger.info("Found " + count + " annotated classes in package [" + configLocation + "]");
    }
    }
    }
    }
    }
    }
    //参考大神
    http://geeekr.com/read-spring-source-1-how-to-load-bean/
  • 相关阅读:
    [Qt] 文本文件读写, 摘自官方文档
    [Windows] Socket Server Failed to bind, error 10048
    lodctr /R 失败的情况
    ModuleNotFoundError: No module named 'sklearn.cross_validation'
    [Qt] 通过socket将另一个程序的某个窗口调到最前端
    SortedDictionary<TKey, TValue> 类 表示根据键进行排序的键/值对的集合。
    finally不管有没有错都会运行 finally 块用于清除 try 块中分配的任何资源,以及运行任何即使在发生异常时也必须执行的代码
    HttpWebRequest使用证书请求
    string StartsWith 方法 Https
    设置https验证方式
  • 原文地址:https://www.cnblogs.com/longxok/p/10832166.html
Copyright © 2011-2022 走看看