技术不太好,对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()]);
}
spring 入门 之运行机制
最新推荐文章于 2020-07-02 21:53:31 发布