呵呵,无论从调用关系、方法名称和注释都能敏感的感觉到找对地方了,
prepareRefresh
的注释写“
refreshing”
,真搞不清这个概念,先进去看看:
protected void prepareRefresh() {
this.startupDate = System.currentTimeMillis();
synchronized (this.activeMonitor) {
this.active = true;
}
if (logger.isInfoEnabled()) {
logger.info("Refreshing " + this);
}
}
发现,就是重置一个标志位(先不要急于对看见的东西着迷,我说的是看到和目标暂时无关的东西),我发现貌似和我找的东西无关,先退到到主程序再说
(
这只是一个小例子,如果遇到一个大的和查找目的无关的代码,你先大体看看,然后再决定是不是马上退回去,不要在这里浪费时间,迟早还会回来的,这可以帮助你减少陷入代码丛林中的几率
)
,接下来看
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
发现
obtainFreshBeanFactory()
方法的实现是:
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
对于
refreshBeanFactory
方法:
protected abstract void refreshBeanFactory() throws BeansException, IllegalStateException;
唉?一个抽象方法!谁实现它,反正不是
AbstractApplicationContext!
想退回去?且慢,当你不明确知道一个方法调用在干什么,尤其是抽象方法,你最好先找找它的实现,再想退回去也不迟,因为只要你忽略掉一个部分,就会对后面的代码的理解产生偏差,但是不要太深入了,这样既可以保证不会掉到实现的代码丛林中,也不会失掉什么关键点!幸好
Eclipse
有查看一个类、方法实现关系的工具,请按
F4,
看来有个好工具对学习是有好的帮助的,所以千万不要低估工具的力量!另外你看
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
只是取一个对象工厂!也是抽象方法,你可以也按我上面和下面介绍的办法去分析,结果就是一个创建对象工厂实例的逻辑,没有加载
XML
的逻辑!这里就不累述了,
发现这样一个实现关系,父类中有
DefaultResourceLoader,
有
Resource
加载的能力吧?
XML
配置文件不就是一种资源吗?看来靠近了想要到达的地方了,至少不会太远了,于是你想先进去看看,不过我还是建议你看看这个实现关系中的其他类,做到心里有数,至少知道这个地图,不然你一个劲往里钻,没有记不起来如何出来了,尤其是类多了时候,于是我先看了一下上面这个结构,知道下面还有两个
ApplicationContext
实现,
Ok,
先看看这个资源加载器,因为从名字来看更接近我想找的东西!
public class DefaultResourceLoader implements ResourceLoader {
private ClassLoader classLoader;
public DefaultResourceLoader() {
this.classLoader = ClassUtils.getDefaultClassLoader();
}
public DefaultResourceLoader(ClassLoader classLoader) {
this.classLoader = classLoader;
}
public void setClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader;
}
public ClassLoader getClassLoader() {
return (this.classLoader != null ? this.classLoader : ClassUtils.getDefaultClassLoader());
}
public Resource getResource(String location) {
Assert.notNull(location, "Location must not be null");
if (location.startsWith(CLASSPATH_URL_PREFIX)) {
return new ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()), getClassLoader());
}
else {
try {
URL url = new URL(location);
return new UrlResource(url);
}
catch (MalformedURLException ex) {
return getResourceByPath(location);
}
}
}
protected Resource getResourceByPath(String path) {
return new ClassPathContextResource(path, getClassLoader());
}
private static class ClassPathContextResource extends ClassPathResource implements ContextResource {
public ClassPathContextResource(String path, ClassLoader classLoader) {
super(path, classLoader);
}
public String getPathWithinContext() {
return getPath();
}
@Override
public Resource createRelative(String relativePath) {
String pathToUse = StringUtils.applyRelativePath(getPath(), relativePath);
return new ClassPathContextResource(pathToUse, getClassLoader());
}
}
}
好了,我可以肯定的一点是这里是加载
XML
文件的地方,但且不是解析的地方,为什么?精通
Java
的家伙都知道资源加载这回事,也知道
Resource
接口这样的东西干什么用的,从代码上看只是加载资源而已,好了!到此为止,我必须退回去一步了,幸好我之前浏览了一下类实现的结构图,
AbstractApplicationContext
下面有两个
ApplicationContext
实现,当你每次看结构时最好做个笔记,在
ApplicationContext
继承体系中,你也能看到这两个类,这样你就清楚这些类和
FileSystemXmlApplicationContext
相对关系了,也知道和
AbtractApplicationContext
之间是个什么关系了,因为我们在
FileSystemXmlApplicationContext
中发现入口的驱动方法是
Refresh
方法,而
Refresh
方法是在
AbstractApplicationContext
中实现的,而
Refresh
方法调用一个方法来实现加载和解析,而这个解析过程被推迟到子类实现,而
FileSystemXmlApplicationContext
并没有实现,只能是处于它们之间的一个
ApplicationContext
来实现的(有关为什么会有这样一个“复杂”的继承体系
-ApllicationContext
下又有一个
ApplicationContext,
我会慢慢给大家讲清楚,这也和软件的设计思想有关,而且是最朴素的理念!),基于这种分析,我就在
AbstractRefreshableApplicationContext
和
GenericApplicationContext
之间做个抉择!因为
refresh
这个方法名让我联想到可能需要仔细看看
AbstractRefreshableApplicationContext
!另外
FileSystemXmlAppliactionContext
的父类中有
AbstractRefreshableApplicationContext
,从地图中分析,从名称中分析(一般像这样著名开源框架都能遵守很好命名规范,否则就不敢拿出来开源了,会被大家骂死)得到最大的可能性是
AbstractRefreshableApplicationContext
!我们就试着打开看看吧!
终于发现
refreshBeanFactory
方法实现的地方了:
@Override
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
Very good!
逻辑简单并且明了!前面是如果一个
BeanFactory
存在就摧毁之,然后再创建一个,哈哈,也就是说是实例化
ApplicationContext
时实际上一个重启动作,也就是清空
AppliactionContext
缓存的对象(容器倒出所有的水或者东西),而且你发现重新创建的
DefaultListableBeanFactory,
我猜这个也许是
ApplicationContext
其他行为的核心,比如对象创建,依赖注入和
AOP
等等!再往下看,一下子盯住一个方法那就是
loadBeanDefinitions(beanFactory)
,好了,凡是经常用
Spring
的人,都知道
BeanDefinition
是干什么的,就是里面存有对象依赖关系的元数据,而这些元数据都是在
XML
中定义的,我兴高采烈地进入这个方法来看一看:
protected
abstract
void
loadBeanDefinitions
(DefaultListableBeanFactory beanFactory)
throws
BeansException, IOException
;
哈哈,又一次触雷,你可能会问,为什么会这么设计,非得子类去实现吗?这个问题是个设计理念的问题,等我把
IOC
的原理都给你展示清楚,你在解释为什么这么设计,会更有说服力的。
现在看来
loadBeanDefinitions
的实现极大可能是在
AbstractRefreshableApplicationContext
和
FileSystemXmlAppliactionContext
之间的
ApplicationContext!
看来记录一下类继承结构很有用啊!而这个之间,就两个类了:
AbstractRefreshableConfigApplicationContext
和
AbstractXmlApplicationContext,
范围已近很小了,我们这时大可以仔细看看这两个类了看看哪个才是真实现
loadBeanDefinitions
方法的!检视一下,发现,是在
AbstractXmlApplicationContext
中,
@Override
分享到:
相关推荐
《Spring框架核心源代码分析及感悟》 Spring框架作为Java企业级应用开发的基石,其强大的功能和灵活性深受开发者喜爱。深入理解Spring的核心源代码,不仅有助于我们更好地使用这个框架,还能提升我们的编程技艺和对...
Spring5 框架 ---- AOP ---- 代码 Spring5 框架 ---- AOP ---- 代码 Spring5 框架 ---- AOP ---- 代码 Spring5 框架 ---- AOP ---- 代码 Spring5 框架 ---- AOP ---- 代码 Spring5 框架 ---- AOP ---- 代码 Spring5 ...
Spring5 框架 ---- 事务操作 ---- 代码 Spring5 框架 ---- 事务操作 ---- 代码 Spring5 框架 ---- 事务操作 ---- 代码 Spring5 框架 ---- 事务操作 ---- 代码 Spring5 框架 ---- 事务操作 ---- 代码 Spring5 框架 --...
Spring5 框架 ---- IOC容器 ---- 代码 Spring5 框架 ---- IOC容器 ---- 代码 Spring5 框架 ---- IOC容器 ---- 代码 Spring5 框架 ---- IOC容器 ---- 代码 Spring5 框架 ---- IOC容器 ---- 代码 Spring5 框架 ---- ...
JavaEE源代码 spring-toplinkJavaEE源代码 spring-toplinkJavaEE源代码 spring-toplinkJavaEE源代码 spring-toplinkJavaEE源代码 spring-toplinkJavaEE源代码 spring-toplinkJavaEE源代码 spring-toplinkJavaEE源...
JavaEE源代码 spring-coreJavaEE源代码 spring-coreJavaEE源代码 spring-coreJavaEE源代码 spring-coreJavaEE源代码 spring-coreJavaEE源代码 spring-coreJavaEE源代码 spring-coreJavaEE源代码 spring-coreJavaEE源...
JavaEE源代码 spring-jpaJavaEE源代码 spring-jpaJavaEE源代码 spring-jpaJavaEE源代码 spring-jpaJavaEE源代码 spring-jpaJavaEE源代码 spring-jpaJavaEE源代码 spring-jpaJavaEE源代码 spring-jpaJavaEE源代码 ...
JavaEE源代码 spring-jdoJavaEE源代码 spring-jdoJavaEE源代码 spring-jdoJavaEE源代码 spring-jdoJavaEE源代码 spring-jdoJavaEE源代码 spring-jdoJavaEE源代码 spring-jdoJavaEE源代码 spring-jdoJavaEE源代码 ...
JavaEE源代码 spring-daoJavaEE源代码 spring-daoJavaEE源代码 spring-daoJavaEE源代码 spring-daoJavaEE源代码 spring-daoJavaEE源代码 spring-daoJavaEE源代码 spring-daoJavaEE源代码 spring-daoJavaEE源代码 ...
JavaEE源代码 spring-jdbcJavaEE源代码 spring-jdbcJavaEE源代码 spring-jdbcJavaEE源代码 spring-jdbcJavaEE源代码 spring-jdbcJavaEE源代码 spring-jdbcJavaEE源代码 spring-jdbcJavaEE源代码 spring-jdbcJavaEE源...
JavaEE源代码 spring-mockJavaEE源代码 spring-mockJavaEE源代码 spring-mockJavaEE源代码 spring-mockJavaEE源代码 spring-mockJavaEE源代码 spring-mockJavaEE源代码 spring-mockJavaEE源代码 spring-mockJavaEE源...
Spring5 框架 ---- Spring5的新功能 ---- 代码 Spring5 框架 ---- Spring5的新功能 ---- 代码 Spring5 框架 ---- Spring5的新功能 ---- 代码 Spring5 框架 ---- Spring5的新功能 ---- 代码 Spring5 框架 ---- Spring...
JavaEE源代码 spring-ibatisJavaEE源代码 spring-ibatisJavaEE源代码 spring-ibatisJavaEE源代码 spring-ibatisJavaEE源代码 spring-ibatisJavaEE源代码 spring-ibatisJavaEE源代码 spring-ibatisJavaEE源代码 ...
JavaEE源代码 spring-beansJavaEE源代码 spring-beansJavaEE源代码 spring-beansJavaEE源代码 spring-beansJavaEE源代码 spring-beansJavaEE源代码 spring-beansJavaEE源代码 spring-beansJavaEE源代码 spring-...
JavaEE源代码 spring-contextJavaEE源代码 spring-contextJavaEE源代码 spring-contextJavaEE源代码 spring-contextJavaEE源代码 spring-contextJavaEE源代码 spring-contextJavaEE源代码 spring-contextJavaEE源...
Spring的源代码分析,不仅仅是技术层面的学习,更是对软件工程思想的探索。它教会我们如何分析问题,如何利用现有知识系统,如何对待不同的设计理念,以及如何更好地学习和使用工具。这种深入的理解可以帮助我们成长...
JavaEE源代码 struts2-spring-plugin-2.0.11JavaEE源代码 struts2-spring-plugin-2.0.11JavaEE源代码 struts2-spring-plugin-2.0.11JavaEE源代码 struts2-spring-plugin-2.0.11JavaEE源代码 struts2-spring-plugin-...
在"spring框架学习源代码"这个资料中,你将有机会深入理解并实践这些关键概念。 首先,让我们从Spring的IOC(Inversion of Control,控制反转)和DI(Dependency Injection,依赖注入)开始。IOC是指应用程序不再...
通过阅读并分析这些源代码,开发者可以更深入地理解Spring框架的工作机制,学习如何有效地使用其特性来提高代码的可维护性和可扩展性。每个章节都会提供实际的示例,帮助开发者将理论知识转化为实践技能。对于想要...
看透springMvc源代码分析与实践-扫描版本 解压后大小(57.7M) 国内资深Web开发专家根据Spring MVC全新技术撰写,基于实际生产环境,从基础知识、源代码和实战3个维度对Spring MVC的结构和实现进行详细讲解 全面介绍...