spring 入门 之运行机制

技术不太好,对spring在慢慢学习ing.写的有错误还望指正..

spring的运行需要在web.xml加上spring的监听,
配置spring的xml文件路径
	<!-- 配置spring资源 -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:config/applicationContext-*.xml</param-value>
	</context-param>
不写上边那个的话也行,代表默认路径在java文件有体现,下边是配置监听
<!-- 配置spring -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
在spring-web.release.jar中的ContextLoadListener这个类
public void contextInitialized(ServletContextEvent event)
    {
        contextLoader = createContextLoader();
        if(contextLoader == null)
            contextLoader = this;
//监听web上下文初始化spring上下文
       contextLoader.initWebApplicationContext(event.getServletContext());
    }


然后追踪到ContextLoad这个类
public WebApplicationContext initWebApplicationContext(ServletContext servletContext)
    {
        Log logger;
        long startTime;
        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!");
        logger = LogFactory.getLog(org/springframework/web/context/ContextLoader);
        servletContext.log("Initializing Spring root WebApplicationContext");
        if(logger.isInfoEnabled())
            logger.info("Root WebApplicationContext: initialization started");
        startTime = System.currentTimeMillis();
       
        //创建web上下文
	if(context == null)
            context = createWebApplicationContext(servletContext);
        if(context instanceof ConfigurableWebApplicationContext)
        {
            ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext)context;
            if(!cwac.isActive())
            {
                if(cwac.getParent() == null)
                {
                    ApplicationContext parent = loadParentContext(servletContext);
                    cwac.setParent(parent);
                }
                configureAndRefreshWebApplicationContext(cwac, servletContext);
            }
        }
        servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, context);
        ClassLoader ccl = Thread.currentThread().getContextClassLoader();
        if(ccl == org/springframework/web/context/ContextLoader.getClassLoader())
            currentContext = context;
        else
        if(ccl != null)
            currentContextPerThread.put(ccl, context);
        if(logger.isDebugEnabled())
            logger.debug((new StringBuilder()).append("Published root WebApplicationContext as ServletContext attribute with name [").append(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE).append("]").toString());
        if(logger.isInfoEnabled())
        {
            long elapsedTime = System.currentTimeMillis() - startTime;
            logger.info((new StringBuilder()).append("Root WebApplicationContext: initialization completed in ").append(elapsedTime).append(" ms").toString());
        }
        return context;
        RuntimeException ex;
        ex;
        logger.error("Context initialization failed", ex);
        servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, ex);
        throw ex;
        Error err;
        err;
        logger.error("Context initialization failed", err);
        servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, err);
        throw err;
    }
然后追踪到ContextLoad.createWebApplicationContext
 protected WebApplicationContext createWebApplicationContext(ServletContext sc)
    {
	//根据ServletContext来决定要实例化的webApplicationContext
        Class contextClass = determineContextClass(sc);
       if(!org/springframework/web/context/ConfigurableWebApplicationContext.isAssignableFrom(contextClass))
            throw new ApplicationContextException((new StringBuilder()).append("Custom context class [").append(contextClass.getName()).append("] is not of type [").append(org/springframework/web/context/ConfigurableWebApplicationContext.getName()).append("]").toString());
        else
            return (ConfigurableWebApplicationContext)BeanUtils.instantiateClass(contextClass);
    }
==>ContextLoader.determineContextClass
 protected Class determineContextClass(ServletContext servletContext)
    {
	//获得初始化的context类名,在web.xml中设置,没有则为空
        String contextClassName;
        contextClassName = servletContext.getInitParameter("contextClass");
        if(contextClassName == null)
            break MISSING_BLOCK_LABEL_55;
        return ClassUtils.forName(contextClassName, ClassUtils.getDefaultClassLoader());
        ClassNotFoundException ex;
        ex;
        throw new ApplicationContextException((new StringBuilder()).append("Failed to load custom context class [").append(contextClassName).append("]").toString(), ex);
	//如果在web.xml中没有设置context类的位置,那么取默认的context
        //取得defaultStrategies配置中的WebApplocationContext属性
        contextClassName = defaultStrategies.getProperty(org/springframework/web/context/WebApplicationContext.getName());
        return ClassUtils.forName(contextClassName, org/springframework/web/context/ContextLoader.getClassLoader());
        ex;
        throw new ApplicationContextException((new StringBuilder()).append("Failed to load default context class [").append(contextClassName).append("]").toString(), ex);
    }
