13 Spring框架的设计理念和设计模式分析

  • 13.1 Spring的骨骼架构

    Spring的核心组件有3个:Core、Context、Bean

    Bean包装的是Object

    Context是一个Bean的关系集合(又叫IoC容器)

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

     

    13.2 核心组件详解

    13.2.1 Bean组件

    Spring Bean组件在org.springframework.beans包下,该包主要解决:Bean的定义、创建(关注)、解析

    1. 创建

    Bean创建采用的是工厂模式,他的顶级接口是BeanFactory。BeanFactory一共有3个子类ListableBeanFactory、HierarchicalBeanFactory 和 AutowireCapableBeanFactory。最终实现类是DefaultListableBeanFactory。如此多的接口主要是区分Spring内部操作过程中对象的传递和转化过程中,对对象的数据访问所做的限制。

    ListableBeanFactory:表示Bean是可列表的,Bean的集合

    HierachicalBeanFactory:表示Bean是有继承关系的,即每个Bean可能有父Bean,Bean之间的关系

    AutowireCapableBeanFactory:定义Bean的自动装配规则,Bean的行为。

     

     

    1. 定义

    Bean的定义由BeanDefinition描述,XML配置文件中的<bean>的配置信息转化成RootDefinition对象

     

     

    1. 解析

    Bean的解析主要是对XML配置文件的解析。

     

     

    13.2.2 Context组件

    Context组件就是给Spring提供一个运行时的环境,用以保存各个对象的状态

    ApplicationContext继承BeanFactory,spring中运行的主体对象是Bean,继承了ResourceLoader接口,使得ApplicationContext可以访问外部资源

    ApplicationContext子类主要包含

    1. ConfigurableApplicationContext ,用户可以动态添加修改已有的配置信息
    2. WebApplicationContext,可以直接访问Servlet,用的很少

    ApplicationContext主要完成

    • 标识一个应用环境
    • 利用BeanFactory创建Bean对象
    • 保存对象关系表
    • 能够捕获各种事件

     

    13.2.3 Core组件

    Core定义了资源的访问方式,他屏蔽了文件类型,资源提供者,加载者之间的差异

     

    13.3 IOC如何工作

    IOC容器实际上是根据Context组件结合Bean和Core组件构建一个Bean的关系网。

    构建过程:

    1. 构建BeanFactory,便于产生Bean
    2. 注册可能感兴趣的事件
    3. 创建Bean实例对象
    4. 出发被监听的事件

     

    13.4 AOP特性详解

    13.4.1 动态代理

    AOP是基于动态代理实现的。

    JDK中动态代理方面有一个newProxyInstance方法:

    ClassLoader:传入加载代理类的Loader类

    IInterfaces:要被代理的接口

    InvocationHandler:除了被代理接口中的方法之外用户自定义的操作

    用户调用的目标方法都被调用到InvocationHandler类中定义的唯一方法invoke中

    public static Object newProxyInstance(ClassLoader loader,  Class<?>[] interfaces,InvocationHandler h)  throws IllegalArgumentException

     

    清单 7. SimpleProxy 类

    public interface SimpleProxy {

    public void simpleMethod1();
            
        public void simpleMethod2();

    }

    代理来生成的类结构如下:

    清单 8. $Proxy2 类

    public class $Proxy2 extends java.lang.reflect.Proxy implements SimpleProxy{
        java.lang.reflect.Method m0;
        java.lang.reflect.Method m1;
        java.lang.reflect.Method m2;
        java.lang.reflect.Method m3;
        java.lang.reflect.Method m4;

        int hashCode();
        boolean equals(java.lang.Object);
        java.lang.String toString();
        void simpleMethod1();
        void simpleMethod2();
    }

    代理类中每个方法对应一个属性变量,作为invoke的传参调用。

     

     

     

    配置代理类 Bean

    要实现AOP需要下面这样配置一个Bean

    <bean id="testBeanSingleton"

        class="org.springframework.aop.framework.ProxyFactoryBean">

        <property name="proxyInterfaces">

            <value>

                org.springframework.aop.framework.PrototypeTargetTests$TestBean

            </value>

        </property>

        <property name="target"><ref local="testBeanTarget"></ref> </property>

        <property name="singleton"><value>true</value></property>

        <property name="interceptorNames">

            <list>

                <value>testInterceptor</value>

                <value>testInterceptor2</value>

            </list>

        </property>

    </bean>

     

    Spring生成动态代理对象

     

    动态调用拦截器的方法

     

    Spring 中设计模式分析

    Spring 中使用的设计模式也很多,比如工厂模式、单例模式、模版模式等,在《 Webx 框架的系统架构与设计模式》、《 Tomcat 的系统架构与模式设计分析》已经有介绍,这里就不赘述了。这里主要介绍代理模式和策略模式。

    代理模式

    代理模式原理

    代理模式就是给某一个对象创建一个代理对象,而由这个代理对象控制对原对象的引用,而创建这个代理对象就是可以在调用原对象是可以增加一些额外的操作。下面是代理模式的结构:

    图 21. 代理模式的结构

    • Subject:抽象主题,它是代理对象的真实对象要实现的接口,当然这可以是多个接口组成。
    • ProxySubject:代理类除了实现抽象主题定义的接口外,还必须持有所代理对象的引用
    • RealSubject:被代理的类,是目标对象。

    Spring 中如何实现代理模式

    Spring Aop 中 Jdk 动态代理就是利用代理模式技术实现的。在 Spring 中除了实现被代理对象的接口外,还会有 org.springframework.aop.SpringProxy 和 org.springframework.aop.framework.Advised 两个接口。Spring 中使用代理模式的结构图如下:

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

    $Proxy 就是创建的代理对象,而 Subject 是抽象主题,代理对象是通过 InvocationHandler 来持有对目标对象的引用的。

    Spring 中一个真实的代理对象结构如下:

    清单 10 代理对象 $Proxy4

    public class $Proxy4 extends java.lang.reflect.Proxy implements
        org.springframework.aop.framework.PrototypeTargetTests$TestBean
            org.springframework.aop.SpringProxy
            org.springframework.aop.framework.Advised
    {
        java.lang.reflect.Method m16;
        java.lang.reflect.Method m9;
        java.lang.reflect.Method m25;
        java.lang.reflect.Method m5;
        java.lang.reflect.Method m2;
        java.lang.reflect.Method m23;
        java.lang.reflect.Method m18;
        java.lang.reflect.Method m26;
        java.lang.reflect.Method m6;
        java.lang.reflect.Method m28;
        java.lang.reflect.Method m14;
        java.lang.reflect.Method m12;
        java.lang.reflect.Method m27;
        java.lang.reflect.Method m11;
        java.lang.reflect.Method m22;
        java.lang.reflect.Method m3;
        java.lang.reflect.Method m8;
        java.lang.reflect.Method m4;
        java.lang.reflect.Method m19;
        java.lang.reflect.Method m7;
        java.lang.reflect.Method m15;
        java.lang.reflect.Method m20;
        java.lang.reflect.Method m10;
        java.lang.reflect.Method m1;
        java.lang.reflect.Method m17;
        java.lang.reflect.Method m21;
        java.lang.reflect.Method m0;
        java.lang.reflect.Method m13;
        java.lang.reflect.Method m24;

    int hashCode();
        int indexOf(org.springframework.aop.Advisor);
        int indexOf(org.aopalliance.aop.Advice);
        boolean equals(java.lang.Object);
        java.lang.String toString();
        void sayhello();
        void doSomething();
        void doSomething2();
        java.lang.Class getProxiedInterfaces();
        java.lang.Class getTargetClass();
        boolean isProxyTargetClass();
        org.springframework.aop.Advisor; getAdvisors();
        void addAdvisor(int, org.springframework.aop.Advisor)
                    throws org.springframework.aop.framework.AopConfigException;
        void addAdvisor(org.springframework.aop.Advisor)
                    throws org.springframework.aop.framework.AopConfigException;
        void setTargetSource(org.springframework.aop.TargetSource);
        org.springframework.aop.TargetSource getTargetSource();
        void setPreFiltered(boolean);
        boolean isPreFiltered();
        boolean isInterfaceProxied(java.lang.Class);
        boolean removeAdvisor(org.springframework.aop.Advisor);
        void removeAdvisor(int)throws org.springframework.aop.framework.AopConfigException;
        boolean replaceAdvisor(org.springframework.aop.Advisor,
                    org.springframework.aop.Advisor)
                    throws org.springframework.aop.framework.AopConfigException;
        void addAdvice(org.aopalliance.aop.Advice)
                    throws org.springframework.aop.framework.AopConfigException;
        void addAdvice(int, org.aopalliance.aop.Advice)
                    throws org.springframework.aop.framework.AopConfigException;
        boolean removeAdvice(org.aopalliance.aop.Advice);
        java.lang.String toProxyConfigString();
        boolean isFrozen();
        void setExposeProxy(boolean);
        boolean isExposeProxy();
    }

    策略模式

    策略模式原理

    策略模式顾名思义就是做某事的策略,这在编程上通常是指完成某个操作可能有多种方法,这些方法各有千秋,可能有不同的适应的场合,然而这些操作方法都有可能用到。各一个操作方法都当作一个实现策略,使用者可能根据需要选择合适的策略。

    下面是策略模式的结构:

    图 23. 策略模式的结构

    • Context:使用不同策略的环境,它可以根据自身的条件选择不同的策略实现类来完成所要的操作。它持有一个策略实例的引用。创建具体策略对象的方法也可以由他完成。
    • Strategy:抽象策略,定义每个策略都要实现的策略方法
    • ConcreteStrategy:具体策略实现类,实现抽象策略中定义的策略方法

    Spring 中策略模式的实现

    Spring 中策略模式使用有多个地方,如 Bean 定义对象的创建以及代理对象的创建等。这里主要看一下代理对象创建的策略模式的实现。

    前面已经了解 Spring 的代理方式有两个 Jdk 动态代理和 CGLIB 代理。这两个代理方式的使用正是使用了策略模式。它的结构图如下所示:

    图 24. Spring 中策略模式结构图

    在上面结构图中与标准的策略模式结构稍微有点不同,这里抽象策略是 AopProxy 接口,Cglib2AopProxy 和 JdkDynamicAopProxy 分别代表两种策略的实现方式,ProxyFactoryBean 就是代表 Context 角色,它根据条件选择使用 Jdk 代理方式还是 CGLIB 方式,而另外三个类主要是来负责创建具体策略对象,ProxyFactoryBean 是通过依赖的方法来关联具体策略对象的,它是通过调用策略对象的 getProxy(ClassLoader classLoader) 方法来完成操作。

     

    来自 <http://www.ibm.com/developerworks/cn/java/j-lo-spring-principle/>

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值