zoukankan      html  css  js  c++  java
  • Spring源码学习笔记(十一、阶段总结)

    学了一段时间的Spring源码,有些感触,虽然谈不上感触颇深但也有些体会,今天我把一些个人的感触记下来(才读了冰山一角,哈哈哈哈哈哈)。

    1、面向接口编程

    哎,这其实没啥好说的,这不是常态么。

    但我个人认为有扩展可能的程序才需要定义接口,向那些短期内不会变化或变化维度过大,我个人认为最好不要定义接口吧(仅针对业务开发)。

    因为你根本不知道需求会怎么变,你完全可以之后再重构,持续重构不香嘛。

    当然如果是框架开发的话,需求还是比较明确的,使用面向接口编程还是很香的。

    2、最小知道原则

    通过阅读Spring源码后,我发现很多关键且通用的函数时无参的居多。

    就比如Spring的核心refresh函数,其内部很多关键流程的代码就是无参的,有的话也只是一个factory,说明Spring封装做的非常好,只要把bean实例化出来后,很多东西就能够通过属性值来获取了。

     1 @Override
     2 public void refresh() throws BeansException, IllegalStateException {
     3     synchronized (this.startupShutdownMonitor) {
     4         // Prepare this context for refreshing.
     5         prepareRefresh();
     6 
     7         // Tell the subclass to refresh the internal bean factory.
     8         ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
     9 
    10         // Prepare the bean factory for use in this context.
    11         prepareBeanFactory(beanFactory);
    12 
    13         try {
    14             // Allows post-processing of the bean factory in context subclasses.
    15             postProcessBeanFactory(beanFactory);
    16 
    17             // Invoke factory processors registered as beans in the context.
    18             invokeBeanFactoryPostProcessors(beanFactory);
    19 
    20             // Register bean processors that intercept bean creation.
    21             registerBeanPostProcessors(beanFactory);
    22 
    23             // Initialize message source for this context.
    24             initMessageSource();
    25 
    26             // Initialize event multicaster for this context.
    27             initApplicationEventMulticaster();
    28 
    29             // Initialize other special beans in specific context subclasses.
    30             onRefresh();
    31 
    32             // Check for listener beans and register them.
    33             registerListeners();
    34 
    35             // Instantiate all remaining (non-lazy-init) singletons.
    36             finishBeanFactoryInitialization(beanFactory);
    37 
    38             // Last step: publish corresponding event.
    39             finishRefresh();
    40         }
    41 
    42         catch (BeansException ex) {
    43             if (logger.isWarnEnabled()) {
    44                 logger.warn("Exception encountered during context initialization - " +
    45                         "cancelling refresh attempt: " + ex);
    46             }
    47 
    48             // Destroy already created singletons to avoid dangling resources.
    49             destroyBeans();
    50 
    51             // Reset 'active' flag.
    52             cancelRefresh(ex);
    53 
    54             // Propagate exception to caller.
    55             throw ex;
    56         }
    57 
    58         finally {
    59             // Reset common introspection caches in Spring's core, since we
    60             // might not ever need metadata for singleton beans anymore...
    61             resetCommonCaches();
    62         }
    63     }
    64 }

    这点和推崇的充血模型还是比较像的,这种模型的开发方式可以让你在不了解系统整体的情况下,可以快速知道相关模块的业务逻辑。

    当然这只适用于具有一定规模的系统,如果是小项目还是用贫血模型比较舒服,开发起来比较简单。

    3、设计模式的灵活运用

    哎,这点就不用说了吧,人尽皆知了,哈哈哈哈。

    设计模式这个东西也需要你有长期的开发经验才能更深层次的体会。

    4、接口定义

    emmmmmmm,我其实想说单一职责的,但这个好像大伙都知道哦。

    Spring的接口定义是非常简单的,一个接口该干什么就干什么,没有多余的定义,而需要扩展的话会再次定义。

    如BeanFactory就是定义bean的相关操作,对父容器的扩展是通过HierarchicalBeanFactory接口来定义的。

    这里要学学,而不是一开始就把接口定义的很模糊,然后往里面加一大堆东西,哈哈哈哈哈哈。

    5、解决问题思路

    循环依赖

    循环依赖就是A依赖B,B又依赖A;因为在实例化A的时候需要用到B,所以肯定会先去把B实例化好,然后又发现B要实例化的时候又需要B,这样就形成了一个死循环。

    既然会出现死循环,那么我们要解决的问题就是找到死循环的退出条件,这样循环依赖的问题不就迎刃而解了嘛(这就是解决问题的思路)。

    那么Spring是如何解决循环依赖的呢,首先我们想想如果两个bean都是通过构造函数注入的话,肯定就是不行的,因为这样两个bean就都没办法实例化了,拿不到对方的对象。那么我们能不能先值注入只完成了实例化的bean呢,当然可以,而Spring也是这样做的。

    Spring是提前暴露刚完成构造函数注入而未完成其它步骤(如setter注入)的bean来解决循环依赖的问题,采用了三级缓存实现,即singletonObjects、earlySingletonObjects和singletonFactories

    6、等等等等。。。。。。。

  • 相关阅读:
    vim使用
    linux下编译openjdk8
    《鸟哥的Linux私房菜》学习笔记(9)——条件判断
    《鸟哥的Linux私房菜》学习笔记(8)——bash脚本编程之变量
    《鸟哥的Linux私房菜》学习笔记(7)——grep及正则表达式
    《鸟哥的Linux私房菜》学习笔记(6)——管道及IO重定向
    《鸟哥的Linux私房菜》学习笔记(5)——权限管理
    《鸟哥的Linux私房菜》学习笔记(4)——用户和组
    《鸟哥的Linux私房菜》学习笔记(0)——磁盘与文件系统管理
    Intellij Idea 创建JavaWeb项目
  • 原文地址:https://www.cnblogs.com/bzfsdr/p/13054069.html
Copyright © 2011-2022 走看看