<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆 - 9, 文章 - 0, 評論 - 3, 引用 - 0
    數據加載中……

    初探spring applicationContext在web容器中加載過程

    轉載自www.javaworld.com.tw 袁杰 原文

    首先從WEB.XML入手

    ==>web.xml

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    <context-param>
                <param-name>webAppRootKey</param-name>
                <param-value>task.root</param-value>
                </context-param>
                <!-- 定義SPRING配置文件 -->
                
                <context-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>/WEB-INF/taskContext*.xml</param-value>
                </context-param>
                
                <context-param>
                <param-name>log4jConfigLocation</param-name>
                <param-value>/WEB-INF/log4j.properties</param-value>
                </context-param>
                <!-- 定義LOG4J監聽器 -->
                <listener>
                <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
                </listener>
                 
                <!-- 定義SPRING監聽器 -->
                
                <listener>
                <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
                </listener>
                
                

    進入contextLoaderListener看看到底加載時做了甚么
    ==>org.springframework.web.context.ContextLoaderListener

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    public class ContextLoaderListener implements ServletContextListener {
                 
                private ContextLoader contextLoader;
                 
                /**
                * Initialize the root web application context.
                */
                //當WEB上下文初始化時,系統會調用此方法
                public void contextInitialized(ServletContextEvent event) {
                this.contextLoader = createContextLoader();
                 
                
                //監聽到WEB上下文初始化的時候執行SPRING上下文contextLoader的初始化工作
                this.contextLoader.initWebApplicationContext(event.getServletContext());
                
                }
                 
                /**
                * Create the ContextLoader to use. Can be overridden in subclasses.
                * @return the new ContextLoader
                */
                protected ContextLoader createContextLoader() {
                return new ContextLoader();
                }
                 
                /**
                * Return the ContextLoader used by this listener.
                */
                public ContextLoader getContextLoader() {
                return contextLoader;
                }
                 
                /**
                * Close the root web application context.
                */
                public void contextDestroyed(ServletContextEvent event) {
                if (this.contextLoader != null) {
                this.contextLoader.closeWebApplicationContext(event.getServletContext());
                }
                }
                 
                }
                

    看一下是怎么來初始化webapplicationContext的
    ==>contextLoader.initWebApplicationContext

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    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!");
                }
                 
                long startTime = System.currentTimeMillis();
                if (logger.isInfoEnabled()) {
                logger.info("Root WebApplicationContext: initialization started");
                }
                servletContext.log("Loading Spring root WebApplicationContext");
                 
                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.
                 
                
                //創建web上下文
                this.context = createWebApplicationContext(servletContext, parent);
                servletContext.setAttribute(
                WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
                
                 
                if (logger.isInfoEnabled()) {
                logger.info("Using context class [" + this.context.getClass().getName() +
                "] for root WebApplicationContext");
                }
                if (logger.isDebugEnabled()) {
                logger.debug("Published root WebApplicationContext [" + this.context +
                "] 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 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;
                }
                }
                

    ==>contextLoader.createWebApplicationContext(servletContext, parent);

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
     protected WebApplicationContext createWebApplicationContext(
                ServletContext servletContext, ApplicationContext parent) throws BeansException {
                
                //根據servletContext來決定要實例化的WebApplicationContext
                Class contextClass = determineContextClass(servletContext);
                if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {
                throw new ApplicationContextException("Custom context class [" + contextClass.getName() +
                "] is not of type ConfigurableWebApplicationContext");
                }
                ConfigurableWebApplicationContext wac =
                (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
                wac.setParent(parent);
                wac.setServletContext(servletContext);
                 
                //得到WEB.XML中設置的SPRING配置文件位置
                String configLocation = servletContext.getInitParameter(CONFIG_LOCATION_PARAM);
                if (configLocation != null) {
                //把配置文件分段后設置到WebApplicationContext的ConfigLocations中
                wac.setConfigLocations(StringUtils.tokenizeToStringArray(configLocation,
                ConfigurableWebApplicationContext.CONFIG_LOCATION_DELIMITERS));
                }
                //刷新WebApplicationContext
                wac.refresh();
                
                return wac;
                }
                

    ==>contextLoader.determineContextClass(servletContext);

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    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 [" + contextClassName + "]", ex);
                }
                }
                //如果在spring web.xml中沒有設置context類位置,那么取得默認context
                else {
                //取得defaultStrategies配置文件中的WebApplicationContext屬性
                contextClassName = defaultStrategies.getProperty(WebApplicationContext.class.getName());
                try {
                return ClassUtils.forName(contextClassName);
                }
                catch (ClassNotFoundException ex) {
                throw new ApplicationContextException(
                "Failed to load default context class [" + contextClassName + "]", ex);
                }
                }
                
                }
                

    SPRING上下文默認的策略是甚么呢?
    ==>contextLoader.defaultStrategies

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
      private static final Properties defaultStrategies;
                 
                static {
                // Load default strategy implementations from properties file.
                // This is currently strictly internal and not meant to be customized
                // by application developers.
                try {
                
                //設置classpath為contextLoader同級目錄
                ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, ContextLoader.class);
                //加載該目錄下的所有properties文件
                defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);
                
                }
                catch (IOException ex) {
                throw new IllegalStateException("Could not load 'ContextLoader.properties': " + ex.getMessage());
                }
                }
                

    找到同級目錄下的配置文件
    ==>ContextLoader.properties

    1
    2
    3
    4
    5
    6
    7
    8
    # Default WebApplicationContext implementation class for ContextLoader.
                # Used as fallback when no explicit context implementation has been specified as context-param.
                # Not meant to be customized by application developers.
                 
                
                #默認的WebApplicationContext為org.springframework.web.context.support.XmlWebApplicationContext
                org.springframework.web.context.WebApplicationContext=org.springframework.web.context.support.XmlWebApplicationContext
                
                

    ==>org.springframework.web.context.support.XmlWebApplicationContext
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    public class XmlWebApplicationContext extends AbstractRefreshableWebApplicationContext {
                 
                /** Default config location for the root context */
                 
                
                //配置了默認的spring配置文件
                public static final String DEFAULT_CONFIG_LOCATION = "/WEB-INF/applicationContext.xml";
                
                 
                //配置文件默認BUILD路徑
                public static final String DEFAULT_CONFIG_LOCATION_PREFIX = "/WEB-INF/";
                 
                //配置文件默認后綴名
                public static final String DEFAULT_CONFIG_LOCATION_SUFFIX = ".xml";
                 
                /**
                * Loads the bean definitions via an XmlBeanDefinitionReader.
                * @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
                * @see #initBeanDefinitionReader
                * @see #loadBeanDefinitions
                */
                //獲得bean配置
                protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws IOException {
                //從BEAN工廠獲得一個XmlBeanDefinitionReader 來讀取SPRING配置文件
                XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
                 
                //設置beanDefinitionReader服務于當前CONTEXT
                // resource loading environment.
                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);
                
                }
                 
                /**
                * Initialize the bean definition reader used for loading the bean
                * definitions of this context. Default implementation is empty.
                * <p>Can be overridden in subclasses, e.g. for turning off XML validation
                * or using a different XmlBeanDefinitionParser implementation.
                * @param beanDefinitionReader the bean definition reader used by this context
                * @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader#setValidationMode
                * @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader#setDocumentReaderClass
                */
                protected void initBeanDefinitionReader(XmlBeanDefinitionReader 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 org.springframework.beans.BeansException in case of bean registration errors
                * @throws java.io.IOException if the required XML document isn't found
                * @see #refreshBeanFactory
                * @see #getConfigLocations
                * @see #getResources
                * @see #getResourcePatternResolver
                */
                
                //讀取配置文件
                protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
                String[] configLocations = getConfigLocations();
                if (configLocations != null) {
                for (int i = 0; i < configLocations.length; i++) {
                reader.loadBeanDefinitions(configLocations[i]);
                }
                }
                }
                
                 
                /**
                * The default location for the root context is "/WEB-INF/applicationContext.xml",
                * and "/WEB-INF/test-servlet.xml" for a context with the namespace "test-servlet"
                * (like for a DispatcherServlet instance with the servlet-name "test").
                */
                //獲得默認的ConfigLocations
                protected String[] getDefaultConfigLocations() {
                if (getNamespace() != null) {
                return new String[] {DEFAULT_CONFIG_LOCATION_PREFIX + getNamespace() +
                 
                DEFAULT_CONFIG_LOCATION_SUFFIX};
                }
                else {
                return new String[] {DEFAULT_CONFIG_LOCATION};
                }
                }
                

    ==>AbstractBeanDefinitionReader.loadBeanDefinitions()

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    public int loadBeanDefinitions(String location) 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 (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 (logger.isDebugEnabled()) {
                logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");
                }
                return loadCount;
                }
                }
                

    這個是其中一個ResourceLoader的實現
    ==>PathMatchingResourcePatternResolver.getResources(String locationPattern);

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
     public Resource[] getResources(String locationPattern) throws IOException {
                Assert.notNull(locationPattern, "Location pattern must not be null");
                if (locationPattern.startsWith(CLASSPATH_ALL_URL_PREFIX)) {
                // a class path resource (multiple resources for same name possible)
                
                if (getPathMatcher().isPattern(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()))) {
                // a class path resource pattern
                return findPathMatchingResources(locationPattern);
                }
                else {
                // all class path resources with the given name
                return findAllClassPathResources(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()));
                }
                
                }
                else {
                // Only look for a pattern after a prefix here
                // (to not get fooled by a pattern symbol in a strange prefix).
                int prefixEnd = locationPattern.indexOf(":") + 1;
                if (getPathMatcher().isPattern(locationPattern.substring(prefixEnd))) {
                // a file pattern
                return findPathMatchingResources(locationPattern);
                }
                else {
                // a single resource with the given name
                return new Resource[] {getResourceLoader().getResource(locationPattern)};
                }
                }
                }
                


    ==>PathMatchingResourcePatternResolver.findPathMatchingResources(String locationPattern);

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
     protected Resource[] findPathMatchingResources(String locationPattern) throws IOException {
                String rootDirPath = determineRootDir(locationPattern);
                String subPattern = locationPattern.substring(rootDirPath.length());
                Resource[] rootDirResources = getResources(rootDirPath);
                
                //collectionFactory初始化一個set容量為16
                Set result = CollectionFactory.createLinkedSetIfPossible(16);
                for (int i = 0; i < rootDirResources.length; i++) {
                Resource rootDirResource = rootDirResources[i];
                if (isJarResource(rootDirResource)) {
                result.addAll(doFindPathMatchingJarResources(rootDirResource, subPattern));
                }
                else {
                result.addAll(doFindPathMatchingFileResources(rootDirResource, subPattern));
                }
                }
                
                if (logger.isDebugEnabled()) {
                logger.debug("Resolved location pattern [" + locationPattern + "] to resources " + result);
                }
                return (Resource[]) result.toArray(new Resource[result.size()]);
                }
                


    前面說到有一個刷新WebApplicationContext的操作,但是XmlWebApplicationContext 并沒有實現refresh方法,而方法的實現寫在

    AbstractRefreshableWebApplicationContext 中

    ==>AbstractRefreshableWebApplicationContext.refresh();
    1
    2
    3
    4
    5
    6
    7
    public void refresh() throws BeansException {
                if (ObjectUtils.isEmpty(getConfigLocations())) {
                //設置configLocations為默認的getDefaultConfigLocations()
                setConfigLocations(getDefaultConfigLocations());
                }
                super.refresh();
                }
                


    ==>AbstractApplicationContext.refresh();
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    public void refresh() throws BeansException, IllegalStateException {
                synchronized (this.startupShutdownMonitor) {
                this.startupTime = System.currentTimeMillis();
                 
                synchronized (this.activeMonitor) {
                this.active = true;
                }
                 
                // Tell subclass to refresh the internal bean factory.
                refreshBeanFactory();
                ConfigurableListableBeanFactory beanFactory = getBeanFactory();
                 
                // Tell the internal bean factory to use the context's class loader.
                beanFactory.setBeanClassLoader(getClassLoader());
                 
                // Populate the bean factory with context-specific resource editors.
                beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this));
                 
                // Configure the bean factory with context semantics.
                beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
                beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
                beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
                beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
                beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
                 
                // Allows post-processing of the bean factory in context subclasses.
                postProcessBeanFactory(beanFactory);
                 
                // Invoke factory processors registered with the context instance.
                for (Iterator it = getBeanFactoryPostProcessors().iterator(); it.hasNext();) {
                BeanFactoryPostProcessor factoryProcessor = (BeanFactoryPostProcessor) it.next();
                factoryProcessor.postProcessBeanFactory(beanFactory);
                }
                 
                if (logger.isInfoEnabled()) {
                if (getBeanDefinitionCount() == 0) {
                logger.info("No beans defined in application context [" + getDisplayName() + "]");
                }
                else {
                logger.info(getBeanDefinitionCount() + " beans defined in application context [" +
                 
                getDisplayName() + "]");
                }
                }
                 
                try {
                // Invoke factory processors registered as beans in the context.
                invokeBeanFactoryPostProcessors();
                 
                // Register bean processors that intercept bean creation.
                registerBeanPostProcessors();
                 
                // 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 singletons this late to allow them to access the message source.
                beanFactory.preInstantiateSingletons();
                 
                // Last step: publish corresponding event.
                publishEvent(new ContextRefreshedEvent(this));
                }
                 
                catch (BeansException ex) {
                // Destroy already created singletons to avoid dangling resources.
                beanFactory.destroySingletons();
                throw ex;
                }
                }
                }
                

    posted on 2007-11-07 15:06 空杯 閱讀(10738) 評論(1)  編輯  收藏 所屬分類: Spring

    評論

    # 福德宮  回復  更多評論   

    的風格大方
    2014-09-03 17:40 | 梵蒂岡的發揮
    主站蜘蛛池模板: 亚洲综合久久一本伊伊区| 亚洲AV成人精品网站在线播放| 亚洲人精品亚洲人成在线| 亚欧色视频在线观看免费| 亚洲理论精品午夜电影| 91高清免费国产自产| 亚洲一级免费毛片| 免费的一级片网站| 国产精品无码亚洲一区二区三区| 国产精品高清全国免费观看| 黄网站色视频免费看无下截 | 又黄又爽的视频免费看| 美女视频黄频a免费大全视频| 免费在线观看的黄色网址| 乱淫片免费影院观看| 夜夜春亚洲嫩草影院| 国产好大好硬好爽免费不卡 | 国产成人精品亚洲2020| 国产禁女女网站免费看| 2022免费国产精品福利在线| 久久亚洲伊人中字综合精品| 2021免费日韩视频网| 亚洲av日韩av永久在线观看| 国产精品亚洲玖玖玖在线观看| 国产免费MV大全视频网站| 91天堂素人精品系列全集亚洲| 无码日韩精品一区二区免费| 国产精品亚洲二区在线| 亚洲无人区午夜福利码高清完整版| 久久国产免费一区二区三区| 亚洲看片无码在线视频| 亚洲色偷偷综合亚洲AV伊人| 91香蕉国产线在线观看免费 | 久久国产精品免费一区| 18gay台湾男同亚洲男同| 成人免费a级毛片无码网站入口 | 四虎成人免费观看在线网址| 一级成人生活片免费看| 亚洲码一区二区三区| 亚洲av午夜成人片精品电影| 最近最新高清免费中文字幕|