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

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

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

    隨筆 - 9, 文章 - 0, 評論 - 3, 引用 - 0
    數(shù)據(jù)加載中……

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

    轉(zhuǎn)載自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監(jiān)聽器 -->
                <listener>
                <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
                </listener>
                 
                <!-- 定義SPRING監(jiān)聽器 -->
                
                <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上下文初始化時,系統(tǒng)會調(diào)用此方法
                public void contextInitialized(ServletContextEvent event) {
                this.contextLoader = createContextLoader();
                 
                
                //監(jiān)聽到WEB上下文初始化的時候執(zhí)行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.
                 
                
                //創(chuàng)建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 {
                
                //根據(jù)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中設(shè)置的SPRING配置文件位置
                String configLocation = servletContext.getInitParameter(CONFIG_LOCATION_PARAM);
                if (configLocation != null) {
                //把配置文件分段后設(shè)置到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中有設(shè)置,如果沒有設(shè)置,那么為空
                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中沒有設(shè)置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 {
                
                //設(shè)置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);
                 
                //設(shè)置beanDefinitionReader服務(wù)于當前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 {
                
                //根據(jù)配置文件讀取相應(yīng)配置
                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的實現(xiàn)
    ==>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 并沒有實現(xiàn)refresh方法,而方法的實現(xiàn)寫在

    AbstractRefreshableWebApplicationContext 中

    ==>AbstractRefreshableWebApplicationContext.refresh();
    1
    2
    3
    4
    5
    6
    7
    public void refresh() throws BeansException {
                if (ObjectUtils.isEmpty(getConfigLocations())) {
                //設(shè)置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

    評論

    # 福德宮  回復(fù)  更多評論   

    的風格大方
    2014-09-03 17:40 | 梵蒂岡的發(fā)揮

    只有注冊用戶登錄后才能發(fā)表評論。


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 亚洲精品tv久久久久| 亚洲AV中文无码乱人伦下载 | 污污网站免费观看| 亚洲日本香蕉视频观看视频| 成年女人毛片免费播放视频m| 羞羞的视频在线免费观看| 国产亚洲精品岁国产微拍精品| 午夜免费福利片观看| 亚洲色精品VR一区区三区| 亚洲国产成人久久综合碰| 无码少妇精品一区二区免费动态 | 久久久久免费看黄A片APP| 色屁屁在线观看视频免费| 亚洲a在线视频视频| 欧洲精品免费一区二区三区| 中文永久免费观看网站| 亚洲精品美女网站| 国产成人精品日本亚洲专区61 | 在线亚洲精品自拍| 国产卡一卡二卡三免费入口 | 成人A片产无码免费视频在线观看| 亚洲国产精品日韩在线| 精品国产人成亚洲区| 麻豆最新国产剧情AV原创免费| 九九全国免费视频| 久久夜色精品国产噜噜亚洲a| 亚洲精品国产美女久久久| 看全色黄大色大片免费久久| 在线观看免费无码专区| 国产99久久亚洲综合精品| 亚洲欧洲视频在线观看| 亚洲色无码专区在线观看| 国产最新凸凹视频免费| 在免费jizzjizz在线播| a毛片免费全部在线播放**| 青青青亚洲精品国产| 亚洲人成综合网站7777香蕉| 亚洲综合国产精品| 亚洲乱码一区二区三区在线观看| 国产一区二区三区免费视频| 国产人在线成免费视频|