spring技术内幕_Spring框架的设计理念与设计模式分析

《深入分析Java Web技术内幕》笔记

13.1、Spring的骨骼架构

Spring框架

786a99d32ad7c835efceb44e1699d8c7.png

Spring框架的核心组件:Core、Bean、Context

13.1.1、Spring的设计理念

设计策略完全类似于Java实现OOP的设计里面,在Spring中没有Bean也就没有Spring存在的意义

13.1.2、核心组件如何协同工作

Bean:演员;Context:演出的舞台背景;Core:演出的道具

对Context来说它就是要发现每个Bean之间的关系,为它们建立这种关系并且维护好这种关系,所以Context就是一个Bean关系的集合,这个关系集合又叫做Ioc容器;

Core就是发现、建立和维护每个Bean之间的关系所需要的一系列工具

Bean、Context和Core之间的关系

af513fca1ec03dc14dddfd6ad3375dc8.png

13.2、核心组件详解

13.2.1、Bean组件

Bean组件在Spring的org.springframework.beans包下,包括:Bean的定义、Bean的创建以及对Bean的解析

Spring Bean的创建是典型的工厂模式

Bean工厂的集成层次关系如下:

fabeaa27d50c107ab5dd13b3ea4307d2.png

BeanFactory有三个子类:ListableBeanFactory(表示Bean是可列表的)、HierarchicalBeanFactory(表示这些Bean是有继承关系的)和AutowireCapableBeanFactory(定义Bean的自动装配规则)

Bean的解析主要就是对Spring配置文件的解析

这个解析过程如下图所示

42ed9a410d24f3273744eee053afc254.png

13.2.2、Context组件

Context在Spring的org.springframework.context包下,给Spring提供一个运行时的环境,用以保存各个对象的状态

Context相关的类结构图

3a8a5814db49b1ce624750383433c5d3.png

ApplicationContext的子类主要包含:

  • ConfigurableApplicationContext

    表示该Context是可修改的,也就是在构建Context中,用户可以动态添加或修改已有的配置信息,子类中AbstractRefreshableApplicationContext类最常用,表示可更新的Context

  • WebApplicationContext

    为Web准备的Context,可以直接访问ServletContext

ApplicationContext需要完成的事情:

  • 标识一个应用环境

  • 利用BeanFactory创建Bean对象

  • 保存对象关系表

  • 能够捕获各种事情

13.2.3、Core组件

Resource相关的类结构图

4e6d482e409bf3de4932b0016f5b2c58.png

Context和Resource的类关系图

dc8fccd6883ce2438ff2fced611ba654.png

Context把资源的加载、解析和描述工作委托给了ResourcePatternResolver类来完成

13.2.4、Ioc容器如何工作

  1. 如何创建BeanFactory

Ioc容器实际上是Context组件结合其他两个组件共同构建一个Bean关系网,这个构建的入口就在AbstractApplicationContext类的refresh方法

public void refresh() throws BeansException, IllegalStateException {    synchronized (this.startupShutdownMonitor) {      // Prepare this context for refreshing.      prepareRefresh();      // Tell the subclass to refresh the internal bean factory.      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();      // Prepare the bean factory for use in this context.      //创建好BeanFactory后,添加一些Spring本身需要的工具类      prepareBeanFactory(beanFactory);      try {        // Allows post-processing of the bean factory in context subclasses.        postProcessBeanFactory(beanFactory);        // Invoke factory processors registered as beans in the context.        //获取实现BeanFactoryPostProcessor接口的子类,并执行它的postProcessBeanFactory方法        invokeBeanFactoryPostProcessors(beanFactory);        // Register bean processors that intercept bean creation.        //获取用户定义的实现了BeanPostProcessor接口的子类,并把它们注册到BeanFactory对象中的BeanPostProcessors变量中        registerBeanPostProcessors(beanFactory);        // Initialize message source for this context.        initMessageSource();        // Initialize event multicaster for this context.        initApplicationEventMulticaster();        // Initialize other special beans in specific context subclasses.        onRefresh();        // Check for listener beans and register them.        registerListeners();        // Instantiate all remaining (non-lazy-init) singletons.        finishBeanFactoryInitialization(beanFactory);        // Last step: publish corresponding event.        finishRefresh();      }      catch (BeansException ex) {        if (logger.isWarnEnabled()) {          logger.warn("Exception encountered during context initialization - " +              "cancelling refresh attempt: " + ex);        }        // Destroy already created singletons to avoid dangling resources.        destroyBeans();        // Reset 'active' flag.        cancelRefresh(ex);        // Propagate exception to caller.        throw ex;      }      finally {        // Reset common introspection caches in Spring's core, since we        // might not ever need metadata for singleton beans anymore...        resetCommonCaches();      }    }  }

这个方法构建整个Ioc容器,主要包含以下步骤:

  • 构建BeanFactory,以便于产生所需的“演员”

  • 注册可能感兴趣的事件

  • 创建Bean实例对象

  • 触发被监听的事件

当BeanFactory已经存在时更新,如果不存在就创建

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);    }  }