spring上下文默认生成策略
==>contextLoader.defaultStrategies
 static 
    {
        try
        {
	//设置properties为ContextLoader同级目录
            ClassPathResource resource = new ClassPathResource("ContextLoader.properties", org/springframework/web/context/ContextLoader);
       	//加载该目录下的properties文件
	    defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);
        }
        catch(IOException ex)
        {
            throw new IllegalStateException((new StringBuilder()).append("Could not load 'ContextLoader.properties': ").append(ex.getMessage()).toString());
        }
    }
找到同级目录下的ContextLoader.properties配置文件


# 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

找到此包下的XmlWebApplicationContext文件
public class XmlWebApplicationContext extends AbstractRefreshableWebApplicationContext
{

    public XmlWebApplicationContext()
    {
    }
		
//获取bean配置
    protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory)
        throws BeansException, IOException
    {
	//从bean工厂获取一个XmlBeanDefinitionReader来读取Spring配置文件
        XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
        beanDefinitionReader.setEnvironment(getEnvironment());
	//设置beanDefinitionReader服务当前CONTEXT
        beanDefinitionReader.setResourceLoader(this);
        beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
        initBeanDefinitionReader(beanDefinitionReader);
	//读取配置文件
        loadBeanDefinitions(beanDefinitionReader);
    }

	
    protected void initBeanDefinitionReader(XmlBeanDefinitionReader xmlbeandefinitionreader)
    {
    }
	//读取配置文件
    protected void loadBeanDefinitions(XmlBeanDefinitionReader reader)
        throws IOException
    {
        String configLocations[] = getConfigLocations();
        if(configLocations != null)
        {
            String arr$[] = configLocations;
            int len$ = arr$.length;
            for(int i$ = 0; i$ < len$; i$++)
            {
                String configLocation = arr$[i$];
                reader.loadBeanDefinitions(configLocation);
            }

        }
    }

	//获得默认的Configlocation
    protected String[] getDefaultConfigLocations()
    {
        if(getNamespace() != null)
            return (new String[] {
                (new StringBuilder()).append("/WEB-INF/").append(getNamespace()).append(".xml").toString()
            });
        else
            return (new String[] {
                "/WEB-INF/applicationContext.xml"
            });
    }
	//配置了默认的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";
}
然后loadBeanDefinitions这个方法在spring-bean.release.jar中的AbstractBeanDefinitionReader中
  public int loadBeanDefinitions(String location)
        throws BeanDefinitionStoreException
    {
        return loadBeanDefinitions(location, null);
    }

    public int loadBeanDefinitions(String location, Set actualResources)
        throws BeanDefinitionStoreException
    {
        ResourceLoader resourceLoader;
        resourceLoader = getResourceLoader();
        if(resourceLoader == null)
            throw new BeanDefinitionStoreException((new StringBuilder()).append("Cannot import bean definitions from location [").append(location).append("]: no ResourceLoader available").toString());
        if(!(resourceLoader instanceof ResourcePatternResolver))
            break MISSING_BLOCK_LABEL_207;
        int loadCount;
	//根据配置文件读取相应位置
        Resource resources[] = ((ResourcePatternResolver)resourceLoader).getResources(location);
        loadCount = loadBeanDefinitions(resources);
        if(actualResources != null)
        {
            Resource arr$[] = resources;
            int len$ = arr$.length;
            for(int i$ = 0; i$ < len$; i$++)
            {
                Resource resource = arr$[i$];
                actualResources.add(resource);
            }

        }
        if(logger.isDebugEnabled())
            logger.debug((new StringBuilder()).append("Loaded ").append(loadCount).append(" bean definitions from location pattern [").append(location).append("]").toString());
        return loadCount;
        IOException ex;
        ex;
        throw new BeanDefinitionStoreException((new StringBuilder()).append("Could not resolve bean definition resource pattern [").append(location).append("]").toString(), ex);
        Resource resource = resourceLoader.getResource(location);
        loadCount = loadBeanDefinitions(resource);
        if(actualResources != null)
            actualResources.add(resource);
        if(logger.isDebugEnabled())
            logger.debug((new StringBuilder()).append("Loaded ").append(loadCount).append(" bean definitions from location [").append(location).append("]").toString());
        return loadCount;
    }
