truevalue>property>
testInterceptorvalue>
testInterceptor2value>
list>
property>
bean>
配置上看到要设置被代理的接口,和接口的实现类也就是目标类,以及拦截器也就在执行目标方法之前被调用,这里Spring中定义的各种各样的拦截器,可以选择使用。
下面看看Spring如何完成了代理以及是如何调用拦截器的。
前面提到Spring Aop也是实现其自身的扩展点来完成这个特性的,从这个代理类可以看出它正是继承了Factory Bean的ProxyFactoryBean,FactoryBean之所以特别就在它可以让你自定义对象的创建 方法。当然代理对象要通过Proxy类来动态生成。
下面是Spring创建的代理对象的时序图:
图19.Spring代理对象的产生
Spring创建了代理对象后,当你调用目标对象上的方法时,将都会被代理到InvocationHandler类的invoke方法中执行,这在前面已经解释。在这里JdkDynamicAopProxy类实现了InvocationHandler接 口。
下面再看看Spring是如何调用拦截器的,下面是这个过程的时序图:
图20.Spring调用拦截器
以上所说的都是Jdk动态代理,Spring还支持一种CGLIB类代理,感兴趣自己看吧。
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;