BeanFactory的原始对象是DefaultListableBeanFactory

DefaultListableBeanFactory类继承关系图如下:

0d5a8772aa646c5e9ff34b78a7f82d68.png

refreshBeanFactory方法的loadBeanDefinitions(beanFactory)将装载、解析Bean的定义,也就是用户定义的数据结构转化为Ioc容器中的特定数据结构

创建BeanFactory的时序图如下:

b1a4ef4e9197d7dc86939b7e79f2cef8.png

Bean的解析和等级流程时序图如下:

ef36d0e41713d236095859ce0ab786c1.png

2.如何创建Bean实例并构建Bean的关系网

Bean的实例化是从finishBeanFactoryInitialization方法开始的

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {    // Initialize conversion service for this context.    if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&        beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {      beanFactory.setConversionService(          beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));    }    // Register a default embedded value resolver if no bean post-processor    // (such as a PropertyPlaceholderConfigurer bean) registered any before:    // at this point, primarily for resolution in annotation attribute values.    if (!beanFactory.hasEmbeddedValueResolver()) {      beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));    }    // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.    String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);    for (String weaverAwareName : weaverAwareNames) {      getBean(weaverAwareName);    }    // Stop using the temporary ClassLoader for type matching.    beanFactory.setTempClassLoader(null);    // Allow for caching all bean definition metadata, not expecting further changes.    beanFactory.freezeConfiguration();    // Instantiate all remaining (non-lazy-init) singletons.    beanFactory.preInstantiateSingletons();  }

Bean的实例化是在BeanFactory中发生的,preInstantiateSingletons()方法

public void preInstantiateSingletons() throws BeansException {    if (logger.isTraceEnabled()) {      logger.trace("Pre-instantiating singletons in " + this);    }    // Iterate over a copy to allow for init methods which in turn register new bean definitions.    // While this may not be part of the regular factory bootstrap, it does otherwise work fine.    List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);    // Trigger initialization of all non-lazy singleton beans...    for (String beanName : beanNames) {      RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);      if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {        if (isFactoryBean(beanName)) {          Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);          if (bean instanceof FactoryBean) {            final FactoryBean> factory = (FactoryBean>) bean;            boolean isEagerInit;            if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {              isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)                      ((SmartFactoryBean>) factory)::isEagerInit,                  getAccessControlContext());            }            else {              isEagerInit = (factory instanceof SmartFactoryBean &&                  ((SmartFactoryBean>) factory).isEagerInit());            }            if (isEagerInit) {              getBean(beanName);            }          }        }        else {          getBean(beanName);        }      }    }    // Trigger post-initialization callback for all applicable beans...    for (String beanName : beanNames) {      Object singletonInstance = getSingleton(beanName);      if (singletonInstance instanceof SmartInitializingSingleton) {        final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;        if (System.getSecurityManager() != null) {          AccessController.doPrivileged((PrivilegedAction<Object>) () -> {            smartSingleton.afterSingletonsInstantiated();            return null;          }, getAccessControlContext());        }        else {          smartSingleton.afterSingletonsInstantiated();        }      }    }  }

FactoryBean是个工厂Bean,可以产生Bean的Bean,这里的产生Bean是指Bean的实例,如果一个类继承FactoryBean,用户可以自己定义产生实例对象的方法,只需实现它的getObject方法即可

如何创建Bean的实例

e3167ff96098b50b54da669f6896899c.png

如果是普通的Bean就通过调用getBean方法直接创建它的实例

e6ffb9697df904c057ee8ffb7c1a1780.png

建立Bean对象实例之间的关系

5dd6144c0c89caa03ef000fbe28116ae.png

  1. Ioc容器的扩展点

    BeanFactoryPostProcessor和BeanPostProcessor,分别构建BeanFactory和构建Bean对象时调用;

    InitializingBean和DisposableBean,分别在Bean创建和销毁时调用;

    这些扩展点就是使用Spring来完成特定任务的地点

  2. Ioc容器如何为我所用

    Spring必须要先构建Ioc容器,没有它Spring无法工作,ApplicationContext.xml就是Ioc容器的默认文件,Spring的所有特性功能都是基于Ioc容器工作的

13.3、Spring中AOP详解

13.3.1、动态代理的实现原理

AOP是基于动态代理实现的

Proxy类是构造代理类的入口

Proxy的类结构图如下

5510fe1664340dce5d35299b2f1311de.png

Proxy产生代理类的过程

33646f373738f5757314201d55a4335c.png

13.3.2、SpringAOP如何实现

代理的目的是调用目标方法时可以转而执行InvocationHandler类的invoke方法

JDK动态代理的类图

549c1e49613cf6d240505802f09744b8.png

Spring创建代理对象的时序图

edbb4e12df26ff3ce0098b51df952b9f.png

Spring调用拦截器

12710e622f752215ffa39b8872bad021.png

13.4、Spring中的设计模式

  1. 代理模式(proxy)

    SpringAOP中JDK动态代理就是利用代理模式技术实现的。在Spring中除了实现被代理对象的接口外,还有org.springframework.aop.SpringProxy和org.springdframework.aop.framework.Advised两个接口

Spring中使用代理模式的结构图

8400bb12da4ecc65ffbb96f0e1e55b1c.png

  1. 策略模式(Strategy)

Spring中策略模式结构图

d95f0f64f621aaa92f5e2891bd069826.png

  1. 简单工厂模式

    spring中的BeanFactory就是简单工厂模式的体现

  2. 工厂方法(Factory Method)

    通常由应用程序直接使用new创建新的对象,为了将对象的创建和使用相分离,采用工厂模式,即应用程序将对象的创建及初始化职责交给工厂对象;

    一般情况下,应用程序有自己的工厂对象来创建bean.如果将应用程序自己的工厂对象交给Spring管理,那么Spring管理的就不是普通的bean,而是工厂Bean

  3. 单例模式(Singleton)

    保证一个类仅有一个实例,并提供一个访问它的全局访问点。;spring中的单例模式完成了后半句话,即提供了全局的访问点BeanFactory。但没有从构造器级别去控制单例,这是因为spring管理的是是任意的java对象。;

  4. 适配器模式(Adapter)

    在Spring的Aop中,使用的Advice(通知)来增强被代理类的功能。Spring实现这一AOP功能的原理就使用代理模式(1、JDK动态代理。2、CGLib字节码生成技术代理。)对类进行方法级别的切面增强,即,生成被代理类的代理类, 并在代理类的方法前,设置拦截器,通过执行拦截器的内容增强了代理方法的功能,实现的面向切面编程

  5. 包装器(Decorator)

    Spring中用到的包装器模式在类名上有两种表现:一种是类名中含有Wrapper,另一种是类名中含有Decorator。基本上都是动态地给一个对象添加一些额外的职责

  6. 观察者(Observer)

    定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新,Spring中Observer模式常用的地方是listener的实现。如ApplicationListener

  7. 模版方法(Template Method)

    定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。Template Method使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。Template Method模式一般是需要继承的。这里想要探讨另一种对Template Method的理解。spring中的JdbcTemplate,在用这个类时并不想去继承这个类,因为这个类的方法太多,但是我们还是想用到JdbcTemplate已有的稳定的、公用的数据库连接,那么我们怎么办呢?我们可以把变化的东西抽出来作为一个参数传入JdbcTemplate的方法中。但是变化的东西是一段代码,而且这段代码会用到JdbcTemplate中的变量。怎么办?那我们就用回调对象吧。在这个回调对象中定义一个操纵JdbcTemplate中变量的方法,我们去实现这个方法,就把变化的东西集中到这里了。然后我们再传入这个回调对象到JdbcTemplate,从而完成了调用。这可能是Template Method不需要继承的另一种实现方式吧。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值