`
leogao_emcom
  • 浏览: 83249 次
  • 性别: Icon_minigender_1
  • 来自: 大连
社区版块
存档分类
最新评论

Spring框架核心源代码的分析及其感受-2

阅读更多

呵呵,无论从调用关系、方法名称和注释都能敏感的感觉到找对地方了, 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

 

2
1
分享到:
评论

相关推荐

    Spring框架核心源代码的分析及其感受-6

    《Spring框架核心源代码分析及感悟》 Spring框架作为Java企业级应用开发的基石,其强大的功能和灵活性深受开发者喜爱。深入理解Spring的核心源代码,不仅有助于我们更好地使用这个框架,还能提升我们的编程技艺和对...

    Spring5 框架 ---- AOP ---- 代码

    Spring5 框架 ---- AOP ---- 代码 Spring5 框架 ---- AOP ---- 代码 Spring5 框架 ---- AOP ---- 代码 Spring5 框架 ---- AOP ---- 代码 Spring5 框架 ---- AOP ---- 代码 Spring5 框架 ---- AOP ---- 代码 Spring5 ...

    Spring5 框架 ---- 事务操作 ---- 代码

    Spring5 框架 ---- 事务操作 ---- 代码 Spring5 框架 ---- 事务操作 ---- 代码 Spring5 框架 ---- 事务操作 ---- 代码 Spring5 框架 ---- 事务操作 ---- 代码 Spring5 框架 ---- 事务操作 ---- 代码 Spring5 框架 --...

    Spring5 框架 ---- IOC容器 ---- 代码

    Spring5 框架 ---- IOC容器 ---- 代码 Spring5 框架 ---- IOC容器 ---- 代码 Spring5 框架 ---- IOC容器 ---- 代码 Spring5 框架 ---- IOC容器 ---- 代码 Spring5 框架 ---- IOC容器 ---- 代码 Spring5 框架 ---- ...

    JavaEE源代码 spring-toplink

    JavaEE源代码 spring-toplinkJavaEE源代码 spring-toplinkJavaEE源代码 spring-toplinkJavaEE源代码 spring-toplinkJavaEE源代码 spring-toplinkJavaEE源代码 spring-toplinkJavaEE源代码 spring-toplinkJavaEE源...

    JavaEE源代码 spring-core

    JavaEE源代码 spring-coreJavaEE源代码 spring-coreJavaEE源代码 spring-coreJavaEE源代码 spring-coreJavaEE源代码 spring-coreJavaEE源代码 spring-coreJavaEE源代码 spring-coreJavaEE源代码 spring-coreJavaEE源...

    JavaEE源代码 spring-jpa

    JavaEE源代码 spring-jpaJavaEE源代码 spring-jpaJavaEE源代码 spring-jpaJavaEE源代码 spring-jpaJavaEE源代码 spring-jpaJavaEE源代码 spring-jpaJavaEE源代码 spring-jpaJavaEE源代码 spring-jpaJavaEE源代码 ...

    JavaEE源代码 spring-jdo

    JavaEE源代码 spring-jdoJavaEE源代码 spring-jdoJavaEE源代码 spring-jdoJavaEE源代码 spring-jdoJavaEE源代码 spring-jdoJavaEE源代码 spring-jdoJavaEE源代码 spring-jdoJavaEE源代码 spring-jdoJavaEE源代码 ...

    JavaEE源代码 spring-dao

    JavaEE源代码 spring-daoJavaEE源代码 spring-daoJavaEE源代码 spring-daoJavaEE源代码 spring-daoJavaEE源代码 spring-daoJavaEE源代码 spring-daoJavaEE源代码 spring-daoJavaEE源代码 spring-daoJavaEE源代码 ...

    JavaEE源代码 spring-jdbc

    JavaEE源代码 spring-jdbcJavaEE源代码 spring-jdbcJavaEE源代码 spring-jdbcJavaEE源代码 spring-jdbcJavaEE源代码 spring-jdbcJavaEE源代码 spring-jdbcJavaEE源代码 spring-jdbcJavaEE源代码 spring-jdbcJavaEE源...

    JavaEE源代码 spring-mock

    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 框架 ---- Spring5的新功能 ---- 代码 Spring5 框架 ---- Spring...

    JavaEE源代码 spring-ibatis

    JavaEE源代码 spring-ibatisJavaEE源代码 spring-ibatisJavaEE源代码 spring-ibatisJavaEE源代码 spring-ibatisJavaEE源代码 spring-ibatisJavaEE源代码 spring-ibatisJavaEE源代码 spring-ibatisJavaEE源代码 ...

    JavaEE源代码 spring-beans

    JavaEE源代码 spring-beansJavaEE源代码 spring-beansJavaEE源代码 spring-beansJavaEE源代码 spring-beansJavaEE源代码 spring-beansJavaEE源代码 spring-beansJavaEE源代码 spring-beansJavaEE源代码 spring-...

    JavaEE源代码 spring-context

    JavaEE源代码 spring-contextJavaEE源代码 spring-contextJavaEE源代码 spring-contextJavaEE源代码 spring-contextJavaEE源代码 spring-contextJavaEE源代码 spring-contextJavaEE源代码 spring-contextJavaEE源...

    Spring框架核心源代码的分析及其感受.pdf

    Spring的源代码分析,不仅仅是技术层面的学习,更是对软件工程思想的探索。它教会我们如何分析问题,如何利用现有知识系统,如何对待不同的设计理念,以及如何更好地学习和使用工具。这种深入的理解可以帮助我们成长...

    JavaEE源代码 struts2-spring-plugin-2.0.11

    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框架学习源代码"这个资料中,你将有机会深入理解并实践这些关键概念。 首先,让我们从Spring的IOC(Inversion of Control,控制反转)和DI(Dependency Injection,依赖注入)开始。IOC是指应用程序不再...

    spring核心技术源代码spring核心技术源代码1-9章

    通过阅读并分析这些源代码,开发者可以更深入地理解Spring框架的工作机制,学习如何有效地使用其特性来提高代码的可维护性和可扩展性。每个章节都会提供实际的示例,帮助开发者将理论知识转化为实践技能。对于想要...

    看透springMvc源代码分析与实践-扫描版本

    看透springMvc源代码分析与实践-扫描版本 解压后大小(57.7M) 国内资深Web开发专家根据Spring MVC全新技术撰写,基于实际生产环境,从基础知识、源代码和实战3个维度对Spring MVC的结构和实现进行详细讲解 全面介绍...

Global site tag (gtag.js) - Google Analytics