分析一个ResourceLoader的实现在spring-core-3.2.1.RELEASE.jar中的 org.springframework.core.io.support包里
有一个PathMatchingResourcePatternResolver实现其接口
    public Resource[] getResources(String locationPattern)
        throws IOException
    {
        Assert.notNull(locationPattern, "Location pattern must not be null");
        if(locationPattern.startsWith("classpath*:"))
            if(getPathMatcher().isPattern(locationPattern.substring("classpath*:".length())))
                return findPathMatchingResources(locationPattern);
            else
                return findAllClassPathResources(locationPattern.substring("classpath*:".length()));
        int prefixEnd = locationPattern.indexOf(":") + 1;
        if(getPathMatcher().isPattern(locationPattern.substring(prefixEnd)))
            return findPathMatchingResources(locationPattern);
        else
            return (new Resource[] {
                getResourceLoader().getResource(locationPattern)
            });
    }

 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 = new LinkedHashSet(16);
        Resource arr$[] = rootDirResources;
        int len$ = arr$.length;
        for(int i$ = 0; i$ < len$; i$++)
        {
            Resource rootDirResource = arr$[i$];
            rootDirResource = resolveRootDirResource(rootDirResource);
            if(isJarResource(rootDirResource))
            {
                result.addAll(doFindPathMatchingJarResources(rootDirResource, subPattern));
                continue;
            }
            if(rootDirResource.getURL().getProtocol().startsWith("vfs"))
                result.addAll(VfsResourceMatchingDelegate.findMatchingResources(rootDirResource, subPattern, getPathMatcher()));
            else
                result.addAll(doFindPathMatchingFileResources(rootDirResource, subPattern));
        }

        if(logger.isDebugEnabled())
            logger.debug((new StringBuilder()).append("Resolved location pattern [").append(locationPattern).append("] to resources ").append(result).toString());
        return (Resource[])result.toArray(new Resource[result.size()]);
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Spring的IOC容器运行机制是通过配置元数据的加载、Bean的实例化、依赖注入、生命周期管理和AOP支持等机制来实现对Bean的管理和控制。具体来说,首先需要定义一个或多个XML配置文件,其中包含了对应的Bean定义和它们之间的关系。然后,在应用程序启动时,IOC容器会读取这些配置文件,并根据配置信息创建和管理相应的Bean实例。IOC容器会负责将依赖关系注入到Bean中,即根据配置信息,自动将依赖的对象注入到需要使用它们的对象中,从而降低了组件之间的耦合度。此外,IOC容器还负责管理Bean的生命周期,包括初始化和销毁。最后,IOC容器还提供了AOP(面向切面编程)的支持,通过代理机制,可以在不修改原有代码的情况下,为Bean添加额外的功能。总的来说,通过这些机制,Spring的IOC容器实现了对Bean的管理和控制,提高了代码的可维护性和可测试性。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Spring详细学习资料下载](https://download.csdn.net/download/xs765914759/83322672)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Spring题集 - Spring IoC容器相关面试题总结](https://blog.csdn.net/qq_42764468/article/details/129468636)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值