设计模式--代理模式

adt126 贡献于2014-01-20

作者 微软用户  创建于2010-06-22 06:31:00   修改者微软用户  修改于2010-06-22 06:50:00字数100937

文档摘要:代理模式代理模式:给某一对象提供代理对象,并由代理对象控制具体对象的引用.代理,指的就是一个角色代表另一个角色采取行动,就象生活中,一个红酒厂商,是不会直接把红酒零售客户的,都是通过代理来完成他的销售业务的.而客户,也不用为了喝红酒而到处找工厂,他只要找到厂商在当地的代理就行了,具体红酒工厂在那里,客户不用关心,代理会帮他处理.代理模式涉及的角色:1:抽象主题角色.
关键词:

1 代理模式 代理模式:给某一对象提供代理对象,并由代理对象控制具体对象的引用. 代理,指的就是一个角色代表另一个角色采取行动,就象生活中,一个红酒厂商,是不会直接把红酒零售客户的,都是通过代理来完成他的销售业务的.而客户,也不用为了喝红酒而到处找工厂,他只要找到厂商在当地的代理就行了,具体红酒工厂在那里,客户不用关心,代理会帮他处理. 代理模式涉及的角色: 1:抽象主题角色.声明了代理主题和真实主题的公共接口,使任何需要真实主题的地方都能用代理主题代替. 2:代理主题角色.含有真实主题的引用,从而可以在任何时候操作真实主题,代理主题功过提供和真实主题相同的接口,使它可以随时代替真实主题.代理主题通过持有真实主题的引用,不但可以控制真实主题的创建或删除,可以在真实主题被调用前进行拦截,或在调用后进行某些操作. 3:真实代理对象.定义了代理角色所代表的具体对象. 下面是代理模式的实现类图: 根据上图的关系,我们可以用客户买红酒来模拟代理模式的实现, 红酒代理商和红酒厂商都有销售红酒的只能,我们可以为他们定义一个共同的抽象主题角色, Java代码 1. /**   2. *抽象主题角色,定义了真实角色和代理角色的公共接口   3. */   4. public interface SellInterface{    5.      public Object sell();    6. }   /** *抽象主题角色,定义了真实角色和代理角色的公共接口 */ public interface SellInterface{ public Object sell(); } 接着,我们定义真实主题角色(这里就是红酒工厂),它必须实现了SellInterface接口的. Java代码 1. /**   2. *真实主题角色,这里指红酒工厂角色,它实现了SellInterface接口   3. */   4. public class RedWineFactory implements SellInterface{    5.      public Object sell(){    6.          System.out.println("真实主题角色RedWineFactory 被调用了");    7.          return new Object();    8.      }    9. }   /** *真实主题角色,这里指红酒工厂角色,它实现了SellInterface接口 */ public class RedWineFactory implements SellInterface{ public Object sell(){ System.out.println("真实主题角色RedWineFactory 被调用了"); return new Object(); } } 下面是代理主题角色(这里指红酒代理商),同样,代理主题也必须实现SellInterface接口. Java代码 1. /**   2. *代理主题角色,这里指红酒代理商.它除了也要实现了sellInterface接口外,还持有红酒   3. *厂商RedWineFactory 对象的引用,从而使它能在调用真实主题前后做一些必要处理.   4. */   5. public class RedWineProxy implements SellInterface{    6.      //持有一个RedWineFactory对象的引用    7.       private RedWineFactory redWineFactory;    8.    9.      //销售总量    10.       private static int sell_count = 0;    11.    12.      public Object sell(){    13.          if(checkUser()){//在通过代理主题角色,我们可以在真实主题角色被调用前做一些诸如权限判断的事情    14.              Object obj = redWineFactory.sell();    15.              count ++;//同样,在调用后我们也可以执行一些额外的动作.    16.              return obj ;    17.          }else{    18.              throw new RuntimeException();    19.          }    20.      }    21.    22.      protected boolean checkUser(){    23.             //do something    24.             return true;    25.      }    26. }   /** *代理主题角色,这里指红酒代理商.它除了也要实现了sellInterface接口外,还持有红酒 *厂商RedWineFactory 对象的引用,从而使它能在调用真实主题前后做一些必要处理. */ public class RedWineProxy implements SellInterface{ //持有一个RedWineFactory对象的引用 private RedWineFactory redWineFactory; //销售总量 private static int sell_count = 0; public Object sell(){ if(checkUser()){//在通过代理主题角色,我们可以在真实主题角色被调用前做一些诸如权限判断的事情 Object obj = redWineFactory.sell(); count ++;//同样,在调用后我们也可以执行一些额外的动作. return obj ; }else{ throw new RuntimeException(); } } protected boolean checkUser(){ //do something return true; } } 接下来看看调用代理对象的代码 Java代码 1. public static void main(String agr[])    2. {    3.      SellInterface sell = new RedWineProxy();    4.      sell.sell();    5. }   public static void main(String agr[]) { SellInterface sell = new RedWineProxy(); sell.sell(); } 从上面的例子可以看出代理模式的工作方式,首先,因为代理主题和真实主题都实现了共同的接口,这使我们可以在不改变原来接口的情况下,只要用真实主题对象的地方,都可以用代理主题来代替.其次,代理主题在客户和真实主题之间起了一个中介作用,利用这个中介平台,我们可以在把客户请求传递给真实主题之前,做一些必要的预处理. java对代理模式的支持 ---动态代理 上面的代理,我们强迫代理类RedWineProxy实现了抽象接口SellInterface.这导致我们的代理类无法通用于其他接口,所以不得不为每一个接口实现一个代理 类.幸好,java为代理模式提供了支持. java主要是通过Proxy类和InvocationHandler接口来给实现对代理模式的支持的. 下面用java的代理机制来实现上面的例子 Java代码 1. import java.lang.reflect.InvocationHandler;    2. import java.lang.reflect.Method;    3. import java.lang.reflect.Proxy;    4. /**   5. *代理类一定要实现了InvocationHandler接口   6. */   7. public class ProxyObject implements InvocationHandler{    8.     private Object proxy_obj;    9.    10.     ProxyObject(Object obj){    11.         this.proxy_obj = obj;    12.     }    13.    14.     public static Object factory(Object obj){    15.         Class cls = obj.getClass();    16.         //通过Proxy类的newProxyInstance方法来返回代理对象    17.         return Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(),new ProxyObject(obj));    18.     }    19.    20. /**   21. *实现InvocationHandler接口的invoke   22. */   23.     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {    24.         System.out.println("函数调用前被拦截了:   " + method);    25.         if(args != null){    26.             //打印参数列表    27.             System.out.println("方法有  " + args.length + "    个参数");    28.             for(int i = 0; i < args.length; i ++){    29.                 System.out.println(args[i]);    30.             }    31.         }    32.         //利用反射机制动态调用原对象的方法    33.          Object mo = method.invoke(proxy_obj, args);    34.         System.out.println("函数调用后进行处理 :   " + method);    35.         return mo;    36.     }    37.    38.     //测试代码        39.     public static void main(String agr[]){    40.         SellInterface si = (SellInterface)factory(new RedWineFactory());    41.         si.sell();    42.     }    43. }   import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** *代理类一定要实现了InvocationHandler接口 */ public class ProxyObject implements InvocationHandler{ private Object proxy_obj; ProxyObject(Object obj){ this.proxy_obj = obj; } public static Object factory(Object obj){ Class cls = obj.getClass(); //通过Proxy类的newProxyInstance方法来返回代理对象 return Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(),new ProxyObject(obj)); } /** *实现InvocationHandler接口的invoke */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("函数调用前被拦截了: " + method); if(args != null){ //打印参数列表 System.out.println("方法有 " + args.length + " 个参数"); for(int i = 0; i < args.length; i ++){ System.out.println(args[i]); } } //利用反射机制动态调用原对象的方法 Object mo = method.invoke(proxy_obj, args); System.out.println("函数调用后进行处理 : " + method); return mo; } //测试代码 public static void main(String agr[]){ SellInterface si = (SellInterface)factory(new RedWineFactory()); si.sell(); } } 通过上面的代码可以看出,代理主题ProxyObject类并没有实现我们定义的SellInterface借口, 而是实现了java的InvocationHandler接口,这样就把代理主题角色和我们的业务代码分离开来,使代理对象能通用于其他接口. 其实InvocationHandler接口就是一种拦截机制,当系统中有了代理对象以后,对原对象(真实主题)方法的调用,都会转由InvocationHandler接口来处理,并把方法信息以参数的形式传递给invoke方法,这样,我们就可以在invoke方法中拦截原对象的调用,并通过反射机制来动态调用原对象的方法.这好象也是spring aop编程的基础吧 接着,用代理模式实现一个超级简单的aop拦截机制 这个例子可以拦截我们指定的函数,并在拦截前后根据需要进行处理 Java代码 1. /**   2. *切面接口,通过实现这个接口,我们可以对指定函数在调用前后进行处理   3. */   4. public interface AopInterface {    5.    public void before(Object obj);//调用的处理    6.    public void end(Object obj);//调用后的处理    7. }   /** *切面接口,通过实现这个接口,我们可以对指定函数在调用前后进行处理 */ public interface AopInterface { public void before(Object obj);//调用的处理 public void end(Object obj);//调用后的处理 } 这个是实现了AopInterface 接口,在这里我们实现了我们的处理逻辑 Java代码 1. public class AopInterfaceImp implements AopInterface{    2.    3.     public void before(Object obj) {    4.         System.out.println("调用前拦截");    5.     }    6.    7.     public void end(Object obj) {    8.         System.out.println("调用调用后处理");    9.     }    10.    11. }   public class AopInterfaceImp implements AopInterface{ public void before(Object obj) { System.out.println("调用前拦截"); } public void end(Object obj) { System.out.println("调用调用后处理"); } } 接着是代理类 Java代码 1. public class PeoxyObject implements InvocationHandler {    2.     private AopInterface aop;//定义了切入时调用的方法    3.     private Object proxy_obj;    4.     private String methodName;//指定要切入的方法名    5.    6.     PeoxyObject(){}    7.    8.     public Object factory(Object obj){    9.         proxy_obj = obj;    10.         Class cls = obj.getClass();    11.         return Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(),this);    12.     }    13.    14.     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {    15.         if(this.aop == null)throw new NullPointerException("aop is null");    16.         if(method == null)throw new NullPointerException("method is null");    17.    18.         Object o;    19. //如果指定了要拦截方法名,并且调用的方法和指定的方法名相同,则进行拦截处理    20. //否则当正常方法处理    21.         if(methodName != null && method.toString().indexOf(methodName) != -1){    22.             aop.before(proxy_obj);//指定方法调用前的处理    23.             o = method.invoke(proxy_obj, args);    24.             aop.end(proxy_obj);//指定方法调用后的处理    25.         }else{    26.             //没有指定的方法,以正常方法调用    27.             o = method.invoke(proxy_obj, args);    28.         }    29.         return o;    30.     }    31.    32.     public AopInterface getAop() {    33.         return aop;    34.     }    35.    36.     public void setAop(AopInterface aop) {    37.         this.aop = aop;    38.     }    39.    40.     public String getMethodName() {    41.         return methodName;    42.     }    43.    44.     public void setMethodName(String methodName) {    45.         this.methodName = methodName;    46.     }    47. }   public class PeoxyObject implements InvocationHandler { private AopInterface aop;//定义了切入时调用的方法 private Object proxy_obj; private String methodName;//指定要切入的方法名 PeoxyObject(){} public Object factory(Object obj){ proxy_obj = obj; Class cls = obj.getClass(); return Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(),this); } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if(this.aop == null)throw new NullPointerException("aop is null"); if(method == null)throw new NullPointerException("method is null"); Object o; //如果指定了要拦截方法名,并且调用的方法和指定的方法名相同,则进行拦截处理 //否则当正常方法处理 if(methodName != null && method.toString().indexOf(methodName) != -1){ aop.before(proxy_obj);//指定方法调用前的处理 o = method.invoke(proxy_obj, args); aop.end(proxy_obj);//指定方法调用后的处理 }else{ //没有指定的方法,以正常方法调用 o = method.invoke(proxy_obj, args); } return o; } public AopInterface getAop() { return aop; } public void setAop(AopInterface aop) { this.aop = aop; } public String getMethodName() { return methodName; } public void setMethodName(String methodName) { this.methodName = methodName; } } 这里定义一个用来测试用的类 Java代码 1. public interface SubInterface {    2.     public void add(String value1,String value2);    3.     public void acc(String value1);    4. }    5.    6. public class ImpObject implements SubInterface{    7.    8.     public void add(String value1,String value2) {    9.         System.out.println("ImpObject add(String value1,String value2)");    10.     }    11.    12.     public void acc(String value1){    13.         System.out.println("ImpObject acc(String value1)");    14.     }    15.    16. }   public interface SubInterface { public void add(String value1,String value2); public void acc(String value1); } public class ImpObject implements SubInterface{ public void add(String value1,String value2) { System.out.println("ImpObject add(String value1,String value2)"); } public void acc(String value1){ System.out.println("ImpObject acc(String value1)"); } } 这里是测试代码 Java代码 1. public static void main(String agr[]){    2.      PeoxyObject po = new PeoxyObject();    3.    4.      po.setAop(new AopInterfaceImp());//我们实现的拦截处理对象    5.       po.setMethodName("acc");//指定要拦截的函数    6.          7.       SubInterface si = (SubInterface)po.factory(new ImpObject());    8.    //因为add方法不是我们指定的拦截函数,AopInterfaceImp是不会被执行    9.       si.add("tt","dd");       10.    11.    //acc是我们指定的拦截方法,所以调用acc的前后会先执行AopInterfaceImp    12.     //对象的两个方法    13.       si.acc("tt");    14.  }   public static void main(String agr[]){ PeoxyObject po = new PeoxyObject(); po.setAop(new AopInterfaceImp());//我们实现的拦截处理对象 po.setMethodName("acc");//指定要拦截的函数 SubInterface si = (SubInterface)po.factory(new ImpObject()); //因为add方法不是我们指定的拦截函数,AopInterfaceImp是不会被执行 si.add("tt","dd"); //acc是我们指定的拦截方法,所以调用acc的前后会先执行AopInterfaceImp //对象的两个方法 si.acc("tt"); } 通过上面可以看出,拦截机制是代理模式的重要使用方式之一, 除了拦截,代理模式还常用于资源加载,当我们要加载的资源很大时,我们可以让真实主题角色在后台加载资源,让代理主题角色负责处理前台的等待提示信息. 还有就是授权机制,通过代理能拦截真实主题的能力,来控制真实主题的访问权限. · · 大小: 53 KB 2 设计模式之--动态代理 动态代理类是一个在运行时由开发人员所指定的一列接口的实现。动态代理接口是一种由代理类实现的接口,并且是一个java.lang.reflect.Proxy类的实例。每一个代理实例都与一个调用处理器对象相联,这个调用处理器实现了java.lang.reflect.InvocationHandler接口。在代理实例上的一个方法调用是 通过其中之一的代理接口被转发到与这个代理实例相联的调用处理的invoke方法上。一个java.lang.reflect.Method对象会决定那一个方法会被调用,一个类型为java.lang.Object的数组包含调用的参数。调用处理器会适当地解码方法的调用(encoded method invocation as appropriate),并且它(调用处理器)的返回结果被作为在代理实例上方法调用返回的结果而返回。 例如,我们已有和装饰器模式中一文中一样的接口IMyBusinessObject和业务类MyBusinessObject。现在当我们使用动态代理时,我必须编写一个调用处理器,因为java.lang.reflect.Proxy类将会用到它。 MyDebugInvocationHandler类看起来像下面那样: Java代码 1. public class MyDebugInvocationHandler implements InvocationHandler {    2.     private Object target ;    3.         4.     public void setTarget(Object target) {    5.         this.target = target;    6.     }    7.    8.     public Object invoke(Object proxy, Method method, Object[] args)    9.             throws Throwable {    10.         System.out.println("Going to execute method :"+method.getName());    11.         Object  retObject = method.invoke(target, args);    12.         System.out.println("After execute method :"+method.getName());    13.         return retObject;    14.     }    15.    16. }   public class MyDebugInvocationHandler implements InvocationHandler { private Object target ; public void setTarget(Object target) { this.target = target; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("Going to execute method :"+method.getName()); Object retObject = method.invoke(target, args); System.out.println("After execute method :"+method.getName()); return retObject; } }  在上面的例子中,invoke ()方法是很重要的,它是被java.lang.reflect.Proxy类所调用的。在这个方法里面,我们执行了一些额外的处理,然后转至真正的目标对象的处理(在这个例子中,是实例MyBusinessObject)。 因此我们的客户端应作如下编码: Java代码 1. IMyBusinessObject bo = new MyBusinessObject();    2.         MyDebugInvocationHandler aMyDebugInvocationHandler = new MyDebugInvocationHandler();    3.         aMyDebugInvocationHandler.setTarget(bo);    4.         IMyBusinessObject proxyObject = (IMyBusinessObject) Proxy    5.                 .newProxyInstance(IMyBusinessObject.class.getClassLoader(),    6.                         new Class[] { IMyBusinessObject.class },    7.                         aMyDebugInvocationHandler);    8.  System.out.println(proxyObject.doExecute("Hello World"));    IMyBusinessObject bo = new MyBusinessObject(); MyDebugInvocationHandler aMyDebugInvocationHandler = new MyDebugInvocationHandler(); aMyDebugInvocationHandler.setTarget(bo); IMyBusinessObject proxyObject = (IMyBusinessObject) Proxy .newProxyInstance(IMyBusinessObject.class.getClassLoader(), new Class[] { IMyBusinessObject.class }, aMyDebugInvocationHandler); System.out.println(proxyObject.doExecute("Hello World"));     输出结果: Java代码 1. Going to execute method :doExecute     2. Here in MyBusinessObject doExecute: input :Hello World     3. After execute method :doExecute     4. Hello World    Going to execute method :doExecute Here in MyBusinessObject doExecute: input :Hello World After execute method :doExecute Hello World  在上面的代码中,我分别创建一个MyBusinessObject实例和一个MyDebugInvocationHandler实例。我们在MyDebugInvocationHandler中设定目标对象为MyBusinessObject。因此当invoke()方法被调用时,它能够把调求发向正确的目标。然后,我们使用java.lang.reflect.Proxy去创建一个IMyBusinessObject接口的代理对象。既然invoke()方法会处理java.lang.reflect.Mehtod类的生成并且其中没有特定的业务接口的方法,通常这些特定的业务接口的方法在每一个业务接口分别编写个业调用处理器是必须的,知道这一点是很重要的。还有,如果我们想实现一些横跨所有业务接口的横切面(cross-cutting aspect),我们不必实现在业务接口中定义的所有业务方法。例如,为了在我们的业务方法中实现安全性,我们仅仅只须在一个地方编写一个方法去实现安全逻辑,这个安全方法我们将以通用的方法编写。 如果我们想在链中增加多个处理器,我们必须创建另一个调用处理器。然后在新定义的处理器中的setTarget()中我们把它设定为链中的前一个代理对象,而不是设定为MyBusinessObject对象。另一个调用处理器代码如下: Java代码 1. public class MyAnotherInvocationHandler implements InvocationHandler {     2.       private Object target;     3.    4.       public void setTarget(Object target) {     5.             this.target = target;     6.       }     7.    8.       public Object invoke(Object proxy, Method method, Object[] args)     9.                   throws Throwable {     10.             System.out     11.                         .println("AnotherConcreteDecorator: Going to execute method : doExecute");     12.             if (method.getName().equals("doExecute") && args != null     13.                         && args.length >= 1) {     14.                   if (args[0] instanceof String) {     15.                         args[0] = args[0] + " Modified by MyAnotherInterceptor";     16.                   }     17.             }     18.             Object temp = method.invoke(target, args);     19.             System.out     20.                         .println("AnotherConcreteDecorator: After execute method : doExecute");     21.             return temp;     22.       }     23.    24. }    public class MyAnotherInvocationHandler implements InvocationHandler { private Object target; public void setTarget(Object target) { this.target = target; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out .println("AnotherConcreteDecorator: Going to execute method : doExecute"); if (method.getName().equals("doExecute") && args != null && args.length >= 1) { if (args[0] instanceof String) { args[0] = args[0] + " Modified by MyAnotherInterceptor"; } } Object temp = method.invoke(target, args); System.out .println("AnotherConcreteDecorator: After execute method : doExecute"); return temp; } }   客户端代码如下: Java代码 1. IMyBusinessObject bo = new MyBusinessObject();    2.         MyDebugInvocationHandler aMyDebugInvocationHandler = new MyDebugInvocationHandler();    3.         aMyDebugInvocationHandler.setTarget(bo);    4.         IMyBusinessObject proxyObject = (IMyBusinessObject) Proxy    5.                 .newProxyInstance(IMyBusinessObject.class.getClassLoader(),    6.                         new Class[] { IMyBusinessObject.class },    7.                         aMyDebugInvocationHandler);    8.    9.         MyAnotherInvocationHandler aMyAnotherInvocationHandler = new MyAnotherInvocationHandler();    10.         aMyAnotherInvocationHandler.setTarget(proxyObject);    11.         IMyBusinessObject nextProxyObject = (IMyBusinessObject) Proxy    12.                 .newProxyInstance(IMyBusinessObject.class.getClassLoader(),    13.                         new Class[] {IMyBusinessObject.class},    14.                         aMyAnotherInvocationHandler);    15.             16.         System.out.println(nextProxyObject.doExecute("Hello World"));   IMyBusinessObject bo = new MyBusinessObject(); MyDebugInvocationHandler aMyDebugInvocationHandler = new MyDebugInvocationHandler(); aMyDebugInvocationHandler.setTarget(bo); IMyBusinessObject proxyObject = (IMyBusinessObject) Proxy .newProxyInstance(IMyBusinessObject.class.getClassLoader(), new Class[] { IMyBusinessObject.class }, aMyDebugInvocationHandler); MyAnotherInvocationHandler aMyAnotherInvocationHandler = new MyAnotherInvocationHandler(); aMyAnotherInvocationHandler.setTarget(proxyObject); IMyBusinessObject nextProxyObject = (IMyBusinessObject) Proxy .newProxyInstance(IMyBusinessObject.class.getClassLoader(), new Class[] {IMyBusinessObject.class}, aMyAnotherInvocationHandler); System.out.println(nextProxyObject.doExecute("Hello World"));   输出结果: Java代码 1. AnotherConcreteDecorator: Going to execute method : doExecute    2. Going to execute method :doExecute    3. Here in MyBusinessObject doExecute: input :Hello World Modified by MyAnotherInterceptor    4. After execute method :doExecute    5. AnotherConcreteDecorator: After execute method : doExecute    6. Hello World Modified by MyAnotherInterceptor   AnotherConcreteDecorator: Going to execute method : doExecute Going to execute method :doExecute Here in MyBusinessObject doExecute: input :Hello World Modified by MyAnotherInterceptor After execute method :doExecute AnotherConcreteDecorator: After execute method : doExecute Hello World Modified by MyAnotherInterceptor 从上面的例子我们可以看出,用动态代理比静态装饰链用更少的代码为业务对象增加额外的行为。但是,如果我们像上面一样使用动态代理仍然有一些问题:当创建和链化动态代理时你仍然必须编写大量的代码,并且你还必须处理不如普通的对象创建或工厂方法的对象创建那么友善的代理接口API,还有,当我们需要代理我们的业务对象时,在多个位置重复一些代码并不是一个好主意。 下一篇博客将试图去解决这些问题。我将会编写一个暴露简单API的通用代理工厂(在其中隐藏代理对象的创建和链化),但仍可提供动态代理的扩展性。 3 设计模式之--进行硬编码的静态装饰器模式和装饰器模式链化 动态代理的背后思想是在一个对象的周围插入动态的行为但不改变对象的已有代码和接口。装饰器模式提供一种不必改变对象代码就可以装饰一个对象(改变它的行为)并向其增加横切面的方法。现在就用静态的装饰来实现具体的业务功能 首先有一个简单业务接口: Java代码 1. public interface IMyBusinessObject {     2.       public String doExecute(String in);     3. }    public interface IMyBusinessObject { public String doExecute(String in); }  这个接口有一个业务对象类的实现。 Java代码 1. public class MyBusinessObject implements IMyBusinessObject {     2. public String doExecute(String in) {     3. System.out.println("Here in MyBusinessObject doExecute: input :" + in);     4. return in;     5. }     6. }    public class MyBusinessObject implements IMyBusinessObject { public String doExecute(String in) { System.out.println("Here in MyBusinessObject doExecute: input :" + in); return in; } }   现在想要在这个业对象类的方法doExecute之前与之后增加一些行为,装饰器模式使我们十分容易增加这个功能。现在定义一个抽象类,这个抽象类实现上面的业务接口。 Java代码 1. public abstract class ADecorator implements IMyBusinessObject {     2.       protected IMyBusinessObject target;     3.       4.       public void setTarget(IMyBusinessObject target) {     5.             this.target = target;     6.       }     7.       8. public ADecorator(){};     9.       10.       public ADecorator(IMyBusinessObject target_) {     11.             setTarget(target_);     12.       }     13. }    public abstract class ADecorator implements IMyBusinessObject { protected IMyBusinessObject target; public void setTarget(IMyBusinessObject target) { this.target = target; } public ADecorator(){}; public ADecorator(IMyBusinessObject target_) { setTarget(target_); } }   为什么要把设置业务对象的方法放到抽象类中呢,这也是重构的一种方法。就是把子类中设置业务对象的方法提到父类中。术语为方法上移。 现在定义一个从ADedorator扩展来的具体类DebugConcreteDecorator,目的是在我们业务对象被调用之前和之后加入一些调试信息: Java代码 1. public class DebugConcreteDecorator extends ADecorator {     2.       3.       4.       public DebugConcreteDecorator(IMyBusinessObject target_) {     5.             super(target_);     6.       }     7.       8.       public String doExecute(String in) {     9.             System.out     10.                         .println("DebugConcreteDecorator: before method : doExecute ");     11.             String ret = target.doExecute(in);     12.             System.out.println("DebugConcreteDecorator: after method : doExecute ");     13.             return ret;     14.       }     15. }    public class DebugConcreteDecorator extends ADecorator { public DebugConcreteDecorator(IMyBusinessObject target_) { super(target_); } public String doExecute(String in) { System.out .println("DebugConcreteDecorator: before method : doExecute "); String ret = target.doExecute(in); System.out.println("DebugConcreteDecorator: after method : doExecute "); return ret; } }   现在在客户端,我们调用业务对象: Java代码 1. IMyBusinessObject aIMyBusinessObject = new MyBusinessObject();     2. IMyBusinessObject wrappedObject = new DebugConcreteDecorator(     3. aIMyBusinessObject);     4. wrappedObject.doExecute("Hello World");    IMyBusinessObject aIMyBusinessObject = new MyBusinessObject(); IMyBusinessObject wrappedObject = new DebugConcreteDecorator( aIMyBusinessObject); wrappedObject.doExecute("Hello World");  输出结果如下: Java代码 1. DebugConcreteDecorator: before method : doExecute     2. Here in MyBusinessObject doExecute: input :Hello World     3. DebugConcreteDecorator: after method : doExecute    DebugConcreteDecorator: before method : doExecute Here in MyBusinessObject doExecute: input :Hello World DebugConcreteDecorator: after method : doExecute 实际的业务方法调用之前链化装饰器----调用一个装饰器后再调用另一个装饰器。让我们再定义另一个装饰器去展示这个方法: Java代码 1. public class AnotherConcreteDecorator extends ADecorator {     2.       3.       public AnotherConcreteDecorator(     4.                   IMyBusinessObject target_) {     5.             super(target_);     6.       }     7.       8.       public String doExecute(String in) {     9.             System.out     10.                         .println("AnotherConcreteDecorator: Going to execute method : doExecute");     11.             in = in + " Modified by AnotherConcreteDecorator";     12.             String ret = target.doExecute(in);     13.             System.out     14.                         .println("AnotherConcreteDecorator: After execute method : doExecute");     15.             return ret;     16.       }     17.       18. }    public class AnotherConcreteDecorator extends ADecorator { public AnotherConcreteDecorator( IMyBusinessObject target_) { super(target_); } public String doExecute(String in) { System.out .println("AnotherConcreteDecorator: Going to execute method : doExecute"); in = in + " Modified by AnotherConcreteDecorator"; String ret = target.doExecute(in); System.out .println("AnotherConcreteDecorator: After execute method : doExecute"); return ret; } }   上面的代码片段通过在业务方法输入的字符参数后增加(" Modified by AnotherConcreteDecorator")字符串,从而实现对其进行了修改。如果我们想链化装饰器,在客户端,我们可以编写如下的代码:   Java代码 1. IMyBusinessObject aIMyBusinessObject = new MyBusinessObject();     2. IMyBusinessObject wrappedObject = new AnotherConcreteDecorator(     3.             new DebugConcreteDecorator(aIMyBusinessObject));     4. wrappedObject.doExecute("Hello World");    IMyBusinessObject aIMyBusinessObject = new MyBusinessObject(); IMyBusinessObject wrappedObject = new AnotherConcreteDecorator( new DebugConcreteDecorator(aIMyBusinessObject)); wrappedObject.doExecute("Hello World");   在上面的代码片段中,我在创建一个DebugConcreteDecorator实例时,向其传递了一个实际的业务对象实例。然后用一个刚才定义的notherConcreteDecorator实例去包装DebugConcreteDecorator实例。AntherConcreteDecorator首先在输入参数后增加字符串对其进行修改,然后调用DebugConcreteDecorator实例的doExecute()方法。这时,DebugConcreteDecorator会记录doExectute()方法的输出的条目,然后调用doExecute()去调用实际业务对象的doExecute()方法。 它的返回路径以相反的顺序。在从实际的业务对象(MyBusinessObject)doExecute()方法返回之后,DebugConcreteDecorator余下代码将被执行。于是,调用返回至AnotherConcreteDecorator实例并执行余下的部份代码。 输出结果如下: Java代码 1. AnotherConcreteDecorator: Going to execute method : doExecute     2. DebugConcreteDecorator: before method : doExecute     3. Here in MyBusinessObject doExecute: input :Hello World Modified by AnotherConcreteDecorator     4. DebugConcreteDecorator: after method : doExecute     5. AnotherConcreteDecorator: After execute method : doExecute    AnotherConcreteDecorator: Going to execute method : doExecute DebugConcreteDecorator: before method : doExecute Here in MyBusinessObject doExecute: input :Hello World Modified by AnotherConcreteDecorator DebugConcreteDecorator: after method : doExecute AnotherConcreteDecorator: After execute method : doExecute   静态装饰器有一个问题:不知大家注意到没有DebugConcreteDecorator 或 AnotherConcreteDecorator中doExecute()方法。它对目标对象doExecute()方法的调用进行了硬编码。并且,如果我们在IMyBusinessObject接口中定义另一个方法,我们必须改写所有装饰器并提供这个方法的实现。于是,在实践中,我们可能会因有许多装饰器和在每个装饰器中有大量的代码而止步。 4 通用的动态代理链--为你的应用程序添加AOP 摘要: 如果你使用一个并不提供AOP支持的框架,但你又需要实现一些AOP特性,那么不要在项目中引入一成熟的AOP框架,请考虑用通用动态代理建立自己的小框架。十分希望这篇文章能为如何实现这个功能提供一些帮助。如果你使用一个使用动态代理方法的AOP框架,那么这篇文章应该可以帮助你理解动态代理和它们的链化的基本原理 大多数开发者都知道在运行时中如何装饰一个对象并向其增加额外的功能。四人帮(GoF)的装饰器模式可帮助开发者获得这个功能。在反射包中,J2SE 1.3引入动态代理用于动态地装饰一个业务对象。此外,链化动态代理可以在运行时动态地向一个业务对象增加多种行为。特别地,这些额外的行为的类型是由面向方面编程定位的。这篇文章并不打算对AOP作深入的讨论,而准备把重点放在动态代理的一般链化上,从而使开发者可以用以框架驱动的方法去实现一些AOP 概念。如果一个项目早已使用用某些现存的AOP框架,那么开发者不用再担心实现一个定制的框架。开发者不论何种原因,在他们的项目中不使用这个框架仍然可以以一种有效的方法中且用较小的努力就可获得链化动态代理的好处。 今天,用简单Java对像(POJOs)编程是相当流行的。当我们用 POJOs编程时,人们可以相当容易地应用面向对象编程方法(OOP)。但有时在一个项目中用OOP去实现横切面(cross-cutting aspects)被证明是很困难的。例如,通常地,对于某个项目,在一个POJOs的业务对象中用OOP去实现日志或安全功能是很因难的。在 J2SE1.3中引入的动态代理提供了一种方便的解决方法。 动态代理的背后思想是在一个对象的周围插入动态的行为但不改变对象的已有代码和接口。著名的四人邦的装饰器模式提供一种不必改变对象代码就可以装饰一个对象(改变它的行为)并向其增加横切面的方法。现在的许多框架和工具都使用这个模式。但当实现静态的装饰时会导致一些问题,在这篇文章的后面我会对此进行讨论。 之前引入的动态代理是没有直接的办法用于动态地装饰一个对象的。于是供应商们提供一些会自动产生代码去装饰对象的工具。尽管代码生成工具可以帮助我们产生静态的装饰器,但它要求一些额外的步骤,同时还带来对生产代码的维护开 销。通过使用动态代理,我们可以大大的减少自动生成的代码量(甚至可能是零)。 为了理解动态代理是如何工作的,同时看一下动态代理在它的位置上能起什么作用。让我们举一个装饰器类将作为一个方法拦截器的例子。如果像这样使用动态代理,我们可能就面临某些编程的复杂性。在这篇文章的后面,你将会看到如何包装和动态代理有关的复杂性,并在它们之上提供一个抽象,在这篇文章中所在使用的大多数源代码都可以从Resources下载。 版权声明:任何获得Matrix授权的网站,转载时请务必保留以下作者信息和链接 作者:Srijeeb Roy;EsunYang(作者的blog:http://blog.matrix.org.cn/page/EsunYang) 原文:http://www.matrix.org.cn/resource/article/44/44408_Dynamic+Proxy+AOP.html 关键字:Dynamic;AOP;Proxy 没有动态代理的静态装饰和链化 假设我们有一个简单的业务接口: Java代码 1. public interface IMyBusinessObject {    2.    public String doExecute(String in);    3. }    public interface IMyBusinessObject { public String doExecute(String in); } 这个接口有一个业务对象类的实现。 Java代码 1. public class MyBusinessObject implements IMyBusinessObject {    2.    public String doExecute(String in) {    3.       System.out.println("Here in MyBusinessObject doExecute: input :" + in);    4.       return in;    5.    }    6. }   public class MyBusinessObject implements IMyBusinessObject { public String doExecute(String in) { System.out.println("Here in MyBusinessObject doExecute: input :" + in); return in; } } 现在,我们想在doExecute()方法之前和之后增加一些行为(如logging)。装饰器模式使我们十分容易增加这个功能。 Java代码 1. public abstract class ADecorator implements IMyBusinessObject {    2.    protected IMyBusinessObject target;    3.    public void setTarget(IMyBusinessObject target_) {    4.       this.target = target_;    5.    }    6.    public ADecorator(){}    7.    public ADecorator(IMyBusinessObject target_) {    8.       setTarget(target_);    9.    }    10. }    public abstract class ADecorator implements IMyBusinessObject { protected IMyBusinessObject target; public void setTarget(IMyBusinessObject target_) { this.target = target_; } public ADecorator(){} public ADecorator(IMyBusinessObject target_) { setTarget(target_); } } 现在定义一个从ADedorator扩展来的具体类DebugConcreteDecorator,我们的目的是在我们业务对象被调用之前和之后加入一些调试信息: Java代码 1. public class DebugConcreteDecorator extends ADecorator {    2.    public String doExecute(String in) {    3.       System.out.println("DebugConcreteDecorator: before method : doExecute ");    4.    5.       String ret = target.doExecute(in);    6.       System.out.println("DebugConcreteDecorator: after method : doExecute ");    7.       return ret;    8.    }    9. }    public class DebugConcreteDecorator extends ADecorator { public String doExecute(String in) { System.out.println("DebugConcreteDecorator: before method : doExecute "); String ret = target.doExecute(in); System.out.println("DebugConcreteDecorator: after method : doExecute "); return ret; } } 现在在客户端,我们调用业务对象: Java代码 1. IMyBusinessObject aIMyBusinessObject = new MyBusinessObject();    2. IMyBusinessObject wrappedObject =     3.    new DebugConcreteDecorator(aIMyBusinessObject);    4. wrappedObject.doExecute("Hello World");    IMyBusinessObject aIMyBusinessObject = new MyBusinessObject(); IMyBusinessObject wrappedObject = new DebugConcreteDecorator(aIMyBusinessObject); wrappedObject.doExecute("Hello World"); 在上面的代码片段中,我们用DebugConcreteDecorator类实例包装了我们的业务对象。因为DebugConcreteDecorator 是从ADecorator类中扩展来的,并且ADecorator实现了业务对象接口IMyBusinessObject,因此 DebugConcreteDecorator类本身就是接口IMyBusinessObject的实例。首先,我们创建一个 MyBusinessObject实例,然后,我再创建DebugConcreteDecorator实例并在构造函数中向其传递业务对象。因为在 DebugConcreteDecorator中是没有构造函数,所以它的超类(ADecorator)的构造函数会被调用,并目标对象设定为 MyBusinessObject的实例。于是,当DebugConcreteDecorator实例的doExectute()被调用时,它首先记录一些调式信息(使用System.out)然后调用实际业务对象上(MyBusinessObject)的业务方法。 上面的调用输出如下: DebugConcreteDecorator: before method : doExecute Here in MyBusinessObject doExecute: input :Hello World DebugConcreteDecorator: after method : doExecute 从输出中,我们可以看出,我们可以在业务方法被调用之前和之后加入调试信息。 我们还可以在实际的业务方法调用之前链化装饰器----调用一个装饰器后再调用另一个装饰器。让我们再定义另一个装饰器去展示这个方法: Java代码 1. public class AnotherConcreteDecorator extends ADecorator {    2.    public String doExecute(String in) {    3.       System.out.println("AnotherConcreteDecorator: Going to execute method : doExecute");    4.       in = in + " Modified by AnotherConcreteDecorator";    5.       String ret = target.doExecute(in);    6.       System.out.println("AnotherConcreteDecorator: After execute method : doExecute");    7.       return ret;    8.    }    9. }   public class AnotherConcreteDecorator extends ADecorator { public String doExecute(String in) { System.out.println("AnotherConcreteDecorator: Going to execute method : doExecute"); in = in + " Modified by AnotherConcreteDecorator"; String ret = target.doExecute(in); System.out.println("AnotherConcreteDecorator: After execute method : doExecute"); return ret; } } 上面的代码片段通过在业务方法输入的字符参数后增加(" Modified by AnotherConcreteDecorator")字符串,从而实现对其进行了修改。 如果我们想链化装饰器,在客户端,我们可以编写如下的代码: Java代码 1. IMyBusinessObject aIMyBusinessObject = new MyBusinessObject();    2. IMyBusinessObject wrappedObject =    3.    new AnotherConcreteDecorator (new DebugConcreteDecorator(aIMyBusinessObject));    4. wrappedObject.doExecute("Hello World");   IMyBusinessObject aIMyBusinessObject = new MyBusinessObject(); IMyBusinessObject wrappedObject = new AnotherConcreteDecorator (new DebugConcreteDecorator(aIMyBusinessObject)); wrappedObject.doExecute("Hello World"); 在上面的代码片段中,我在创建一个DebugConcreteDecorator实例时,向其传递了一个实际的业务对象实例。然后用一个刚才定义的 AnotherConcreteDecorator实例去包装DebugConcreteDecorator实例。 AntherConcreteDecorator首先在输入参数后增加字符串对其进行修改,然后调用DebugConcreteDecorator实例的 doExecute()方法。这时,DebugConcreteDecorator会记录doExectute()方法的输出的条目,然后调用 doExecute()去调用实际业务对象的doExecute()方法。 它的返回路径以相反的顺序。在从实际的业务对象 (MyBusinessObject)doExecute()方法返回之后,DebugConcreteDecorator余下代码将被执行。于是,调用返回至AnotherConcreteDecorator实例并执行余下的部份代码。 上面的调用产生如个输出: AnotherConcreteDecorator: Going to execute method : doExecute DebugConcreteDecorator: before method : doExecute Here in MyBusinessObject doExecute: input :Hello World Modified by AnotherConcreteDecorator DebugConcreteDecorator: after method : doExecute AnotherConcreteDecorator: After execute method : doExecute 上面方法所展示的类图如图1: 图1。用静态装饰器修饰的业务对象类图 让我们看一下静态装饰器所产生的问题。 考察DebugConcreteDecorator 或 AnotherConcreteDecorator中doExecute()方法。它对目标对象doExecute()方法的调用进行了硬编码。并且,如果我们在IMyBusinessObject接口中定义另一个方法,我们必须改写所有装饰器并提供这个方法的实现。于是,在实践中,我们可能会因有许多装饰器和在每个装饰器中有大量的代码而止步。一个动态代理可以帮助我们去掉这些硬编码,此外,我们不必在每个装饰器去实现和改写业务接口中的每个方法。 在这篇文章中我不打算深究动态代理的细节。相反,我会举一个小例子,同时展示动态代理如何工作的。然后,我直接进入动态代理的链化从而以通用的方法去拦截方法的调用。 J2SE 1.3动态代理:一个例子 动态代理类是一个在运行时所指定的一列接口的实现。动态代理接口是一种由代理类实现的接口,并且是一个java.lang.reflect.Proxy类的实例。每一个代理实例都与一个调用处理器对像相联,这个调用处理器实现了java.lang.reflect.InvocationHandler接口。在代理实例上的一个方法调用是通过其中之一的代理接口被转发到与这个代理实例相联的调用处理的invoke方法上。一个 java.lang.reflect.Method对象会决定那一个方法会被调用,一个类型为java.lang.Object的数组包含调用的参数。调用处理器会适当地解码方法的调用(encoded method invocation as appropriate),并且它(调用处理器)的返回结果被作为在代理实例上方法调用返回的结果而返回。 例如,我们已有和前面例子一样的接口IMyBusinessObject和业务类MyBusinessObject。现在当我们使用动态代理时,我必须编写一个调用处理器,因为java.lang.reflect.Proxy类将会用到它。 DebugInvocationHandler类看起来像下面那样: Java代码 1. public class MyDebugInvocationHandler     2.    implements java.lang.reflect.InvocationHandler  {    3.    4.    private Object target = null;    5.    public void setTarget(Object target_) {    6.       this.target = target_;    7.    }    8.    public Object invoke(Object proxy, Method method,     9.       Object[] args) throws Throwable {    10.       try {    11.          System.out.println("Going to execute method : " + method.getName);    12.          Object retObject = method.invoke(target, args);    13.          System.out.println("After execute method : " + method.getName());    14.          return retObject;    15.       } catch(InvocationTargetException e) {    16.          throw e.getTargetException();    17.       } catch(Exception e) {    18.          throw e;    19.       }    20.    }    21. }   public class MyDebugInvocationHandler implements java.lang.reflect.InvocationHandler { private Object target = null; public void setTarget(Object target_) { this.target = target_; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { try { System.out.println("Going to execute method : " + method.getName); Object retObject = method.invoke(target, args); System.out.println("After execute method : " + method.getName()); return retObject; } catch(InvocationTargetException e) { throw e.getTargetException(); } catch(Exception e) { throw e; } } } 在上面的例子中,invoke ()方法是很重要的,它是被java.lang.reflect.Proxy类所调用的。在这个方法里面,我们执行了一些额外的处理,然后转至真正的目标对象的处理(在这个例子中,是实例MyBusinessObject)。 因此我们的客户端应作如下编码: Java代码 1. IMyBusinessObject bo = new MyBusinessObject();    2. MyDebugInvocationHandler aMyDebugInvocationHandler =    3.    new MyDebugInvocationHandler();    4. aMyDebugInvocationHandler.setTarget(bo);    5.    6. IMyBusinessObject proxyObject =     7.    (IMyBusinessObject) Proxy.newProxyInstance    8.       (IMyBusinessObject.class.getClassLoader(),    9.       new Class[] { IMyBusinessObject.class },    10.       aMyDebugInvocationHandler);    11.    12. System.out.println(proxyObject.doExecute("Hello World"));   IMyBusinessObject bo = new MyBusinessObject(); MyDebugInvocationHandler aMyDebugInvocationHandler = new MyDebugInvocationHandler(); aMyDebugInvocationHandler.setTarget(bo); IMyBusinessObject proxyObject = (IMyBusinessObject) Proxy.newProxyInstance (IMyBusinessObject.class.getClassLoader(), new Class[] { IMyBusinessObject.class }, aMyDebugInvocationHandler); System.out.println(proxyObject.doExecute("Hello World")); 在上面的代码中,我分别创建一个MyBusinessObject实例和一个MyDebugInvocationHandler实例。我们在 MyDebugInvocationHandler中设定目标对象为MyBusinessObject。因此当invoke()方法被调用时,它能够把调求发向正确的目标。然后,我们使用java.lang.reflect.Proxy去创建一个IMyBusinessObject接口的代理对象。既然 invoke()方法会处理java.lang.reflect.Mehtod类的生成并且其中没有特定的业务接口的方法,通常这些特定的业务接口的方法在每一个业务接口分别编写个业调用处理器是必 须的,知道这一点是很重要的。还有,如果我们想实现一些横跨所有业务接口的横切面(cross- cutting aspect),我们不必实现在业务接口中定义的所有业务方法。例如,为了在我们的业务方法中实现安全性,我们仅仅只须在一个地方编写一个方法去实现安全逻辑,这个安全方法我们将以通用的方法编写。 如果我们想在链中增加多个处理器,我们必须创建另一个调用处理器。然后在新定义的处理器中的setTarget()中我们把它设定为链中的前一个代理对象,而不是设定为MyBusinessObject对象。因此代码看起来像下面那样子: Java代码 1. MyAnotherInvocationHandler aMyAnotherInvocationHandler = new MyAnotherInvocationHandler ();    2.    3. //Here we will set the proxyObject, which we get through earlier     4. //code snippet, instead of the business object instance    5. aMyAnotherInvocationHandler.setTarget(proxyObject);    6.    7. IMyBusinessObject nextProxyObject =    8.    (IMyBusinessObject) Proxy.newProxyInstance    9.       (IMyBusinessObject.class.getClassLoader(),    10.       new Class[] { IMyBusinessObject.class },    11.       aMyAnotherInvocationHandler);    12.    13. System.out.println(nextProxyObject.doExecute("Hello World"));    MyAnotherInvocationHandler aMyAnotherInvocationHandler = new MyAnotherInvocationHandler (); //Here we will set the proxyObject, which we get through earlier //code snippet, instead of the business object instance aMyAnotherInvocationHandler.setTarget(proxyObject); IMyBusinessObject nextProxyObject = (IMyBusinessObject) Proxy.newProxyInstance (IMyBusinessObject.class.getClassLoader(), new Class[] { IMyBusinessObject.class }, aMyAnotherInvocationHandler); System.out.println(nextProxyObject.doExecute("Hello World")); 从上面的例子我们可以看出,如何用动态代理以比静态装饰链更少的代码为业务对象增加额外的行为。但是,如果我们像上面一样使用动态代理仍然有一些问题:当创建和链化动态代理时你仍然必须编写大量的代码,并且你还必须处理不如普通的对象创建或工厂方法的对象创建那么友善的代理接口API,还有,当我们需要代理我们的业务对象时,在多个位置重复一些代码并不是一个好主意。 文章的余下部份将会试图去解决这些问题。我将会编写一个暴露简单API的通用代理工厂(在其中隐藏代理对象的创建和链化),但仍可提供动态代理的扩展性。 通用链化动态代理:方法一 如果我们的用户使用下面的代码片段去调用业务对象合适吗? Java代码 1. String[] interceptorClasses = {"MyDebugInterceptor",     2.                               "MyAnotherInterceptor"};    3. IMyBusinessObject aIMyBusinessObject =    4.    (IMyBusinessObject)MyProxyFactory.getProxyObject    5.    6.       ("MyBusinessObject", interceptorClasses);    7. String ret = aIMyBusinessObject.doExecute("Hello World");     String[] interceptorClasses = {"MyDebugInterceptor", "MyAnotherInterceptor"}; IMyBusinessObject aIMyBusinessObject = (IMyBusinessObject)MyProxyFactory.getProxyObject ("MyBusinessObject", interceptorClasses); String ret = aIMyBusinessObject.doExecute("Hello World"); 上面的代码的目的是,提供存储一个拦截器类名的java.lang.String 数组和在MyProxyFactory类的方法内提供业务类。我们期望MyProxyFactory可以创建业务对象,并用在 getProxyObject()方法上的第二个参数所传递来的拦截器包装它。现在如果我们调用doExectue()业务方法,所有在链上的拦截器都会执行,并且实际的业务方法最终也会被调用到。 如果MyDebugInterceptor 和 MyAnotherInterceptor是通用的并且不随我们的业务接口(IMyBusinessObject)而变化的话,这也是合适的。为达到这种功能,我们现在检查下面的步骤。 因为这个方法,我们假定在业务方法被执行之前和之后方法的拦截都会独立的完成。我们为拦截器定义一个接口: Java代码 1. public interface IMethodInterceptor {    2.    Object interceptBefore(Object proxy, Method method,     3.       Object[] args, Object realtarget);    4.    void interceptAfter(Object proxy, Method method,     5.       Object[] args, Object realtarget, Object retObject,     6.       Object interceptBeforeReturnObject);    7. }    public interface IMethodInterceptor { Object interceptBefore(Object proxy, Method method, Object[] args, Object realtarget); void interceptAfter(Object proxy, Method method, Object[] args, Object realtarget, Object retObject, Object interceptBeforeReturnObject); } 我们的目的是在执行任何业务方法之前调用interceptBefore()方法,在成功执行我们的业务方法之后调用interceptAfter()方法(没有抛出任何异常)。 现在我们写两个IMethodInterceptor接口的实现: Java代码 1. public class MyDebugInterceptor implements IMethodInterceptor {    2.    3.    public Object interceptBefore(Object proxy, Method method,     4.       Object[] args, Object realtarget) {    5.    6.       System.out.println("MyDebugInterceptor: Going to execute method : ");    7.       return null;    8.    }    9.    public void interceptAfter(Object proxy, Method method, Object[] args,     10.       Object realtarget, Object retObject, Object interceptBefore) {    11.    12.       System.out.println("MyDebugInterceptor: After execute method : " );    13.    }    14. }    public class MyDebugInterceptor implements IMethodInterceptor { public Object interceptBefore(Object proxy, Method method, Object[] args, Object realtarget) { System.out.println("MyDebugInterceptor: Going to execute method : "); return null; } public void interceptAfter(Object proxy, Method method, Object[] args, Object realtarget, Object retObject, Object interceptBefore) { System.out.println("MyDebugInterceptor: After execute method : " ); } } 这是第一个实现,在方法被转至目标对象object.interceptBefore()之前,MyDebugInterceptor's interceptBefore()方法拦截请求-----仅仅是向控制台打印一行。 Java代码 1. public class MyAnotherInterceptor implements IMethodInterceptor {    2.    3.    4.    public Object interceptBefore(Object proxy, Method method,     5.       Object[] args, Object realtarget) {    6.    7.       System.out.println("MyAnotherInterceptor: Going to execute method : ");    8.       if ( method.getName().equals("doExecute") &&     9.          args != null && args.length >= 1 ) {    10.    11.          if ( args[0] instanceof String ) {    12.             args[0] = args[0] +     13.                " Modified by MyAnotherInterceptor";    14.          }    15.        return null;    16.       }    17.    }    18.    19.    public void interceptAfter(Object proxy, Method method, Object[] args,     20.       Object realtarget, Object retObject, Object interceptBefore) {    21.    22.       System.out.println("MyAnotherInterceptor: After execute method : ");    23.    }    24. }    public class MyAnotherInterceptor implements IMethodInterceptor { public Object interceptBefore(Object proxy, Method method, Object[] args, Object realtarget) { System.out.println("MyAnotherInterceptor: Going to execute method : "); if ( method.getName().equals("doExecute") && args != null && args.length >= 1 ) { if ( args[0] instanceof String ) { args[0] = args[0] + " Modified by MyAnotherInterceptor"; } return null; } } public void interceptAfter(Object proxy, Method method, Object[] args, Object realtarget, Object retObject, Object interceptBefore) { System.out.println("MyAnotherInterceptor: After execute method : "); } } 上面是第二个实现,在方法被转至目标对象之前,MyAnotherInterceptor's interceptBefore()方法也拦截请求。这时,它修改请求参数并改变它的值(如果方法名称是doExecute()的话),它输入的字符串参数中附加了“Modified by MyAnotherInterceptor”字符串。 下一步是写一个能处理我们刚才所写的拦截器的通用调用处理器。 Java代码 1. public class GenericInvocationHandler     2.       implements java.lang.reflect.InvocationHandler {    3.    4.    private Object target = null;    5.    public void setTarget(Object target_) {    6.       this.target = target_;    7.    }    8.    private Object realtarget = null;    9.    public void setRealTarget(Object realtarget_) {    10.       this.realtarget = realtarget_;    11.    }    12.    IMethodInterceptor methodInterceptor = null;    13.    public void setMethodInterceptor     14.       (IMethodInterceptor methodInterceptor_) {    15.       this.methodInterceptor = methodInterceptor_;    16.    }    17.    public Object invoke(Object proxy, Method method, Object[] args)     18.       throws Throwable {    19.       try {    20.          Object interceptBeforeReturnObject = null;    21.          if ( methodInterceptor != null ) {    22.             interceptBeforeReturnObject =    23.                methodInterceptor.interceptBefore    24.                  (proxy, method, args, realtarget );    25.          }    26.          Object retObject = method.invoke(target, args);    27.          if ( methodInterceptor != null ) {    28.             methodInterceptor.interceptAfter    29.                (proxy, method, args, realtarget,    30.                retObject, interceptBeforeReturnObject );    31.          }    32.          return retObject;    33.       }    34.       catch(InvocationTargetException e) {    35.          throw e.getTargetException();    36.       }    37.    38.       catch(Exception e) {    39.          throw e;    40.       }    41.    }    42. }   public class GenericInvocationHandler implements java.lang.reflect.InvocationHandler { private Object target = null; public void setTarget(Object target_) { this.target = target_; } private Object realtarget = null; public void setRealTarget(Object realtarget_) { this.realtarget = realtarget_; } IMethodInterceptor methodInterceptor = null; public void setMethodInterceptor (IMethodInterceptor methodInterceptor_) { this.methodInterceptor = methodInterceptor_; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { try { Object interceptBeforeReturnObject = null; if ( methodInterceptor != null ) { interceptBeforeReturnObject = methodInterceptor.interceptBefore (proxy, method, args, realtarget ); } Object retObject = method.invoke(target, args); if ( methodInterceptor != null ) { methodInterceptor.interceptAfter (proxy, method, args, realtarget, retObject, interceptBeforeReturnObject ); } return retObject; } catch(InvocationTargetException e) { throw e.getTargetException(); } catch(Exception e) { throw e; } } } 请看一下在IMethodInterceptor 上的interceptBefore() 和 interceptAfter()方法在方法被调用之前和之后是如何被分别地插入的。 下一步是写一个MyProxyFactory类,它可通用地创建代理并链化他们。这特别的一步应该可以给你一个如何使用动态代理设计自己框架的印象。 Java代码 1. public class MyProxyFactory {    2.    3.    public static Object getProxyObject( String className,     4.       String[] interceptors ) throws Throwable {    5.    6.       Object inputObject = getTargetObject(className);    7.       if ( interceptors != null && interceptors.length > 0  ) {    8.    9.          Object inputProxiedObject = inputObject;    10.          for ( int i=0; i < interceptors.length; i++ ) {    11.             inputProxiedObject =     12.                getProxyObject(inputObject, interceptors[i],     13.                   inputProxiedObject);    14.          }    15.          return inputProxiedObject;    16.       }    17.       else {    18.          return inputObject;    19.       }    20.    }    21.    22.    private static Object getProxyObject(Object inObject,     23.       String interceptor,Object inProxiedObject) throws Throwable {    24.    25.       GenericInvocationHandler invocationHandler =    26.          new GenericInvocationHandler();    27.       IMethodInterceptor interceptorObject =     28.          (IMethodInterceptor)getInterceptor(interceptor);    29.       if ( interceptor == null ) {    30.          return inProxiedObject;    31.       }    32.       invocationHandler.setTarget(inProxiedObject);    33.       invocationHandler.setRealTarget(inObject);    34.       invocationHandler.setMethodInterceptor(interceptorObject);    35.    36.       return Proxy.newProxyInstance    37.                (inObject.getClass().getClassLoader(),    38.                inObject.getClass().getInterfaces(),    39.                invocationHandler) ;    40.    }    41.    42.    private static Object getInterceptor( String interceptors )     43.       throws Exception {        44.       //...    45.       //From the class name return the class instance.    46.         //You can use Class.forName and newInstance() method on Class     47.         //to return the Object instance.    48.    }    49.    private static Object getTargetObject( String className )      50.       throws Exception {    51.       //...    52.       //From the class name return the class instance.    53.         //You can use Class.forName and newInstance() method on Class     54.         //to return the Object instance.    55.    }    56. }   public class MyProxyFactory { public static Object getProxyObject( String className, String[] interceptors ) throws Throwable { Object inputObject = getTargetObject(className); if ( interceptors != null && interceptors.length > 0 ) { Object inputProxiedObject = inputObject; for ( int i=0; i < interceptors.length; i++ ) { inputProxiedObject = getProxyObject(inputObject, interceptors[i], inputProxiedObject); } return inputProxiedObject; } else { return inputObject; } } private static Object getProxyObject(Object inObject, String interceptor,Object inProxiedObject) throws Throwable { GenericInvocationHandler invocationHandler = new GenericInvocationHandler(); IMethodInterceptor interceptorObject = (IMethodInterceptor)getInterceptor(interceptor); if ( interceptor == null ) { return inProxiedObject; } invocationHandler.setTarget(inProxiedObject); invocationHandler.setRealTarget(inObject); invocationHandler.setMethodInterceptor(interceptorObject); return Proxy.newProxyInstance (inObject.getClass().getClassLoader(), inObject.getClass().getInterfaces(), invocationHandler) ; } private static Object getInterceptor( String interceptors ) throws Exception { //... //From the class name return the class instance. //You can use Class.forName and newInstance() method on Class //to return the Object instance. } private static Object getTargetObject( String className ) throws Exception { //... //From the class name return the class instance. //You can use Class.forName and newInstance() method on Class //to return the Object instance. } } 这段代码,code's public static Object getProxyObject(String className, String[] interceptors)方法里,所有被遍历的拦截器迭代器会调用每个拦截器的private static getProxyObject方法,它的每次调用都会创建一个GenericInvocationHandler实例。这个方法还会设定目标对象和 GenericInvocationHandler实例的拦截器,并且在代理类的static newProxyInstance()方法传递这个实例。 当客户调用public static getProxyObject方法时,对于第一个迭代器,它用下面三个参数调用private getProxyObject()方法: 1.        业务对象实例 2.        用java.lang.String的表示第一个拦截器的名称。 3.        与第一个业务对象相同的一个实例。 一个新的代理对象会用在代理链上的第一个拦截器去包装业务对象实例,并且返回一个代理对象。 在第二个迭代器中,public static getProxyObject方法用下面三个参数调用private getProxyObject(): 1业务对象实例 2用java.lang.String的表示第二个拦截器的名称。 3用第一个拦截器包装的业务对象的实例的代理对象。 一个新的代理对象会使用在拦截链上的第二个拦截器去包装第一个代理对象(从循环中的第一个迭代器返回),并且返回一个新创建的代理对象。 你可能会有下面的想法:通用链化是发生在MyProxyFactory类中。同时知道这一点也很重要:当产生许多的拦截器时,也会同时产生许多的GenericInvocationHandlers和代理实例(因为它们都是在同一个循环中创建的)。 在这个例子中,类的名称是用java.lang.String传送的并且用到了Class.forName()方法,此外,newInstance()方法被用于去实例化目标对象及迭代器。在真正的实践中,每次都使用Class.forName 和 newInstance()方法可能会导致问题。我们可能想在我们的业务对象或拦截器被调用之前设置某些变量,或者我们想某些业务对象和拦截器被定义为 Singleton实例。在一个实际的实践中这些详细的细节必须要考虑的,在方法三中,你将会看到这些特殊性如何被获得以达到某些扩展性。 方法一的程序结果与我们的静态装饰器结果是相匹配的。但这里我获得更好的扩展性。既然MyProxyFactory 和 GenericInvocationHandler是通用的,我们可以使用它去包装任何对象。当然,我们的业务对象必须实现某些预定义的接口,这是一个良好的编程实践。 MyDebugInterceptor 和 MyAnotherInterceptor也可以被通用化而不必为每一个业务接口和业务方法去分别编写代码。假设我们想在业务方法执行之前做一些安全业务方法检查,我们可以在一个拦截器里面的interceptBefore()方法实现。这个安全拦截器可读取文件/数据库,然后执行安全检查。例如我们有下面自定义的安全XML文件: Java代码 1.    2.        3.       MyBusinessObject    4.           5.    6.          doExecute    7.          admin,manager    8.           9.        10.    MyBusinessObject doExecute admin,manager 这个配置可以被读取并缓存起来,之后,安全拦截器会根据方法名称进行处理并用角色来匹配它。(注意:你可能觉得奇怪,在拦截中,我们是如何获得用户的角色的,因为我们并没有传递角色过来。原来它们是用TreadLocal处理的,但这是另一个主题)。 于是,在安全拦截器interceptBefore()方法里面,代码类似如下片段: Java代码 1. public Object interceptBefore(Object proxy, Method method,     2.       Object[] args, Object realtarget) {    3.           4.    String nameOfMethod = method.getName();    5.    String targetClassName = realtarget.getClass().getName();    6.    MethodPermissions mPerm =     7.       SecurityFactory.getPermission(targetClassName);    8.    If ( !mPerm.isAuthorized(MyThreadLocalRoleStore.getRole(),     9.                            nameOfMethod ) ) {    10.       throw new RuntimeException("User not authorized");    11.    }    12.    return null;    13. }    public Object interceptBefore(Object proxy, Method method, Object[] args, Object realtarget) { String nameOfMethod = method.getName(); String targetClassName = realtarget.getClass().getName(); MethodPermissions mPerm = SecurityFactory.getPermission(targetClassName); If ( !mPerm.isAuthorized(MyThreadLocalRoleStore.getRole(), nameOfMethod ) ) { throw new RuntimeException("User not authorized"); } return null; } 我们还必须编写MethodPermissions, SecurityFactory, MyThreadLocalRoleStore去实现完全流动(overall flow),但这些扩展已超出的讨论的范围。并且列出XML仅仅是为了举例而已。对于真正的应用,则需要更健壮的代码(例如异常处理等)。如果在我们业务对象中有一个过载的方法会发生什么事情呢?XML和interceptBefore()方法内的代码都需要改变,并且诸如 MethodPermissions和 SecurityFactory也需要处理那些细节性的改变。 方法一的类图结构如下: 图2。链化动态代理:方法一类图 注意:因为了简化及篇幅的限制,在图2至图4某些类的方法和参数以及接口的细节都没出画出来。在上面的类图中,注意到业务接口IMyBusinessObject并不一定要与任何其它类或接口相联,但除了业务对象之外。 动态链化动态代理:方法二 方法二处理与方法一有相同的类集,并且在客户端的角度来睇也是一样的。可能要改变的是GenericInvocationHandler和 MyProxyFactory。正如方法所说,因为大量的拦截器被创建,GenericInvocationHandler实例和代理实例也大量增加。方法二试图去解决这个问题并同时获得与方法一相近的好处。 因此,客户端的代码与方法一相同: Java代码 1. String[] interceptorClasses = {"MyDebugInterceptor", "MyAnotherInterceptor"};    2. IMyBusinessObject aIMyBusinessObject =    3.    (IMyBusinessObject)MyProxyFactory.getProxyObject    4.       ("MyBusinessObject", interceptorClasses);    5. String ret = aIMyBusinessObject.doExecute("Hello World");   String[] interceptorClasses = {"MyDebugInterceptor", "MyAnotherInterceptor"}; IMyBusinessObject aIMyBusinessObject = (IMyBusinessObject)MyProxyFactory.getProxyObject ("MyBusinessObject", interceptorClasses); String ret = aIMyBusinessObject.doExecute("Hello World"); 在这个方法中我们的目的是仅仅使用一个GenericInvocationHandler实例和代理实例。让我们看一下新的 GenericInvocationHandler代码: Java代码 1. public class GenericInvocationHandler     2.       implements java.lang.reflect.InvocationHandler {    3.    4.    private Object realtarget = null;    5.    public void setRealTarget(Object realtarget_) {    6.       this.realtarget = realtarget_;    7.    }    8.    Object[] methodInterceptors = null;    9.    public void setMethodInterceptors     10.       (Object[] methodInterceptors_) {    11.       this.methodInterceptors = methodInterceptors_;    12.    }    13.    public Object invoke(Object proxy, Method method, Object[] args)     14.          throws Throwable {    15.       try {    16.          Object[] retInterceptBefore = null;    17.          if ( methodInterceptors != null &&     18.             methodInterceptors.length > 0 ) {    19.    20.             retInterceptBefore = new Object[methodInterceptors.length];    21.             for ( int i= methodInterceptors.length - 1; i >= 0; i-- ) {    22.                if ( methodInterceptors[i] != null ) {    23.                   retInterceptBefore[i] =     24.                      ((IMethodInterceptor)methodInterceptors[i]).    25.                         interceptBefore(proxy,     26.                            method,args, realtarget );    27.                }    28.             }    29.          }    30.          Object retObject = method.invoke(realtarget, args);    31.          if ( methodInterceptors != null ) {    32.             for ( int i= 0; i < methodInterceptors.length; i++ ) {    33.                if ( methodInterceptors[i] != null ) {    34.              ((IMethodInterceptor)methodInterceptors[i]).    35.                 interceptAfter(proxy, method, args, realtarget,     36.                    retObject, retInterceptBefore[i] );    37.                }    38.    39.             }    40.          }    41.          return retObject;    42.       }    43.       catch(InvocationTargetException e) {    44.          throw e.getTargetException();    45.       }    46.       catch(Exception e) {    47.          throw e;    48.       }    49.    }    50. }   public class GenericInvocationHandler implements java.lang.reflect.InvocationHandler { private Object realtarget = null; public void setRealTarget(Object realtarget_) { this.realtarget = realtarget_; } Object[] methodInterceptors = null; public void setMethodInterceptors (Object[] methodInterceptors_) { this.methodInterceptors = methodInterceptors_; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { try { Object[] retInterceptBefore = null; if ( methodInterceptors != null && methodInterceptors.length > 0 ) { retInterceptBefore = new Object[methodInterceptors.length]; for ( int i= methodInterceptors.length - 1; i >= 0; i-- ) { if ( methodInterceptors[i] != null ) { retInterceptBefore[i] = ((IMethodInterceptor)methodInterceptors[i]). interceptBefore(proxy, method,args, realtarget ); } } } Object retObject = method.invoke(realtarget, args); if ( methodInterceptors != null ) { for ( int i= 0; i < methodInterceptors.length; i++ ) { if ( methodInterceptors[i] != null ) { ((IMethodInterceptor)methodInterceptors[i]). interceptAfter(proxy, method, args, realtarget, retObject, retInterceptBefore[i] ); } } } return retObject; } catch(InvocationTargetException e) { throw e.getTargetException(); } catch(Exception e) { throw e; } } } GenericInvocationHandler 在调用业务接口上的方法之前会处理一个方法拦截器的数组。它会迭代数组中所有的解释器,并调用每一个解释器的interceptBefore()方法。类似地,在业务方法调用之后,GenericInvocationHandler也会在循环中调用interceptAfter()方法。请注意:interceptBefore()在循环中以相反的方向调用的而interceptAfter()是正向调用的。 MyProxyFactory类也需要改变,但getInterceptor() 和 getTargetObject()则与原来一样。新的MyProxyFactory代码如下: Java代码 1. public static Object getProxyObject( String className,     2.    String[] interceptors ) throws Throwable {    3.    4.    5.    Object inputObject = getTargetObject(className);    6.    if ( interceptors != null && interceptors.length > 0  ) {    7.       return getProxyObject(inputObject, interceptors);    8.    }    9.    else {    10.       return inputObject;    11.    }    12. }    13. private static Object getProxyObject(Object inObject,     14.    String[] interceptors) throws Throwable {    15.    16.    GenericInvocationHandler invocationHandler =    17.       new GenericInvocationHandler();    18.    Object[] interceptorObjects = getInterceptors(interceptors);    19.    invocationHandler.setRealTarget(inObject);    20.    invocationHandler.setMethodInterceptors(interceptorObjects);    21.    22.    return Proxy.newProxyInstance    23.                (inObject.getClass().getClassLoader(),    24.                inObject.getClass().getInterfaces(),    25.                invocationHandler) ;    26. }    27. private static Object[] getInterceptors(String[] interceptors)     28.    throws Exception {    29.    30.    Object[] objInterceptors = new Object[interceptors.length];    31.    for ( int i=0; i < interceptors.length; i++ ) {    32.       objInterceptors[i] = getInterceptor(interceptors[i]);    33.    }    34.    return objInterceptors;    35. }   public static Object getProxyObject( String className, String[] interceptors ) throws Throwable { Object inputObject = getTargetObject(className); if ( interceptors != null && interceptors.length > 0 ) { return getProxyObject(inputObject, interceptors); } else { return inputObject; } } private static Object getProxyObject(Object inObject, String[] interceptors) throws Throwable { GenericInvocationHandler invocationHandler = new GenericInvocationHandler(); Object[] interceptorObjects = getInterceptors(interceptors); invocationHandler.setRealTarget(inObject); invocationHandler.setMethodInterceptors(interceptorObjects); return Proxy.newProxyInstance (inObject.getClass().getClassLoader(), inObject.getClass().getInterfaces(), invocationHandler) ; } private static Object[] getInterceptors(String[] interceptors) throws Exception { Object[] objInterceptors = new Object[interceptors.length]; for ( int i=0; i < interceptors.length; i++ ) { objInterceptors[i] = getInterceptor(interceptors[i]); } return objInterceptors; } 从上面的代码我们可以看出,GenericInvocationHandler仅有一个实例。此外,仅只有一个代理对被创建并且不随许许多多的拦截器而变化。因此,它需要更少的内存。还有,方法二比方法一还会稍微快一些。在最后我将会用一个简单的测试去对比所有方法的结果。 某些人可能会指出,在方法二我们仅仅在GenericInvocationHandler中而不在MyProxyFactory中循环所有的拦截器。需要知道的重点是:在方法一和方法二,拦截器的实例数量是一样的。在方法一中,在循环中还额外地创建了GenericInvocationHandlerS和代理对象。但在方法二中,仅仅只有一个GenericInvocationHandler实例和代理被创建。 方法二的类图如图形所示: 图3.通用链化动态代理:方法二类图 在 IMethodInterceptor接口增加一个能够拦截由目标对象抛出的异常的方法(例如:interceptException()),方法一和方法二可能会更有用(GenericInvocationHandler也需要修改)。此外,我们可以为全部的三个方法((interceptBefore(), interceptAfter(), 和 interceptException())创建不同的接口。我建议你把接口拆分为不同的小接口。例如,我们仅仅想在业务对象执行之前进行拦截,那么我们可能使用仅仅含有interceptBefore()方法的接口而不用考虑关于其它方法的实现。在面向方面编程中(AOP),拦截是作为程序的不同的部份,称为通知(advice)。于是在通知(advice)之前(相对于interceptBefore()方法),在返回通知(advice)之后(相对于interceptAfter()方法),或抛出通知(相对于interceptException ()方法),分别创建各种接口,。另一种更通用更具扩展性的通知能够一齐处理所有的方法的拦截。但既然它是更通用的方法,开发者可能要做更多的工作(开发者要定位下一个目标的方法)。这种通知类型称为环绕通知(around advice)。后面将讨论的方法三将会与AOP的环绕通知(around advice)作一个对比。方法一和方法二都有局限性,不能充分利用不必作大修改的动态代理的优点。例如,既然interceptBefore() 和 interceptAfter()不是直接被调用的,那么在interceptBefore() 和 interceptAfter()之间插入某些控制将会变得很困难。比如我们想写一个同步(synchronized)业务对象的拦截器,我们想达到下面的样子: Java代码 1. synchronized(realtarget) {    2.    3.    retObject = method.invoke(target, args);    4. }   synchronized(realtarget) { retObject = method.invoke(target, args); } 在方法三中,我将马上开始学习。 动态链化动态代理:方法三 在方法三中,客户代码类似于方法一和方法二: Java代码 1. String[] invocationHandlers = {"MyDebugInvocationHandler",     2.    "MyAnotherInvocationHandler"};    3. IMyBusinessObject aIMyBusinessObject =    4.    (IMyBusinessObject)MyProxyFactory.getProxyObject    5.       ("MyBusinessObject", invocationHandlers);    6. String ret = aIMyBusinessObject.doExecute("Hello World");   String[] invocationHandlers = {"MyDebugInvocationHandler", "MyAnotherInvocationHandler"}; IMyBusinessObject aIMyBusinessObject = (IMyBusinessObject)MyProxyFactory.getProxyObject ("MyBusinessObject", invocationHandlers); String ret = aIMyBusinessObject.doExecute("Hello World"); 在方法三中,我们对IMyInvocationHandler作如下的定义: Java代码 1. public interface IMyInvocationHandler {    2.    void setTarget(Object target_);    3.    void setRealTarget(Object realtarget_);    4. }   public interface IMyInvocationHandler { void setTarget(Object target_); void setRealTarget(Object realtarget_); } 我们还定义一个实现IMyInvocationHandler 和 java.lang.reflect.InvocationHandler接口的抽象方法: Java代码 1. public abstract class AMyInvocationHandler     2.    implements IMyInvocationHandler,     3.       java.lang.reflect.InvocationHandler {    4.    5.    protected Object target = null;    6.    protected Object realtarget = null;    7.    8.    public void setTarget(Object target_) {    9.       this.target = target_;    10.    }    11.    public void setRealTarget(Object realtarget_) {    12.       this.realtarget = realtarget_;    13.    }    14. }    public abstract class AMyInvocationHandler implements IMyInvocationHandler, java.lang.reflect.InvocationHandler { protected Object target = null; protected Object realtarget = null; public void setTarget(Object target_) { this.target = target_; } public void setRealTarget(Object realtarget_) { this.realtarget = realtarget_; } } 在方法三中并没有包含 GenericInvocationHandler类或 IMethodInterceptor接口。相反,我们的拦截器扩展了AMyInvocationHandler类。让我们看一下我们的两个拦截器,它们现在提供对接口java.lang.reflect.InvocationHandler中invoke()方法的实现: 1.        Java代码 1. public class MyDebugInvocationHandler extends AMyInvocationHandler {    2.    3.    public Object invoke(Object proxy, Method method, Object[] args)     4.       throws Throwable {    5.    6.       try {    7.          System.out.println("MyDebugInterceptor: Before execute method : "     8.             + method.getName());       9.          Object retObject = method.invoke(target, args);    10.          System.out.println("MyDebugInterceptor: After execute method : "     11.             + method.getName());    12.          return retObject;    13.       }    14.       catch(InvocationTargetException e) {    15.          throw e.getTargetException();    16.       }    17.       catch(Exception e) {    18.          throw e;    19.       }    20.    }    21. }    public class MyDebugInvocationHandler extends AMyInvocationHandler { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { try { System.out.println("MyDebugInterceptor: Before execute method : " + method.getName()); Object retObject = method.invoke(target, args); System.out.println("MyDebugInterceptor: After execute method : " + method.getName()); return retObject; } catch(InvocationTargetException e) { throw e.getTargetException(); } catch(Exception e) { throw e; } } } 2.        Java代码 1. public class MyAnotherInvocationHandler extends AMyInvocationHandler {    2.    3.    public Object invoke(Object proxy, Method method, Object[] args)     4.       throws Throwable {    5.    6.       try {    7.          System.out.println("MyAnotherInvocationHandler: Before execute method : "     8.             + method.getName());             9.          if ( method.getName().equals("doExecute")     10.             && args != null && args.length >= 1 ) {    11.             if ( args[0] instanceof String ) {    12.                args[0] = args[0] + " Modified by MyAnotherInvocationHandler";    13.             }    14.          }    15.          Object retObject = method.invoke(target, args);    16.          System.out.println("MyAnotherInvocationHandler: After execute method : "     17.             + method.getName());    18.          return retObject;    19.       }    20.       catch(InvocationTargetException e) {    21.          throw e.getTargetException();    22.       }    23.       catch(Exception e) {    24.          throw e;    25.       }    26.    }    27. }    public class MyAnotherInvocationHandler extends AMyInvocationHandler { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { try { System.out.println("MyAnotherInvocationHandler: Before execute method : " + method.getName()); if ( method.getName().equals("doExecute") && args != null && args.length >= 1 ) { if ( args[0] instanceof String ) { args[0] = args[0] + " Modified by MyAnotherInvocationHandler"; } } Object retObject = method.invoke(target, args); System.out.println("MyAnotherInvocationHandler: After execute method : " + method.getName()); return retObject; } catch(InvocationTargetException e) { throw e.getTargetException(); } catch(Exception e) { throw e; } } } 在类MyDebugInvocationHandler 和 MyAnotherInvocationHandler中,在拦截doExecute()之前或之后并没有明显的接口或接口方法可用或抛出任何异常去匹配方法调用。考虑Servlet的Filter接口,里面仅有一个doFilter()方法,而没有doBefore()或doAfter()方法。方法三有与之类似的功能。 方法三提供了比其它方法(方法一和方法二)更好的扩展性。例如,通过方法三,看一下我们是如何获得同步性的。我们仅仅实现了从AMyInvocationHandler扩展的同步处理器并在invoke()方法内实现同步逻辑。为了测试它的同步行为,我们要确保有多个线程同时地去访问相同业务实例上的doExecute()方法。同步处理器的例子如下: Java代码 1. public class MySynchronizeInvocationHandler extends AMyInvocationHandler {    2.    3.    public Object invoke(Object proxy, Method method, Object[] args)     4.       throws Throwable {    5.           6.       Object retObject = null;    7.       synchronized(realtarget) {    8.          retObject = method.invoke(target, args);    9.       }    10.       return retObject;    11.    }    12. }   public class MySynchronizeInvocationHandler extends AMyInvocationHandler { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object retObject = null; synchronized(realtarget) { retObject = method.invoke(target, args); } return retObject; } } 让我们看一下方法三的MyProxyFactory主代码: Java代码 1. public static Object getProxyObject( String className,     2.    String[] invocationHandlers ) throws Throwable {    3.    4.    Object inputObject = getTargetObject(className);    5.    if ( invocationHandlers != null &&     6.       invocationHandlers.length > 0  ) {    7.    8.       Object inputProxiedObject = inputObject;    9.       for ( int i=0; i < invocationHandlers.length; i++ ) {    10.          AMyInvocationHandler myInvocationHandler =    11.             (AMyInvocationHandler)getInvocationHandler    12.                (invocationHandlers[i]);    13.          inputProxiedObject = getProxyObject(inputObject,     14.             myInvocationHandler, inputProxiedObject);    15.       }    16.       return inputProxiedObject;    17.    }    18.    else {    19.       return inputObject;    20.    21.    }    22. }    23. public static Object getProxyObject( Object inputObject,     24.    Object[] invocationHandlers ) throws Throwable {    25.    26.    if ( invocationHandlers != null     27.       && invocationHandlers.length > 0  ) {    28.    29.       Object inputProxiedObject = inputObject;    30.       for ( int i=0; i < invocationHandlers.length; i++ ) {    31.          inputProxiedObject = getProxyObject(inputObject,     32.             (AMyInvocationHandler)invocationHandlers[i],     33.                inputProxiedObject);    34.       }    35.    36.       return inputProxiedObject;    37.    }    38.    else {    39.       return inputObject;    40.    }    41. }    42. private static Object getProxyObject(Object inObject,     43.    AMyInvocationHandler myInvocationHandler,    44.       Object inProxiedObject) throws Throwable {    45.    46.    if ( myInvocationHandler == null ) {    47.       return inProxiedObject;    48.    }    49.    myInvocationHandler.setTarget(inProxiedObject);    50.    myInvocationHandler.setRealTarget(inObject);    51.    52.    return Proxy.newProxyInstance    53.                   (inObject.getClass().getClassLoader(),    54.                   inObject.getClass().getInterfaces(),    55.                   myInvocationHandler) ;    56. }   public static Object getProxyObject( String className, String[] invocationHandlers ) throws Throwable { Object inputObject = getTargetObject(className); if ( invocationHandlers != null && invocationHandlers.length > 0 ) { Object inputProxiedObject = inputObject; for ( int i=0; i < invocationHandlers.length; i++ ) { AMyInvocationHandler myInvocationHandler = (AMyInvocationHandler)getInvocationHandler (invocationHandlers[i]); inputProxiedObject = getProxyObject(inputObject, myInvocationHandler, inputProxiedObject); } return inputProxiedObject; } else { return inputObject; } } public static Object getProxyObject( Object inputObject, Object[] invocationHandlers ) throws Throwable { if ( invocationHandlers != null && invocationHandlers.length > 0 ) { Object inputProxiedObject = inputObject; for ( int i=0; i < invocationHandlers.length; i++ ) { inputProxiedObject = getProxyObject(inputObject, (AMyInvocationHandler)invocationHandlers[i], inputProxiedObject); } return inputProxiedObject; } else { return inputObject; } } private static Object getProxyObject(Object inObject, AMyInvocationHandler myInvocationHandler, Object inProxiedObject) throws Throwable { if ( myInvocationHandler == null ) { return inProxiedObject; } myInvocationHandler.setTarget(inProxiedObject); myInvocationHandler.setRealTarget(inObject); return Proxy.newProxyInstance (inObject.getClass().getClassLoader(), inObject.getClass().getInterfaces(), myInvocationHandler) ; } 这段代码与方法一的MyProxyFactory几乎一样。这个类同样在一个循环里迭代调用处理器的数组并为每个调用处理器和代理对象创建实例。在方法一中,GenericInvocationHandler,拦截器和代理对象都是在一个循环中被创建的。在方法三中,仅调用处理器和代理对象在一个循环中被创建的(因为这里面没有独立分开的拦截器)。 在上面的代码片段,我还要介绍一下别一个在MyProxyFactory类中public static方法,它定义如下: Java代码 1. public static Object getProxyObject    2.    ( Object inputObject, Object[] invocationHandlers )   public static Object getProxyObject ( Object inputObject, Object[] invocationHandlers ) 这就像前面我所提到用Class.forName或某些类似的含意。在目标对象,在调用处理器或在拦截器使用Class.forName方法之前,我们不能设定任何变量。因此,为了简化,我提供了上面的方法(你也可以在方法一和方法二中使用相同的办法)。现你可以传递一个标对象,调用处理器或拦截器的实例。例如,客户端的代码看起像下面的样子: Java代码 1. MyDebugInvocationHandler dHandler = new MyDebugInvocationHandler();    2. MyAnotherInvocationHandler aHandler = new MyAnotherInvocationHandler();    3. IMyBusinessObject bo = new MyBusinessObject();    4.    5. //Now set any variables to these objects    6. //or some of these objects may be singletons    7.    8.    9. Object[] invocationHandlers = { dHandler, aHandler };    10.    (IMyBusinessObject)MyProxyFactory.getProxyObject    11.       (bo , invocationHandlers);    12. String ret = aIMyBusinessObject.doExecute("Hello World");   MyDebugInvocationHandler dHandler = new MyDebugInvocationHandler(); MyAnotherInvocationHandler aHandler = new MyAnotherInvocationHandler(); IMyBusinessObject bo = new MyBusinessObject(); //Now set any variables to these objects //or some of these objects may be singletons Object[] invocationHandlers = { dHandler, aHandler }; (IMyBusinessObject)MyProxyFactory.getProxyObject (bo , invocationHandlers); String ret = aIMyBusinessObject.doExecute("Hello World"); 方法三的类图如图4所示: 图4通用链化动态代理:方法三类图 除了这篇文章所描述的方法之外,还存在其它各种不同的方法。特别地,代理工厂可以有完全不现的写法。而且你可能写一个混合或匹配方法一和方法三的代理工厂。 不同方法之间的简单比较 我会做一个简单的测试去看一看去调用一个在被拦截器包装之后实际的业务对象的每一个业务方法要花多少时间。因为没考虑机器配置的原因(比如处理器速度及数量,使用内存的大小等)这个测试不能作为定量的测试。但从这个测试中,我们仍然可以对每一个方法的效率获得大概的印象。 为了进行测试,首先,所有的System.out.println语句都应该注释掉(确保不受I/O时间因素影响)。然后,在每一个方法里面,在一个循环内使用代理工厂去调用的业务方法的调用都运行1000次。在它的顶层,每一个程序运行20次。下面的信息显示了1000次(连续的)调用平均毫秒时间。 静态装饰链: 51.7 毫秒 每1,000 调用 动态代理链:方法1: 166.5毫秒 每1,000 调用 动态代理链:方法2: 125.1毫秒 每1,000 调用 动态代理链:方法3: 159.25毫秒 每1,000 调用 尽管静态装饰器链化所需的时间少得多,如果我们考虑单一的方法调用,那么比较会进入微秒级,这就使得差异变得无关紧要。在实际应用中,为获得毫秒或微妙的时间而不使用通用的方法的通常结果是,在分散的代码中使用更多的客户代码,这实际上花费更多的执行时间。 就像前面所指的一样,我们可混合和匹配方法一和方法三去建立一个良好的AOP框架。另一方面,如果我们需要定义横切面(可以获得所有的好处)去组织程序,并且我们需要考虑到微秒级的性能,那么我们可以考虑使用方法二。 结论 在这篇文章的例子中,在工厂里的方法是静态的。如果你扩展一个工厂或想捅用配置不同的多个工厂实例,这种方法可能会引致以后才出现的问题。因此,要使用合适的工厂模式去编写工厂方法。 我在此仅仅接触了一些AOP概念,并展示在java中如何用动态代理去实现它。其它几个AOP概念如连接点(在程序执行中定义良好的点,例如一个方法调用或一个被抛出的特定异常)点切(point cuts)(一组连接点)都可以在你的工厂类中实现。请查看Resources以获得更详细的信息。 如果你需在你的应用程序中大量使用AOP概念并且可以选择一个现有的框架,那么你可以选择一个有名的,经过严格测试的和支持良好的框架,而不是自己建造一个。如果这样的一个框架对于你是可选的,那么可考虑建造一个你自己的框架。一个旨在提供用于拦截方法调用的java AOP接口的AOP联盟已成立(查看Resources以获得更多的信息)。在建造你自己的框架之前,请查看一下AOP联盟的接口。 如果你使用一个并不提供AOP支持的框架,但你又需要实现一些AOP特性,那么不要在项目中引入一成熟的AOP框架,请考虑用通用动态代理建立自己的小框架。十分希望这篇文章能为如何实现这个功能提供一些帮助。如果你使用一个使用动态代理方法的AOP框架,那么这篇文章应该可以帮助你理解动态代理和它们的链化的基本原理。 5 Spring代码分析(Bean调用,事务,AOP)(一) 在调试了半天后,终于无法忍受时间的流逝以及精神上的折磨(一次又一次的失败),把Spring的源码导进项目工程里,开始调试之路,下面结合Spring的源码说一下Spring事务的运行机理以及如果定义了其他AOP(Spring事务本身就是AOP的around实现)的实现方式。 首先给出一段配置代码: Java代码 1.    2.              5.             6.             7.             10.             11.               12.                   15.             16.             17.        上面的一段是aop的配置代码,其实很简单,第一个aop配置的切入点是Service层以save,update,delete开始的方法,作用是记录日志,当然了,你不想记录的时候,也是可以的,后面会有叙述。第二个aop的advisor就不用说了,事务的配置,第三个是异常拦截并记录日志的aop配置。针对上面的aop配置,我们就假设这里有一个部门的Service: Java代码 1. public interface DepartmentService{    2.     public void saveDepartment(departmentVO vo, LogVO LogVO);    3. }   public interface DepartmentService{ public void saveDepartment(departmentVO vo, LogVO LogVO); } DepartmentService的实现类我们就不写了,另外,我们假设在Action层(无论是struts或者是Webwork或者其他的MVC框架)来调用这个Service里的方法来保存部门的信息,下面我们来看一下整个过程Spring内部是如何运作的。 众所周知的,Spring对接口是使用jdk动态代理的,当我们从Action里调用Service里方法时,Spring会去执行DepartmentService的动态代理类JdkDynamicAopProxy,关于动态代理方面的知识,最近到处都是,都快审美疲劳了,看来什么都可以流行啊,如果那位不是很明白,可以网上搜索一下。ok,继续,看里面的invoke方法 Java代码 1. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {    2.         .......    3.             // Get the interception chain for this method.    4.             List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);    5.    6.             // Check whether we have any advice. If we don't, we can fallback on direct    7.             // reflective invocation of the target, and avoid creating a MethodInvocation.    8.             if (chain.isEmpty()) {    9.                 // We can skip creating a MethodInvocation: just invoke the target directly    10.                 // Note that the final invoker must be an InvokerInterceptor so we know it does    11.                 // nothing but a reflective operation on the target, and no hot swapping or fancy proxying.    12.                 retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args);    13.             }    14.             else {    15.                 // We need to create a method invocation...    16.                 invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);    17.                 // Proceed to the joinpoint through the interceptor chain.    18.                 retVal = invocation.proceed();    19.             }    20.     .........    21. }   public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { ....... // Get the interception chain for this method. List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); // Check whether we have any advice. If we don't, we can fallback on direct // reflective invocation of the target, and avoid creating a MethodInvocation. if (chain.isEmpty()) { // We can skip creating a MethodInvocation: just invoke the target directly // Note that the final invoker must be an InvokerInterceptor so we know it does // nothing but a reflective operation on the target, and no hot swapping or fancy proxying. retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args); } else { // We need to create a method invocation... invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); // Proceed to the joinpoint through the interceptor chain. retVal = invocation.proceed(); } ......... } 从上面这段代码可以看出,getInterceptorsAndDynamicInterceptionAdvice是得到作用于要拦截方法(saveDepartment)上的所有的拦截器,并封装成一个List列表,而下面紧接会做一判断,如果没有配置拦截器,则不会创建一个方法调用,而直接调用目标代码执行,而如果有作用于改方法上的拦截器,则创建一个拦截方法调用,即 Java代码 1. invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);   invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); 实际上代码 Java代码 1. retVal = invocation.proceed();   retVal = invocation.proceed(); 中调用的方法proceed()即为ReflectiveMethodInvocation里的方法,我们看一下这个方法有什么作用: Java代码 1. public Object proceed() throws Throwable {    2.         //  We start with an index of -1 and increment early.    3.         if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {    4.             return invokeJoinpoint();    5.         }    6.    7.         Object interceptorOrInterceptionAdvice =    8.             this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);    9.         if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {    10.             // Evaluate dynamic method matcher here: static part will already have    11.             // been evaluated and found to match.    12.             InterceptorAndDynamicMethodMatcher dm =    13.                 (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;    14.             if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {    15.                 return dm.interceptor.invoke(this);    16.             }    17.             else {    18.                 // Dynamic matching failed.    19.                 // Skip this interceptor and invoke the next in the chain.    20.                 return proceed();    21.             }    22.         }    23.         else {    24.             // It's an interceptor, so we just invoke it: The pointcut will have    25.             // been evaluated statically before this object was constructed.    26.             return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);    27.         }    28.     }   public Object proceed() throws Throwable { // We start with an index of -1 and increment early. if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { return invokeJoinpoint(); } Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex); if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) { // Evaluate dynamic method matcher here: static part will already have // been evaluated and found to match. InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice; if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) { return dm.interceptor.invoke(this); } else { // Dynamic matching failed. // Skip this interceptor and invoke the next in the chain. return proceed(); } } else { // It's an interceptor, so we just invoke it: The pointcut will have // been evaluated statically before this object was constructed. return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); } } 稍微一了解,就能看出,这是一个AOP拦截器的匹配操作,如果匹配上,则进行调用操作,通过该方法就能够得到所有配置的aop中那些是真正作用于该方法,另外注意的是代码:return proceed();明显的递归操作,会递归调用所有符合条件的拦截器操作。 仍旧以我们的代码为例,按照我们上面配置的,首先会是事务的拦截器被调用,即TransactionInterceptor,看此类的invoke方法: Java代码 1. public Object invoke(final MethodInvocation invocation) throws Throwable {    2.         // Work out the target class: may be null.    3.         // The TransactionAttributeSource should be passed the target class    4.         // as well as the method, which may be from an interface.    5.         Class targetClass = (invocation.getThis() != null ? invocation.getThis().getClass() : null);    6.    7.         // If the transaction attribute is null, the method is non-transactional.    8.         final TransactionAttribute txAttr =    9.                 getTransactionAttributeSource().getTransactionAttribute(invocation.getMethod(), targetClass);    10.         final String joinpointIdentification = methodIdentification(invocation.getMethod());    11.    12.         if (txAttr == null || !(getTransactionManager() instanceof CallbackPreferringPlatformTransactionManager)) {    13.             // Standard transaction demarcation with getTransaction and commit/rollback calls.    14.             TransactionInfo txInfo = createTransactionIfNecessary(txAttr, joinpointIdentification);    15.             Object retVal = null;    16.             try {    17.                 // This is an around advice: Invoke the next interceptor in the chain.    18.                 // This will normally result in a target object being invoked.    19.                 retVal = invocation.proceed();    20.             }    21.             catch (Throwable ex) {    22.                 // target invocation exception    23.                 completeTransactionAfterThrowing(txInfo, ex);    24.                 throw ex;    25.             }    26.             finally {    27.                 cleanupTransactionInfo(txInfo);    28.             }    29.             commitTransactionAfterReturning(txInfo);    30.             return retVal;    31.         }    32.     .....    33.    34. }   public Object invoke(final MethodInvocation invocation) throws Throwable { // Work out the target class: may be null. // The TransactionAttributeSource should be passed the target class // as well as the method, which may be from an interface. Class targetClass = (invocation.getThis() != null ? invocation.getThis().getClass() : null); // If the transaction attribute is null, the method is non-transactional. final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(invocation.getMethod(), targetClass); final String joinpointIdentification = methodIdentification(invocation.getMethod()); if (txAttr == null || !(getTransactionManager() instanceof CallbackPreferringPlatformTransactionManager)) { // Standard transaction demarcation with getTransaction and commit/rollback calls. TransactionInfo txInfo = createTransactionIfNecessary(txAttr, joinpointIdentification); Object retVal = null; try { // This is an around advice: Invoke the next interceptor in the chain. // This will normally result in a target object being invoked. retVal = invocation.proceed(); } catch (Throwable ex) { // target invocation exception completeTransactionAfterThrowing(txInfo, ex); throw ex; } finally { cleanupTransactionInfo(txInfo); } commitTransactionAfterReturning(txInfo); return retVal; } ..... } 这个方法就是使用AOP进行声明式事务的实现代码,这里需要说明的是,首先是createTransactionIfNecessary方法,这个方法看名字就知道,在必要的情况下创建事务,我们进入这个方法会看到这样的一行代码: Java代码 1. status = getTransactionManager().getTransaction(txAttr);   status = getTransactionManager().getTransaction(txAttr); 这行代码说明从事务管理器得到一个事务,这里其实说来简单,其实深入的看一下代码还是蛮复杂的,假设我们项目使用的Spring+hibernate,那么自然我们使用Hibernate的事务,下面我们会就代码说明如何取的一个Hibernate事务,首先我们看AbstractPlatformTransactionManager的 getTransaction方法,这里提醒一下,如果你想弄懂Spring的事务的话,请先把这个方法里的代码搞明白,下面我们在这个方法里用中文将一些代码的含义标识出来: Java代码 1. public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {    2.         Object transaction = doGetTransaction();    3.    4.         // Cache debug flag to avoid repeated checks.    5.         boolean debugEnabled = logger.isDebugEnabled();    6.         if (debugEnabled) {    7.             logger.debug("Using transaction object [" + transaction + "]");    8.         }    9.    10.         if (definition == null) {    11.             // Use defaults if no transaction definition given.    12.             definition = new DefaultTransactionDefinition();    13.         }    14.    15.         if (isExistingTransaction(transaction)) {//这里判断当前是否存在事务    16.             // Existing transaction found -> check propagation behavior to find out how to behave.    17.             //在下面方法里,由于当前存在事务,那么需要判断当前拦截的方法在Spring配置文件中配置的propagation的值    18.             //如果是Never的话,则会抛出异常,因为当前已经存在事务    19.             //如果是REQUIRES_NEW,则会挂起当前事务,重新开启一个新事务    20.             //如果是NESTED,则创建一个savepoint,以便事务回滚的时候,可以回滚到该savepoint    21.             return handleExistingTransaction(definition, transaction, debugEnabled);    22.         }    23.    24.         // Check definition settings for new transaction.    25.         if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {//判断事务的失效时间(如果设置的话,默认是-1,不失效)    26.             throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout());    27.         }    28.    29.         // No existing transaction found -> check propagation behavior to find out how to proceed.    30.         //没有事务存在,则检查propagation,目前基本都是使用的默认值,即REQUIRED    31.         if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {    32.             throw new IllegalTransactionStateException(    33.                     "No existing transaction found for transaction marked with propagation 'mandatory'");    34.         }    35.         //如果下面条件满足,则新建一个事务    36.         else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||    37.                 definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||    38.             definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {    39.             Object suspendedResources = suspend(null);    40.             if (debugEnabled) {    41.                 logger.debug("Creating new transaction with name [" + definition.getName() + "]: " + definition);    42.             }    43.             doBegin(transaction, definition);//新建一个事务    44.             boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);    45.             return newTransactionStatus(    46.                     definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);    47.         }    48.         else {    49.             // Create "empty" transaction: no actual transaction, but potentially synchronization.    50.             boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);    51.             return newTransactionStatus(definition, null, true, newSynchronization, debugEnabled, null);    52.         }    53.     }   public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException { Object transaction = doGetTransaction(); // Cache debug flag to avoid repeated checks. boolean debugEnabled = logger.isDebugEnabled(); if (debugEnabled) { logger.debug("Using transaction object [" + transaction + "]"); } if (definition == null) { // Use defaults if no transaction definition given. definition = new DefaultTransactionDefinition(); } if (isExistingTransaction(transaction)) {//这里判断当前是否存在事务 // Existing transaction found -> check propagation behavior to find out how to behave. //在下面方法里,由于当前存在事务,那么需要判断当前拦截的方法在Spring配置文件中配置的propagation的值 //如果是Never的话,则会抛出异常,因为当前已经存在事务 //如果是REQUIRES_NEW,则会挂起当前事务,重新开启一个新事务 //如果是NESTED,则创建一个savepoint,以便事务回滚的时候,可以回滚到该savepoint return handleExistingTransaction(definition, transaction, debugEnabled); } // Check definition settings for new transaction. if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {//判断事务的失效时间(如果设置的话,默认是-1,不失效) throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout()); } // No existing transaction found -> check propagation behavior to find out how to proceed. //没有事务存在,则检查propagation,目前基本都是使用的默认值,即REQUIRED if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) { throw new IllegalTransactionStateException( "No existing transaction found for transaction marked with propagation 'mandatory'"); } //如果下面条件满足,则新建一个事务 else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED || definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW || definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) { Object suspendedResources = suspend(null); if (debugEnabled) { logger.debug("Creating new transaction with name [" + definition.getName() + "]: " + definition); } doBegin(transaction, definition);//新建一个事务 boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER); return newTransactionStatus( definition, transaction, true, newSynchronization, debugEnabled, suspendedResources); } else { // Create "empty" transaction: no actual transaction, but potentially synchronization. boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS); return newTransactionStatus(definition, null, true, newSynchronization, debugEnabled, null); } } 实际上AbstractPlatformTransactionManager类是个平台事务的抽象类,如果你使用的是Hibernate,那么取事务的时候得到就是Hiberante的事务,即通过 HibernateTransactionManager里doBegin方法得到一个Hibernate事务。看HibernateTransactionManager里doBegin方法里的一段代码: Java代码 1. // Register transaction timeout.    2.             int timeout = determineTimeout(definition);    3.             if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {    4.                 if (hibernateSetTimeoutAvailable) {    5.                     // Use Hibernate's own transaction timeout mechanism on Hibernate 3.1    6.                     // Applies to all statements, also to inserts, updates and deletes!    7.                     hibTx = session.getTransaction();    8.                     hibTx.setTimeout(timeout);    9.                     hibTx.begin();    10.                 }    11.                 else {    12.                     // Use Spring query timeouts driven by SessionHolder on Hibernate 3.0    13.                     // Only applies to Hibernate queries, not to insert/update/delete statements.    14.                     hibTx = session.beginTransaction();    15.                     txObject.getSessionHolder().setTimeoutInSeconds(timeout);    16.                 }    17.             }    18.             else {    19.                 // Open a plain Hibernate transaction without specified timeout.    20.                 hibTx = session.beginTransaction();    21.             }   // Register transaction timeout. int timeout = determineTimeout(definition); if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) { if (hibernateSetTimeoutAvailable) { // Use Hibernate's own transaction timeout mechanism on Hibernate 3.1 // Applies to all statements, also to inserts, updates and deletes! hibTx = session.getTransaction(); hibTx.setTimeout(timeout); hibTx.begin(); } else { // Use Spring query timeouts driven by SessionHolder on Hibernate 3.0 // Only applies to Hibernate queries, not to insert/update/delete statements. hibTx = session.beginTransaction(); txObject.getSessionHolder().setTimeoutInSeconds(timeout); } } else { // Open a plain Hibernate transaction without specified timeout. hibTx = session.beginTransaction(); } 是不是很熟悉啊,相信用过Hiberante的大侠,对session.beginTransaction();再熟悉不过了。至于启动事务,然后将该事务设置到一个session holder,可以看一下此方法下面的代码。 ok,至此,我们成功的开启一个事务,那么让我们回到TransactionInterceptor,既然事务已经开启,而事务aop又是一个around advice,那么下面就会调用目标代码执行: Java代码 1. retVal = invocation.proceed();   retVal = invocation.proceed(); 目标代码执行的过程中,如果没有异常抛出,则会提交事务: commitTransactionAfterReturning(txInfo); 如果有异常抛出,则会根据情况来处理事务: completeTransactionAfterThrowing(txInfo, ex);此方法里实现的即为我们经常提到的,如果是runtime异常事务会回滚,如果不是,则事务仍然会提交,看代码: Java代码 1. protected void completeTransactionAfterThrowing(TransactionInfo txInfo, Throwable ex) {    2.         if (txInfo != null && txInfo.hasTransaction()) {    3.             if (logger.isDebugEnabled()) {    4.                 logger.debug("Completing transaction for [" + txInfo.getJoinpointIdentification() +    5.                         "] after exception: " + ex);    6.             }    7.             if (txInfo.transactionAttribute.rollbackOn(ex)) {    8.                 try {    9.                     this.transactionManager.rollback(txInfo.getTransactionStatus());    10.                 }    11.                 catch (RuntimeException ex2) {    12.                     logger.error("Application exception overridden by rollback exception", ex);    13.                     throw ex2;    14.                 }    15.                 catch (Error err) {    16.                     logger.error("Application exception overridden by rollback error", ex);    17.                     throw err;    18.                 }    19.             }    20.             else {    21.                 // We don't roll back on this exception.    22.                 // Will still roll back if TransactionStatus.isRollbackOnly() is true.    23.                 try {    24.                     this.transactionManager.commit(txInfo.getTransactionStatus());    25.                 }    26.                 catch (RuntimeException ex2) {    27.                     logger.error("Application exception overridden by commit exception", ex);    28.                     throw ex2;    29.                 }    30.                 catch (Error err) {    31.                     logger.error("Application exception overridden by commit error", ex);    32.                     throw err;    33.                 }    34.             }    35.         }    36.     }   protected void completeTransactionAfterThrowing(TransactionInfo txInfo, Throwable ex) { if (txInfo != null && txInfo.hasTransaction()) { if (logger.isDebugEnabled()) { logger.debug("Completing transaction for [" + txInfo.getJoinpointIdentification() + "] after exception: " + ex); } if (txInfo.transactionAttribute.rollbackOn(ex)) { try { this.transactionManager.rollback(txInfo.getTransactionStatus()); } catch (RuntimeException ex2) { logger.error("Application exception overridden by rollback exception", ex); throw ex2; } catch (Error err) { logger.error("Application exception overridden by rollback error", ex); throw err; } } else { // We don't roll back on this exception. // Will still roll back if TransactionStatus.isRollbackOnly() is true. try { this.transactionManager.commit(txInfo.getTransactionStatus()); } catch (RuntimeException ex2) { logger.error("Application exception overridden by commit exception", ex); throw ex2; } catch (Error err) { logger.error("Application exception overridden by commit error", ex); throw err; } } } } 6 Spring源代码解析(六):Spring声明式事务处理 我们看看Spring中的事务处理的代码,使用Spring管理事务有声明式和编程式两种方式,声明式事务处理通过AOP的实现把事物管理代码作为方面封装来横向插入到业务代码中,使得事务管理代码和业务代码解藕。在这种方式我们结合IoC容器和Spirng已有的FactoryBean来对事务管理进行属性配置,比如传播行为,隔离级别等。其中最简单的方式就是通过配置TransactionProxyFactoryBean来实现声明式事物; 在整个源代码分析中,我们可以大致可以看到Spring实现声明式事物管理有这么几个部分:     * 对在上下文中配置的属性的处理,这里涉及的类是TransactionAttributeSourceAdvisor,这是一个通知器,用它来对属性值进行处理,属性信息放在TransactionAttribute中来使用,而这些属性的处理往往是和对切入点的处理是结合起来的。对属性的处理放在类TransactionAttributeSource中完成。     * 创建事物的过程,这个过程是委托给具体的事物管理器来创建的,但Spring通过TransactionStatus来传递相关的信息。     * 对事物的处理通过对相关信息的判断来委托给具体的事物管理器完成。 我们下面看看具体的实现,在TransactionFactoryBean中: Java代码 1. public class TransactionProxyFactoryBean extends AbstractSingletonProxyFactoryBean    2.         implements FactoryBean, BeanFactoryAware {    3. //这里是Spring事务处理而使用的AOP拦截器,中间封装了Spring对事务处理的代码来支持声明式事务处理的实现    4.     private final TransactionInterceptor transactionInterceptor = new TransactionInterceptor();    5.    6.     private Pointcut pointcut;    7.    8. //这里Spring把TransactionManager注入到TransactionInterceptor中去    9.     public void setTransactionManager(PlatformTransactionManager transactionManager) {    10.         this.transactionInterceptor.setTransactionManager(transactionManager);    11.     }    12.    13. //这里把在bean配置文件中读到的事务管理的属性信息注入到TransactionInterceptor中去    14.     public void setTransactionAttributes(Properties transactionAttributes) {    15.         this.transactionInterceptor.setTransactionAttributes(transactionAttributes);    16.     }    17.    18.     .........中间省略了其他一些方法.......    19.    20.     //这里创建Spring AOP对事务处理的Advisor    21.     protected Object createMainInterceptor() {    22.         this.transactionInterceptor.afterPropertiesSet();    23.         if (this.pointcut != null) {    24.             //这里使用默认的通知器    25.             return new DefaultPointcutAdvisor(this.pointcut, this.transactionInterceptor);    26.         }    27.         else {    28.             // 使用上面定义好的TransactionInterceptor作为拦截器,同时使用TransactionAttributeSourceAdvisor    29.             return new TransactionAttributeSourceAdvisor(this.transactionInterceptor);    30.         }    31.     }    32. }   public class TransactionProxyFactoryBean extends AbstractSingletonProxyFactoryBean implements FactoryBean, BeanFactoryAware { //这里是Spring事务处理而使用的AOP拦截器,中间封装了Spring对事务处理的代码来支持声明式事务处理的实现 private final TransactionInterceptor transactionInterceptor = new TransactionInterceptor(); private Pointcut pointcut; //这里Spring把TransactionManager注入到TransactionInterceptor中去 public void setTransactionManager(PlatformTransactionManager transactionManager) { this.transactionInterceptor.setTransactionManager(transactionManager); } //这里把在bean配置文件中读到的事务管理的属性信息注入到TransactionInterceptor中去 public void setTransactionAttributes(Properties transactionAttributes) { this.transactionInterceptor.setTransactionAttributes(transactionAttributes); } .........中间省略了其他一些方法....... //这里创建Spring AOP对事务处理的Advisor protected Object createMainInterceptor() { this.transactionInterceptor.afterPropertiesSet(); if (this.pointcut != null) { //这里使用默认的通知器 return new DefaultPointcutAdvisor(this.pointcut, this.transactionInterceptor); } else { // 使用上面定义好的TransactionInterceptor作为拦截器,同时使用TransactionAttributeSourceAdvisor return new TransactionAttributeSourceAdvisor(this.transactionInterceptor); } } } 那什么时候Spring的TransactionInterceptor被注入到Spring AOP中成为Advisor中的一部分呢?我们看到在TransactionProxyFactoryBean中,这个方法在IOC初始化bean的时候被执行: Java代码 1. public void afterPropertiesSet() {    2.     .......    3.     //TransactionProxyFactoryBean实际上使用ProxyFactory完成AOP的基本功能。    4.     ProxyFactory proxyFactory = new ProxyFactory();    5.    6.     if (this.preInterceptors != null) {    7.         for (int i = 0; i < this.preInterceptors.length; i++) {    8.             proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(this.preInterceptors[i]));    9.         }    10.     }    11.    12.     //这里是Spring加入通知器的地方    13.     //有两种通知器可以被加入DefaultPointcutAdvisor或者TransactionAttributeSourceAdvisor    14.     //这里把Spring处理声明式事务处理的AOP代码都放到ProxyFactory中去,怎样加入advisor我们可以参考ProxyFactory的父类AdvisedSupport()    15.     //由它来维护一个advice的链表,通过这个链表的增删改来抽象我们对整个通知器配置的增删改操作。    16.     proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(createMainInterceptor()));    17.    18.     if (this.postInterceptors != null) {    19.         for (int i = 0; i < this.postInterceptors.length; i++) {    20.             proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(this.postInterceptors[i]));    21.         }    22.     }    23.    24.     proxyFactory.copyFrom(this);    25.        26.     //这里创建AOP的目标源    27.     TargetSource targetSource = createTargetSource(this.target);    28.     proxyFactory.setTargetSource(targetSource);    29.    30.     if (this.proxyInterfaces != null) {    31.         proxyFactory.setInterfaces(this.proxyInterfaces);    32.     }    33.     else if (!isProxyTargetClass()) {    34.         proxyFactory.setInterfaces(ClassUtils.getAllInterfacesForClass(targetSource.getTargetClass()));    35.     }    36.    37.     this.proxy = getProxy(proxyFactory);    38. }   public void afterPropertiesSet() { ....... //TransactionProxyFactoryBean实际上使用ProxyFactory完成AOP的基本功能。 ProxyFactory proxyFactory = new ProxyFactory(); if (this.preInterceptors != null) { for (int i = 0; i < this.preInterceptors.length; i++) { proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(this.preInterceptors[i])); } } //这里是Spring加入通知器的地方 //有两种通知器可以被加入DefaultPointcutAdvisor或者TransactionAttributeSourceAdvisor //这里把Spring处理声明式事务处理的AOP代码都放到ProxyFactory中去,怎样加入advisor我们可以参考ProxyFactory的父类AdvisedSupport() //由它来维护一个advice的链表,通过这个链表的增删改来抽象我们对整个通知器配置的增删改操作。 proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(createMainInterceptor())); if (this.postInterceptors != null) { for (int i = 0; i < this.postInterceptors.length; i++) { proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(this.postInterceptors[i])); } } proxyFactory.copyFrom(this); //这里创建AOP的目标源 TargetSource targetSource = createTargetSource(this.target); proxyFactory.setTargetSource(targetSource); if (this.proxyInterfaces != null) { proxyFactory.setInterfaces(this.proxyInterfaces); } else if (!isProxyTargetClass()) { proxyFactory.setInterfaces(ClassUtils.getAllInterfacesForClass(targetSource.getTargetClass())); } this.proxy = getProxy(proxyFactory); } Spring 已经定义了一个transctionInterceptor作为拦截器或者AOP advice的实现,在IOC容器中定义的其他属性比如transactionManager和事务管理的属性都会传到已经定义好的 TransactionInterceptor那里去进行处理。以上反映了基本的Spring AOP的定义过程,其中pointcut和advice都已经定义好,同时也通过通知器配置到ProxyFactory中去了。 下面让我们回到TransactionProxyFactoryBean中看看TransactionAttributeSourceAdvisor是怎样定义的,这样我们可以理解具体的属性是怎样起作用,这里我们分析一下类TransactionAttributeSourceAdvisor: Java代码 1. public class TransactionAttributeSourceAdvisor extends AbstractPointcutAdvisor {    2.     //和其他Advisor一样,同样需要定义AOP中的用到的Interceptor和Pointcut    3.     //Interceptor使用传进来的TransactionInterceptor    4.     //而对于pointcut,这里定义了一个内部类,参见下面的代码      5.     private TransactionInterceptor transactionInterceptor;    6.    7.     private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut();    8.        9.     .........    10.     //定义的PointCut内部类    11.         private class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {    12.        .......    13.       //方法匹配的实现,使用了TransactionAttributeSource类    14.         public boolean matches(Method method, Class targetClass) {    15.             TransactionAttributeSource tas = getTransactionAttributeSource();    16.             //这里使用TransactionAttributeSource来对配置属性进行处理    17.             return (tas != null && tas.getTransactionAttribute(method, targetClass) != null);    18.         }    19.     ........省略了equal,hashcode,tostring的代码    20.     }   public class TransactionAttributeSourceAdvisor extends AbstractPointcutAdvisor { //和其他Advisor一样,同样需要定义AOP中的用到的Interceptor和Pointcut //Interceptor使用传进来的TransactionInterceptor //而对于pointcut,这里定义了一个内部类,参见下面的代码 private TransactionInterceptor transactionInterceptor; private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut(); ......... //定义的PointCut内部类 private class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable { ....... //方法匹配的实现,使用了TransactionAttributeSource类 public boolean matches(Method method, Class targetClass) { TransactionAttributeSource tas = getTransactionAttributeSource(); //这里使用TransactionAttributeSource来对配置属性进行处理 return (tas != null && tas.getTransactionAttribute(method, targetClass) != null); } ........省略了equal,hashcode,tostring的代码 } 这里我们看看属性值是怎样被读入的:AbstractFallbackTransactionAttributeSource负责具体的属性读入任务,我们可以有两种读入方式,比如annotation和直接配置.我们下面看看直接配置的读入方式,在Spring中同时对读入的属性值进行了缓存处理,这是一个decorator模式: Java代码 1. public final TransactionAttribute getTransactionAttribute(Method method, Class targetClass) {    2.     //这里先查一下缓存里有没有事务管理的属性配置,如果有从缓存中取得TransactionAttribute    3.     Object cacheKey = getCacheKey(method, targetClass);    4.     Object cached = this.cache.get(cacheKey);    5.     if (cached != null) {    6.         if (cached == NULL_TRANSACTION_ATTRIBUTE) {    7.             return null;    8.         }    9.         else {    10.             return (TransactionAttribute) cached;    11.         }    12.     }    13.     else {    14.         // 这里通过对方法和目标对象的信息来计算事务缓存属性    15.         TransactionAttribute txAtt = computeTransactionAttribute(method, targetClass);    16.         //把得到的事务缓存属性存到缓存中,下次可以直接从缓存中取得。    17.         if (txAtt == null) {    18.             this.cache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE);    19.         }    20.         else {    21.             ...........    22.             this.cache.put(cacheKey, txAtt);    23.         }    24.         return txAtt;    25.     }    26. }   public final TransactionAttribute getTransactionAttribute(Method method, Class targetClass) { //这里先查一下缓存里有没有事务管理的属性配置,如果有从缓存中取得TransactionAttribute Object cacheKey = getCacheKey(method, targetClass); Object cached = this.cache.get(cacheKey); if (cached != null) { if (cached == NULL_TRANSACTION_ATTRIBUTE) { return null; } else { return (TransactionAttribute) cached; } } else { // 这里通过对方法和目标对象的信息来计算事务缓存属性 TransactionAttribute txAtt = computeTransactionAttribute(method, targetClass); //把得到的事务缓存属性存到缓存中,下次可以直接从缓存中取得。 if (txAtt == null) { this.cache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE); } else { ........... this.cache.put(cacheKey, txAtt); } return txAtt; } } 别急,基本的处理在computeTransactionAttribute()中: Java代码 1. private TransactionAttribute computeTransactionAttribute(Method method, Class targetClass) {    2.     //这里检测是不是public方法    3.     if(allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {    4.         return null;    5.     }    6.        7.     Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);    8.        9.     // First try is the method in the target class.    10.     TransactionAttribute txAtt = findTransactionAttribute(findAllAttributes(specificMethod));    11.     if (txAtt != null) {    12.         return txAtt;    13.     }    14.    15.     // Second try is the transaction attribute on the target class.    16.     txAtt = findTransactionAttribute(findAllAttributes(specificMethod.getDeclaringClass()));    17.     if (txAtt != null) {    18.         return txAtt;    19.     }    20.    21.     if (specificMethod != method) {    22.         // Fallback is to look at the original method.    23.         txAtt = findTransactionAttribute(findAllAttributes(method));    24.         if (txAtt != null) {    25.             return txAtt;    26.         }    27.         // Last fallback is the class of the original method.    28.         return findTransactionAttribute(findAllAttributes(method.getDeclaringClass()));    29.     }    30.     return null;    31. }   private TransactionAttribute computeTransactionAttribute(Method method, Class targetClass) { //这里检测是不是public方法 if(allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) { return null; } Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass); // First try is the method in the target class. TransactionAttribute txAtt = findTransactionAttribute(findAllAttributes(specificMethod)); if (txAtt != null) { return txAtt; } // Second try is the transaction attribute on the target class. txAtt = findTransactionAttribute(findAllAttributes(specificMethod.getDeclaringClass())); if (txAtt != null) { return txAtt; } if (specificMethod != method) { // Fallback is to look at the original method. txAtt = findTransactionAttribute(findAllAttributes(method)); if (txAtt != null) { return txAtt; } // Last fallback is the class of the original method. return findTransactionAttribute(findAllAttributes(method.getDeclaringClass())); } return null; } 经过一系列的尝试我们可以通过findTransactionAttribute()通过调用findAllAttribute()得到TransactionAttribute的对象,如果返回的是null,这说明该方法不是我们需要事务处理的方法。 在完成把需要的通知器加到ProxyFactory中去的基础上,我们看看具体的看事务处理代码怎样起作用,在TransactionInterceptor中: Java代码 1. public Object invoke(final MethodInvocation invocation) throws Throwable {    2.     //这里得到目标对象    3.     Class targetClass = (invocation.getThis() != null ? invocation.getThis().getClass() : null);    4.    5.     //这里同样的通过判断是否能够得到TransactionAttribute来决定是否对当前方法进行事务处理,有可能该属性已经被缓存,    6.     //具体可以参考上面对getTransactionAttribute的分析,同样是通过TransactionAttributeSource    7.     final TransactionAttribute txAttr =    8.             getTransactionAttributeSource().getTransactionAttribute(invocation.getMethod(), targetClass);    9.     final String joinpointIdentification = methodIdentification(invocation.getMethod());    10.    11.     //这里判断我们使用了什么TransactionManager    12.     if (txAttr == null || !(getTransactionManager() instanceof CallbackPreferringPlatformTransactionManager)) {    13.         // 这里创建事务,同时把创建事务过程中得到的信息放到TransactionInfo中去    14.         TransactionInfo txInfo = createTransactionIfNecessary(txAttr, joinpointIdentification);    15.         Object retVal = null;    16.         try {    17.               retVal = invocation.proceed();    18.         }    19.         catch (Throwable ex) {    20.             // target invocation exception    21.             completeTransactionAfterThrowing(txInfo, ex);    22.             throw ex;    23.         }    24.         finally {    25.             cleanupTransactionInfo(txInfo);    26.         }    27.         commitTransactionAfterReturning(txInfo);    28.         return retVal;    29.     }    30.    31.     else {    32.         // 使用的是Spring定义的PlatformTransactionManager同时实现了回调接口,我们通过其回调函数完成事务处理,就像我们使用编程式事务处理一样。    33.         try {    34.             Object result = ((CallbackPreferringPlatformTransactionManager) getTransactionManager()).execute(txAttr,    35.                     new TransactionCallback() {    36.                         public Object doInTransaction(TransactionStatus status) {    37.                             //同样的需要一个TransactonInfo    38.                             TransactionInfo txInfo = prepareTransactionInfo(txAttr, joinpointIdentification, status);    39.                             try {    40.                                 return invocation.proceed();    41.                             }    42.                          .....这里省去了异常处理和事务信息的清理代码    43.                     });    44.          ...........    45.     }    46. }   public Object invoke(final MethodInvocation invocation) throws Throwable { //这里得到目标对象 Class targetClass = (invocation.getThis() != null ? invocation.getThis().getClass() : null); //这里同样的通过判断是否能够得到TransactionAttribute来决定是否对当前方法进行事务处理,有可能该属性已经被缓存, //具体可以参考上面对getTransactionAttribute的分析,同样是通过TransactionAttributeSource final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(invocation.getMethod(), targetClass); final String joinpointIdentification = methodIdentification(invocation.getMethod()); //这里判断我们使用了什么TransactionManager if (txAttr == null || !(getTransactionManager() instanceof CallbackPreferringPlatformTransactionManager)) { // 这里创建事务,同时把创建事务过程中得到的信息放到TransactionInfo中去 TransactionInfo txInfo = createTransactionIfNecessary(txAttr, joinpointIdentification); Object retVal = null; try { retVal = invocation.proceed(); } catch (Throwable ex) { // target invocation exception completeTransactionAfterThrowing(txInfo, ex); throw ex; } finally { cleanupTransactionInfo(txInfo); } commitTransactionAfterReturning(txInfo); return retVal; } else { // 使用的是Spring定义的PlatformTransactionManager同时实现了回调接口,我们通过其回调函数完成事务处理,就像我们使用编程式事务处理一样。 try { Object result = ((CallbackPreferringPlatformTransactionManager) getTransactionManager()).execute(txAttr, new TransactionCallback() { public Object doInTransaction(TransactionStatus status) { //同样的需要一个TransactonInfo TransactionInfo txInfo = prepareTransactionInfo(txAttr, joinpointIdentification, status); try { return invocation.proceed(); } .....这里省去了异常处理和事务信息的清理代码 }); ........... } } 这里面涉及到事务的创建,我们可以在TransactionAspectSupport实现的事务管理代码: Java代码 1. protected TransactionInfo createTransactionIfNecessary(    2.         TransactionAttribute txAttr, final String joinpointIdentification) {    3.    4.     // If no name specified, apply method identification as transaction name.    5.     if (txAttr != null && txAttr.getName() == null) {    6.         txAttr = new DelegatingTransactionAttribute(txAttr) {    7.             public String getName() {    8.                 return joinpointIdentification;    9.             }    10.         };    11.     }    12.    13.     TransactionStatus status = null;    14.     if (txAttr != null) {    15.     //这里使用了我们定义好的事务配置信息,有事务管理器来创建事务,同时返回TransactionInfo    16.         status = getTransactionManager().getTransaction(txAttr);    17.     }    18.     return prepareTransactionInfo(txAttr, joinpointIdentification, status);    19. }   protected TransactionInfo createTransactionIfNecessary( TransactionAttribute txAttr, final String joinpointIdentification) { // If no name specified, apply method identification as transaction name. if (txAttr != null && txAttr.getName() == null) { txAttr = new DelegatingTransactionAttribute(txAttr) { public String getName() { return joinpointIdentification; } }; } TransactionStatus status = null; if (txAttr != null) { //这里使用了我们定义好的事务配置信息,有事务管理器来创建事务,同时返回TransactionInfo status = getTransactionManager().getTransaction(txAttr); } return prepareTransactionInfo(txAttr, joinpointIdentification, status); } 首先通过TransactionManager得到需要的事务,事务的创建根据我们定义的事务配置决定,在 AbstractTransactionManager中给出一个标准的创建过程,当然创建什么样的事务还是需要具体的 PlatformTransactionManager来决定,但这里给出了创建事务的模板: Java代码 1. public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {    2.     Object transaction = doGetTransaction();    3.     ......    4.    5.     if (definition == null) {    6.         //如果事务信息没有被配置,我们使用Spring默认的配置方式    7.         definition = new DefaultTransactionDefinition();    8.     }    9.    10.     if (isExistingTransaction(transaction)) {    11.         // Existing transaction found -> check propagation behavior to find out how to behave.    12.         return handleExistingTransaction(definition, transaction, debugEnabled);    13.     }    14.    15.     // Check definition settings for new transaction.    16.     //下面就是使用配置信息来创建我们需要的事务;比如传播属性和同步属性等    17.     //最后把创建过程中的信息收集起来放到TransactionStatus中返回;      18.     if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {    19.         throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout());    20.     }    21.    22.     // No existing transaction found -> check propagation behavior to find out how to behave.    23.     if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {    24.         throw new IllegalTransactionStateException(    25.                 "Transaction propagation 'mandatory' but no existing transaction found");    26.     }    27.     else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||    28.             definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||    29.         definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {    30.         //这里是事务管理器创建事务的地方,并将创建过程中得到的信息放到TransactionStatus中去,包括创建出来的事务    31.         doBegin(transaction, definition);    32.         boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);    33.         return newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, null);    34.     }    35.     else {    36.         boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);    37.         return newTransactionStatus(definition, null, false, newSynchronization, debugEnabled, null);    38.     }    39. }   public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException { Object transaction = doGetTransaction(); ...... if (definition == null) { //如果事务信息没有被配置,我们使用Spring默认的配置方式 definition = new DefaultTransactionDefinition(); } if (isExistingTransaction(transaction)) { // Existing transaction found -> check propagation behavior to find out how to behave. return handleExistingTransaction(definition, transaction, debugEnabled); } // Check definition settings for new transaction. //下面就是使用配置信息来创建我们需要的事务;比如传播属性和同步属性等 //最后把创建过程中的信息收集起来放到TransactionStatus中返回; if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) { throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout()); } // No existing transaction found -> check propagation behavior to find out how to behave. if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) { throw new IllegalTransactionStateException( "Transaction propagation 'mandatory' but no existing transaction found"); } else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED || definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW || definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) { //这里是事务管理器创建事务的地方,并将创建过程中得到的信息放到TransactionStatus中去,包括创建出来的事务 doBegin(transaction, definition); boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER); return newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, null); } else { boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS); return newTransactionStatus(definition, null, false, newSynchronization, debugEnabled, null); } } 接着通过调用prepareTransactionInfo完成事务创建的准备,创建过程中得到的信息存储在TransactionInfo对象中进行传递同时把信息和当前线程绑定; Java代码 1. protected TransactionInfo prepareTransactionInfo(    2.         TransactionAttribute txAttr, String joinpointIdentification, TransactionStatus status) {    3.    4.     TransactionInfo txInfo = new TransactionInfo(txAttr, joinpointIdentification);    5.     if (txAttr != null) {    6.     .....    7.         // 同样的需要把在getTransaction中得到的TransactionStatus放到TransactionInfo中来。    8.         txInfo.newTransactionStatus(status);    9.     }    10.     else {    11.     .......    12.    }    13.    14.     // 绑定事务创建信息到当前线程    15.     txInfo.bindToThread();    16.     return txInfo;    17. }   protected TransactionInfo prepareTransactionInfo( TransactionAttribute txAttr, String joinpointIdentification, TransactionStatus status) { TransactionInfo txInfo = new TransactionInfo(txAttr, joinpointIdentification); if (txAttr != null) { ..... // 同样的需要把在getTransaction中得到的TransactionStatus放到TransactionInfo中来。 txInfo.newTransactionStatus(status); } else { ....... } // 绑定事务创建信息到当前线程 txInfo.bindToThread(); return txInfo; } 将创建事务的信息返回,然后看到其他的事务管理代码: Java代码 1. protected void commitTransactionAfterReturning(TransactionInfo txInfo) {    2.     if (txInfo != null && txInfo.hasTransaction()) {    3.         if (logger.isDebugEnabled()) {    4.             logger.debug("Invoking commit for transaction on " + txInfo.getJoinpointIdentification());    5.         }    6.         this.transactionManager.commit(txInfo.getTransactionStatus());    7.     }    8. }   protected void commitTransactionAfterReturning(TransactionInfo txInfo) { if (txInfo != null && txInfo.hasTransaction()) { if (logger.isDebugEnabled()) { logger.debug("Invoking commit for transaction on " + txInfo.getJoinpointIdentification()); } this.transactionManager.commit(txInfo.getTransactionStatus()); } } 通过transactionManager对事务进行处理,包括异常抛出和正常的提交事务,具体的事务管理器由用户程序设定。 Java代码 1. protected void completeTransactionAfterThrowing(TransactionInfo txInfo, Throwable ex) {    2.     if (txInfo != null && txInfo.hasTransaction()) {    3.         if (txInfo.transactionAttribute.rollbackOn(ex)) {    4.             ......    5.             try {    6.                 this.transactionManager.rollback(txInfo.getTransactionStatus());    7.             }    8.             ..........    9.   }    10.         else {    11.             .........    12.             try {    13.                 this.transactionManager.commit(txInfo.getTransactionStatus());    14.             }    15.    ...........    16. }    17.    18. protected void commitTransactionAfterReturning(TransactionInfo txInfo) {    19.     if (txInfo != null && txInfo.hasTransaction()) {    20.         ......    21.         this.transactionManager.commit(txInfo.getTransactionStatus());    22.     }    23. }   protected void completeTransactionAfterThrowing(TransactionInfo txInfo, Throwable ex) { if (txInfo != null && txInfo.hasTransaction()) { if (txInfo.transactionAttribute.rollbackOn(ex)) { ...... try { this.transactionManager.rollback(txInfo.getTransactionStatus()); } .......... } else { ......... try { this.transactionManager.commit(txInfo.getTransactionStatus()); } ........... } protected void commitTransactionAfterReturning(TransactionInfo txInfo) { if (txInfo != null && txInfo.hasTransaction()) { ...... this.transactionManager.commit(txInfo.getTransactionStatus()); } } Spring通过以上代码对transactionManager进行事务处理的过程进行了AOP包装,到这里我们看到为了方便客户实现声明式的事务处理,Spring还是做了许多工作的。如果说使用编程式事务处理,过程其实比较清楚,我们可以参考书中的例子: Java代码 1. TransactionDefinition td = new DefaultTransactionDefinition();    2. TransactionStatus status = transactionManager.getTransaction(td);    3. try{    4.       ......//这里是我们的业务方法    5. }catch (ApplicationException e) {    6.    transactionManager.rollback(status);    7.    throw e    8. }    9. transactionManager.commit(status);    10.  ........   TransactionDefinition td = new DefaultTransactionDefinition(); TransactionStatus status = transactionManager.getTransaction(td); try{ ......//这里是我们的业务方法 }catch (ApplicationException e) { transactionManager.rollback(status); throw e } transactionManager.commit(status); ........ 我们看到这里选取了默认的事务配置DefaultTransactionDefinition,同时在创建事物的过程中得到TransactionStatus,然后通过直接调用事务管理器的相关方法就能完成事务处理。 声明式事务处理也同样实现了类似的过程,只是因为采用了声明的方法,需要增加对属性的读取处理,并且需要把整个过程整合到Spring AOP框架中和IoC容器中去的过程。 下面我们选取一个具体的transactionManager - DataSourceTransactionManager来看看其中事务处理的实现: 同样的通过使用AbstractPlatformTransactionManager使用模板方法,这些都体现了对具体平台相关的事务管理器操作的封装,比如commit: Java代码 1. public final void commit(TransactionStatus status) throws TransactionException {    2.     ......    3.     DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;    4.     if (defStatus.isLocalRollbackOnly()) {    5.         ......    6.         processRollback(defStatus);    7.         return;    8.     }    9.          .......    10.         processRollback(defStatus);    11.     ......    12.     }    13.    14.     processCommit(defStatus);    15. }   public final void commit(TransactionStatus status) throws TransactionException { ...... DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status; if (defStatus.isLocalRollbackOnly()) { ...... processRollback(defStatus); return; } ....... processRollback(defStatus); ...... } processCommit(defStatus); } 通过对TransactionStatus的具体状态的判断,来决定具体的事务处理: Java代码 1. private void processCommit(DefaultTransactionStatus status) throws TransactionException {    2.     try {    3.         boolean beforeCompletionInvoked = false;    4.         try {    5.             triggerBeforeCommit(status);    6.             triggerBeforeCompletion(status);    7.             beforeCompletionInvoked = true;    8.             boolean globalRollbackOnly = false;    9.             if (status.isNewTransaction() || isFailEarlyOnGlobalRollbackOnly()) {    10.                 globalRollbackOnly = status.isGlobalRollbackOnly();    11.             }    12.             if (status.hasSavepoint()) {    13.             ........    14.                status.releaseHeldSavepoint();    15.             }    16.             else if (status.isNewTransaction()) {    17.             ......    18.                 doCommit(status);    19.             }    20.         .........    21. }   private void processCommit(DefaultTransactionStatus status) throws TransactionException { try { boolean beforeCompletionInvoked = false; try { triggerBeforeCommit(status); triggerBeforeCompletion(status); beforeCompletionInvoked = true; boolean globalRollbackOnly = false; if (status.isNewTransaction() || isFailEarlyOnGlobalRollbackOnly()) { globalRollbackOnly = status.isGlobalRollbackOnly(); } if (status.hasSavepoint()) { ........ status.releaseHeldSavepoint(); } else if (status.isNewTransaction()) { ...... doCommit(status); } ......... } 这些模板方法的实现由具体的transactionManager来实现,比如在DataSourceTransactionManager: Java代码 1. protected void doCommit(DefaultTransactionStatus status) {    2.     //这里得到存在TransactionInfo中已经创建好的事务    3.     DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();    4.    5.     //这里得到和事务绑定的数据库连接    6.     Connection con = txObject.getConnectionHolder().getConnection();    7.     ........    8.     try {    9.     //这里通过数据库连接来提交事务    10.         con.commit();    11.     }    12.    .......    13. }    14.    15. protected void doRollback(DefaultTransactionStatus status) {    16.     DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();    17.     Connection con = txObject.getConnectionHolder().getConnection();    18.     if (status.isDebug()) {    19.         logger.debug("Rolling back JDBC transaction on Connection [" + con + "]");    20.     }    21.     try {    22.     //这里通过数据库连接来回滚事务    23.         con.rollback();    24.     }    25.     catch (SQLException ex) {    26.         throw new TransactionSystemException("Could not roll back JDBC transaction", ex);    27.     }    28. }   protected void doCommit(DefaultTransactionStatus status) { //这里得到存在TransactionInfo中已经创建好的事务 DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction(); //这里得到和事务绑定的数据库连接 Connection con = txObject.getConnectionHolder().getConnection(); ........ try { //这里通过数据库连接来提交事务 con.commit(); } ....... } protected void doRollback(DefaultTransactionStatus status) { DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction(); Connection con = txObject.getConnectionHolder().getConnection(); if (status.isDebug()) { logger.debug("Rolling back JDBC transaction on Connection [" + con + "]"); } try { //这里通过数据库连接来回滚事务 con.rollback(); } catch (SQLException ex) { throw new TransactionSystemException("Could not roll back JDBC transaction", ex); } } 我们看到在DataSourceTransactionManager中最后还是交给connection来实现事务的提交和rollback。整个声明式事务处理是事务处理在Spring AOP中的应用,我们看到了一个很好的使用Spring AOP的例子,在Spring声明式事务处理的源代码中我们可以看到: 1.怎样封装各种不同平台下的事务处理代码 2.怎样读取属性值和结合事务处理代码来完成既定的事务处理策略 3.怎样灵活的使用SpringAOP框架。 如果能够结合前面的Spring AOP的源代码来学习,理解可能会更深刻些。 7 深入解析Spring架构与设计原理(二)AOP AOP联盟定义的AOP体系结构把与AOP相关的概念大致分为了由高到低、从使用到实现的三个层次。关于这个体系结构,个人的理解是这样的,从上往下,最高层是语言和开发环境,在这个环境中可以看到几个重要的概念:base可以视为待增强对象,或者说目标对象;aspect指切面,通常包含对于base的增强应用;configuration可以看成是一种编织或者说配置,通过在AOP体系中提供这个configuration配置环境,可以把base和aspect结合起来,从而完成切面对目标对象的编织实现。 对Spring平台或者说生态系统来说,AOP是Spring框架的核心功能模块之一。AOP与IOC容器的结合使用, 为应用开发或者Spring自身功能的扩展都提供了许多便利。Spring AOP的实现和其他特性的实现一样,非常丰富,除了可以使用Spring本身提供的AOP实现之外,还封装了业界优秀的AOP解决方案AspectJ来让应用使用。在这里,主要对Spring自身的AOP实现原理做一些解析;在这个AOP实现中,Spring充分利用了IOC容器Proxy代理对象以及AOP拦截器的功能特性,通过这些对AOP基本功能的封装机制,为用户提供了AOP的实现框架。所以,要了解这些AOP的基本实现,需要我们对Java 的Proxy机制有一些基本了解。 AOP实现的基本线索 AOP实现中,可以看到三个主要的步骤,一个是代理对象的生成,然后是拦截器的作用,然后是Aspect编织的实现。AOP框架的丰富,很大程度体现在这三个具体实现中,所具有的丰富的技术选择,以及如何实现与IOC容器的无缝结合。毕竟这也是一个非常核心的模块,需要满足不同的应用需求带来的解决方案需求。 在Spring AOP的实现原理中,我们主要举ProxyFactoryBean的实现作为例子和实现的基本线索进行分析;很大一个原因,是因为ProxyFactoryBean是在Spring IoC环境中,创建AOP应用的最底层方法,从中,可以看到一条实现AOP的基本线索。在ProxyFactoryBean中,它的AOP实现需要依赖JDK或者CGLIB提供的Proxy特性。从FactoryBean中获取对象,是从getObject()方法作为入口完成的。然后为proxy代理对象配置advisor链,这个配置是在initializeAdvisorChain方法中完成的;然后就为生成AOP代理对象做好了准备,生成代理对象如下所示: Java代码 1. private synchronized Object getSingletonInstance() {    2.     if (this.singletonInstance == null) {    3.         this.targetSource = freshTargetSource();    4.         if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {    5.             // Rely on AOP infrastructure to tell us what interfaces to proxy.    6.             Class targetClass = getTargetClass();    7.             if (targetClass == null) {    8.                 throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy");    9.             }    10.  // 这里设置代理对象的接口     setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));    11.         }    12.         // Initialize the shared singleton instance.    13.         super.setFrozen(this.freezeProxy);    14.         // 注意这里的方法会使用ProxyFactory来生成我们需要的Proxy    15.         this.singletonInstance = getProxy(createAopProxy());    16.     }    17.     return this.singletonInstance;    18. }    19. //使用createAopProxy返回的AopProxy来得到代理对象    20. protected Object getProxy(AopProxy aopProxy) {    21.     return aopProxy.getProxy(this.proxyClassLoader);    22. }   private synchronized Object getSingletonInstance() { if (this.singletonInstance == null) { this.targetSource = freshTargetSource(); if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) { // Rely on AOP infrastructure to tell us what interfaces to proxy. Class targetClass = getTargetClass(); if (targetClass == null) { throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy"); } // 这里设置代理对象的接口 setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader)); } // Initialize the shared singleton instance. super.setFrozen(this.freezeProxy); // 注意这里的方法会使用ProxyFactory来生成我们需要的Proxy this.singletonInstance = getProxy(createAopProxy()); } return this.singletonInstance; } //使用createAopProxy返回的AopProxy来得到代理对象 protected Object getProxy(AopProxy aopProxy) { return aopProxy.getProxy(this.proxyClassLoader); } 上面我们看到了在Spring中通过ProxyFactoryBean实现AOP功能的第一步,得到AopProxy代理对象的基本过程,下面我们看看AopProxy代理对象的拦截机制是怎样发挥作用,是怎样实现AOP功能的。我们知道,对代理对象的生成,有CGLIB和JDK两种生成方式,在CGLIB中,对拦截器设计是通过在Cglib2AopProxy的AopProxy代理对象生成的时候,在回调DynamicAdvisedInterceptor对象中实现的,这个回调的实现在intercept方法中完成。对于AOP是怎样完成对目标对象的增强的,这些实现是封装在AOP拦截器链中,由一个个具体的拦截器来完成的。具体拦截器的运行是在以下的代码实现中完成的,这些调用在ReflectiveMethodInvocation中。 Java代码 1. public Object proceed() throws Throwable {    2.     //  We start with an index of -1 and increment early.    3.     //如果拦截器链中的拦截器迭代调用完毕,这里开始调用target的函数,这个函数是通过反射机制完成的,具体实现在:AopUtils.invokeJoinpointUsingReflection方法里面。    4.     if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {    5.         return invokeJoinpoint();    6.     }    7.     //这里沿着定义好的 interceptorOrInterceptionAdvice链进行处理。    8.     Object interceptorOrInterceptionAdvice =    9.         this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);    10.     if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {    11.         // Evaluate dynamic method matcher here: static part will already have    12.         // been evaluated and found to match.    13.         //这里对拦截器进行动态匹配的的判断,还记得我们前面分析的pointcut吗?这里是触发进行匹配的地方,如果和定义的pointcut匹配,那么这个advice将会得到执行。    14.         InterceptorAndDynamicMethodMatcher dm =    15.             (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;    16.         if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {    17.             return dm.interceptor.invoke(this);    18.         }    19.         else {    20.             // Dynamic matching failed.    21.             // Skip this interceptor and invoke the next in the chain.    22.             // //如果不匹配,那么这个proceed会被递归调用,直到所有的拦截器都被运行过为止。    23.             return proceed();    24.         }    25.     }    26.     else {    27.         // It's an interceptor, so we just invoke it: The pointcut will have    28.         // been evaluated statically before this object was constructed.    29.         //如果是一个interceptor,直接调用这个interceptor对应的方法    30.         return((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);    31.     }    32. }   public Object proceed() throws Throwable { // We start with an index of -1 and increment early. //如果拦截器链中的拦截器迭代调用完毕,这里开始调用target的函数,这个函数是通过反射机制完成的,具体实现在:AopUtils.invokeJoinpointUsingReflection方法里面。 if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { return invokeJoinpoint(); } //这里沿着定义好的 interceptorOrInterceptionAdvice链进行处理。 Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex); if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) { // Evaluate dynamic method matcher here: static part will already have // been evaluated and found to match. //这里对拦截器进行动态匹配的的判断,还记得我们前面分析的pointcut吗?这里是触发进行匹配的地方,如果和定义的pointcut匹配,那么这个advice将会得到执行。 InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice; if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) { return dm.interceptor.invoke(this); } else { // Dynamic matching failed. // Skip this interceptor and invoke the next in the chain. // //如果不匹配,那么这个proceed会被递归调用,直到所有的拦截器都被运行过为止。 return proceed(); } } else { // It's an interceptor, so we just invoke it: The pointcut will have // been evaluated statically before this object was constructed. //如果是一个interceptor,直接调用这个interceptor对应的方法 return((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); } } 在调用拦截器的时候,我们接下去就可以看到对advice的通知的调用。而经过一系列的注册,适配的过程以后,拦截器在拦截的时候,会调用到预置好的一个通知适配器,设置通知拦截器,这是一系列Spring设计好为通知服务的类的一个,是最终完成通知拦截和实现的地方,非常的关键。比如,对MethodBeforeAdviceInterceptor的实现是这样的: Java代码 1. public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {    2.    3.     private MethodBeforeAdvice advice;    4.    5.    6.     /**   7.      * Create a new MethodBeforeAdviceInterceptor for the given advice.   8.      * @param advice the MethodBeforeAdvice to wrap   9.      */   10.     public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {    11.         Assert.notNull(advice, "Advice must not be null");    12.         this.advice = advice;    13.     }    14.     //这个invoke方法是拦截器的回调方法,会在代理对象的方法被调用的时候触发回调。    15.     public Object invoke(MethodInvocation mi) throws Throwable {    16.         this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );    17.         return mi.proceed();    18.     }    19. }   public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable { private MethodBeforeAdvice advice; /** * Create a new MethodBeforeAdviceInterceptor for the given advice. * @param advice the MethodBeforeAdvice to wrap */ public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) { Assert.notNull(advice, "Advice must not be null"); this.advice = advice; } //这个invoke方法是拦截器的回调方法,会在代理对象的方法被调用的时候触发回调。 public Object invoke(MethodInvocation mi) throws Throwable { this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() ); return mi.proceed(); } } 在代码中,可以看到,就是这里,会调用advice的before方法!这样就成功的完成了before通知的编织! 因为Spring AOP本身并不打算成为一个一统天下的AOP框架,秉持Spring的一贯设计理念,设想中的Spring设计目标应该是,致力于AOP框架与IOC容器的紧密集成,通过集成AOP技术为JavaEE应用开发中遇到的普遍问题提供解决方案,从而为AOP用户使用AOP技术提供最大的便利,从这个角度上为Java EE的应用开发人员服务。在没有使用第三方AOP解决方案的时候,Spring通过虚拟机的Proxy特性和CGLIB实现了AOP的基本功能,我想,如果有了Spring AOP实现原理的知识背景,再加上我们对源代码实现的认真解读,可以为我们了解其他AOP框架与IOC容器的集成原理,也打下了很好的基础,并真正了解一个AOP框架是在怎样实现的。 这还真是就是我们喜欢开源软件一个原因,有了源代码,软件就没有什么神秘的面纱了!本立而道生,多读源代码吧,或者找一本从源代码出发讲解软件实现的书来看看,就像以前我们学习操作系统,学习TCP/IP那样!一定会有长进的。 8 Spring源代码解析(七):Spring AOP中对拦截器调用的实现 前面我们分析了Spring AOP实现中得到Proxy对象的过程,下面我们看看在Spring AOP中拦截器链是怎样被调用的,也就是Proxy模式是怎样起作用的,或者说Spring是怎样为我们提供AOP功能的; 在JdkDynamicAopProxy中生成Proxy对象的时候: Java代码 1. return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);   return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); 这里的this参数对应的是InvocationHandler对象,这里我们的JdkDynamicAopProxy实现了这个接口,也就是说当Proxy对象的函数被调用的时候,这个InvocationHandler的invoke方法会被作为回调函数调用,下面我们看看这个方法的实现: Java代码 1. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {    2.     MethodInvocation invocation = null;    3.     Object oldProxy = null;    4.     boolean setProxyContext = false;    5.    6.     TargetSource targetSource = this.advised.targetSource;    7.     Class targetClass = null;    8.     Object target = null;    9.    10.     try {    11.         // Try special rules for equals() method and implementation of the    12.         // Advised AOP configuration interface.    13.    14.         if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {    15.             // What if equals throws exception!?    16.             // This class implements the equals(Object) method itself.    17.             return equals(args[0]) ? Boolean.TRUE : Boolean.FALSE;    18.         }    19.         if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {    20.             // This class implements the hashCode() method itself.    21.             return new Integer(hashCode());    22.         }    23.         if (Advised.class == method.getDeclaringClass()) {    24.             // service invocations on ProxyConfig with the proxy config    25.             return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);    26.         }    27.    28.         Object retVal = null;    29.    30.         if (this.advised.exposeProxy) {    31.             // make invocation available if necessary    32.             oldProxy = AopContext.setCurrentProxy(proxy);    33.             setProxyContext = true;    34.         }    35.    36.         // May be null. Get as late as possible to minimize the time we "own" the target,    37.         // in case it comes from a pool.    38.         // 这里是得到目标对象的地方,当然这个目标对象可能来自于一个实例池或者是一个简单的JAVA对象    39.         target = targetSource.getTarget();    40.         if (target != null) {    41.             targetClass = target.getClass();    42.         }    43.    44.         // get the interception chain for this method    45.         // 这里获得定义好的拦截器链    46.         List chain = this.advised.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(    47.                 this.advised, proxy, method, targetClass);    48.    49.         // Check whether we have any advice. If we don't, we can fallback on direct    50.         // reflective invocation of the target, and avoid creating a MethodInvocation.    51.         // 如果没有设定拦截器,那么我们就直接调用目标的对应方法    52.         if (chain.isEmpty()) {    53.             // We can skip creating a MethodInvocation: just invoke the target directly    54.             // Note that the final invoker must be an InvokerInterceptor so we know it does    55.             // nothing but a reflective operation on the target, and no hot swapping or fancy proxying    56.             retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args);    57.         }    58.         else {    59.             // We need to create a method invocation...    60.             // invocation = advised.getMethodInvocationFactory().getMethodInvocation(    61.             //         proxy, method, targetClass, target, args, chain, advised);    62.             // 如果有拦截器的设定,那么需要调用拦截器之后才调用目标对象的相应方法    63.             // 这里通过构造一个ReflectiveMethodInvocation来实现,下面我们会看这个ReflectiveMethodInvocation类    64.             invocation = new ReflectiveMethodInvocation(    65.                     proxy, target, method, args, targetClass, chain);    66.    67.             // proceed to the joinpoint through the interceptor chain    68.             // 这里通过ReflectiveMethodInvocation来调用拦截器链和相应的目标方法    69.             retVal = invocation.proceed();    70.         }    71.    72.         // massage return value if necessary    73.         if (retVal != null && retVal == target && method.getReturnType().isInstance(proxy)) {    74.             // Special case: it returned "this" and the return type of the method is type-compatible    75.             // Note that we can't help if the target sets    76.             // a reference to itself in another returned object.    77.             retVal = proxy;    78.         }    79.         return retVal;    80.     }    81.     finally {    82.         if (target != null && !targetSource.isStatic()) {    83.             // must have come from TargetSource    84.             targetSource.releaseTarget(target);    85.         }    86.    87.         if (setProxyContext) {    88.             // restore old proxy    89.             AopContext.setCurrentProxy(oldProxy);    90.         }    91.     }    92. }   public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { MethodInvocation invocation = null; Object oldProxy = null; boolean setProxyContext = false; TargetSource targetSource = this.advised.targetSource; Class targetClass = null; Object target = null; try { // Try special rules for equals() method and implementation of the // Advised AOP configuration interface. if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) { // What if equals throws exception!? // This class implements the equals(Object) method itself. return equals(args[0]) ? Boolean.TRUE : Boolean.FALSE; } if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { // This class implements the hashCode() method itself. return new Integer(hashCode()); } if (Advised.class == method.getDeclaringClass()) { // service invocations on ProxyConfig with the proxy config return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args); } Object retVal = null; if (this.advised.exposeProxy) { // make invocation available if necessary oldProxy = AopContext.setCurrentProxy(proxy); setProxyContext = true; } // May be null. Get as late as possible to minimize the time we "own" the target, // in case it comes from a pool. // 这里是得到目标对象的地方,当然这个目标对象可能来自于一个实例池或者是一个简单的JAVA对象 target = targetSource.getTarget(); if (target != null) { targetClass = target.getClass(); } // get the interception chain for this method // 这里获得定义好的拦截器链 List chain = this.advised.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice( this.advised, proxy, method, targetClass); // Check whether we have any advice. If we don't, we can fallback on direct // reflective invocation of the target, and avoid creating a MethodInvocation. // 如果没有设定拦截器,那么我们就直接调用目标的对应方法 if (chain.isEmpty()) { // We can skip creating a MethodInvocation: just invoke the target directly // Note that the final invoker must be an InvokerInterceptor so we know it does // nothing but a reflective operation on the target, and no hot swapping or fancy proxying retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args); } else { // We need to create a method invocation... // invocation = advised.getMethodInvocationFactory().getMethodInvocation( // proxy, method, targetClass, target, args, chain, advised); // 如果有拦截器的设定,那么需要调用拦截器之后才调用目标对象的相应方法 // 这里通过构造一个ReflectiveMethodInvocation来实现,下面我们会看这个ReflectiveMethodInvocation类 invocation = new ReflectiveMethodInvocation( proxy, target, method, args, targetClass, chain); // proceed to the joinpoint through the interceptor chain // 这里通过ReflectiveMethodInvocation来调用拦截器链和相应的目标方法 retVal = invocation.proceed(); } // massage return value if necessary if (retVal != null && retVal == target && method.getReturnType().isInstance(proxy)) { // Special case: it returned "this" and the return type of the method is type-compatible // Note that we can't help if the target sets // a reference to itself in another returned object. retVal = proxy; } return retVal; } finally { if (target != null && !targetSource.isStatic()) { // must have come from TargetSource targetSource.releaseTarget(target); } if (setProxyContext) { // restore old proxy AopContext.setCurrentProxy(oldProxy); } } } 我们先看看目标对象方法的调用,这里是通过AopUtils的方法调用 - 使用反射机制来对目标对象的方法进行调用: Java代码 1. public static Object invokeJoinpointUsingReflection(Object target, Method method, Object[] args)    2.     throws Throwable {    3.    4.     // Use reflection to invoke the method.    5.     // 利用放射机制得到相应的方法,并且调用invoke    6.     try {    7.         if (!Modifier.isPublic(method.getModifiers()) ||    8.                 !Modifier.isPublic(method.getDeclaringClass().getModifiers())) {    9.             method.setAccessible(true);    10.         }    11.         return method.invoke(target, args);    12.     }    13.     catch (InvocationTargetException ex) {    14.         // Invoked method threw a checked exception.    15.         // We must rethrow it. The client won't see the interceptor.    16.         throw ex.getTargetException();    17.     }    18.     catch (IllegalArgumentException ex) {    19.         throw new AopInvocationException("AOP configuration seems to be invalid: tried calling method [" +    20.                 method + "] on target [" + target + "]", ex);    21.     }    22.     catch (IllegalAccessException ex) {    23.         throw new AopInvocationException("Couldn't access method: " + method, ex);    24.     }    25. }   public static Object invokeJoinpointUsingReflection(Object target, Method method, Object[] args) throws Throwable { // Use reflection to invoke the method. // 利用放射机制得到相应的方法,并且调用invoke try { if (!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers())) { method.setAccessible(true); } return method.invoke(target, args); } catch (InvocationTargetException ex) { // Invoked method threw a checked exception. // We must rethrow it. The client won't see the interceptor. throw ex.getTargetException(); } catch (IllegalArgumentException ex) { throw new AopInvocationException("AOP configuration seems to be invalid: tried calling method [" + method + "] on target [" + target + "]", ex); } catch (IllegalAccessException ex) { throw new AopInvocationException("Couldn't access method: " + method, ex); } } 对拦截器链的调用处理是在ReflectiveMethodInvocation里实现的: Java代码 1. public Object proceed() throws Throwable {    2.     //    We start with an index of -1 and increment early.    3.     // 这里直接调用目标对象的方法,没有拦截器的调用或者拦截器已经调用完了,这个currentInterceptorIndex的初始值是0    4.     if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size()) {    5.         return invokeJoinpoint();    6.     }    7.    8.     Object interceptorOrInterceptionAdvice =    9.         this.interceptorsAndDynamicMethodMatchers.get(this.currentInterceptorIndex);    10.     if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {    11.         // Evaluate dynamic method matcher here: static part will already have    12.         // been evaluated and found to match.    13.         // 这里获得相应的拦截器,如果拦截器可以匹配的上的话,那就调用拦截器的invoke方法    14.         InterceptorAndDynamicMethodMatcher dm =    15.             (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;    16.         if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {    17.             return dm.interceptor.invoke(nextInvocation());    18.         }    19.         else {    20.             // Dynamic matching failed.    21.             // Skip this interceptor and invoke the next in the chain.    22.             // 如果拦截器匹配不上,那就调用下一个拦截器,这个时候拦截器链的位置指示后移并迭代调用当前的proceed方法    23.             this.currentInterceptorIndex++;    24.             return proceed();    25.         }    26.     }    27.     else {    28.         // It's an interceptor, so we just invoke it: The pointcut will have    29.         // been evaluated statically before this object was constructed.    30.         return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(nextInvocation());    31.     }    32. }   public Object proceed() throws Throwable { // We start with an index of -1 and increment early. // 这里直接调用目标对象的方法,没有拦截器的调用或者拦截器已经调用完了,这个currentInterceptorIndex的初始值是0 if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size()) { return invokeJoinpoint(); } Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(this.currentInterceptorIndex); if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) { // Evaluate dynamic method matcher here: static part will already have // been evaluated and found to match. // 这里获得相应的拦截器,如果拦截器可以匹配的上的话,那就调用拦截器的invoke方法 InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice; if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) { return dm.interceptor.invoke(nextInvocation()); } else { // Dynamic matching failed. // Skip this interceptor and invoke the next in the chain. // 如果拦截器匹配不上,那就调用下一个拦截器,这个时候拦截器链的位置指示后移并迭代调用当前的proceed方法 this.currentInterceptorIndex++; return proceed(); } } else { // It's an interceptor, so we just invoke it: The pointcut will have // been evaluated statically before this object was constructed. return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(nextInvocation()); } } 这里把当前的拦截器链以及在拦截器链的位置标志都clone到一个MethodInvocation对象了,作用是当前的拦截器执行完之后,会继续沿着得到这个拦截器链执行下面的拦截行为,也就是会迭代的调用上面这个proceed: Java代码 1. private ReflectiveMethodInvocation nextInvocation() throws CloneNotSupportedException {    2.     ReflectiveMethodInvocation invocation = (ReflectiveMethodInvocation) clone();    3.     invocation.currentInterceptorIndex = this.currentInterceptorIndex + 1;    4.     invocation.parent = this;    5.     return invocation;    6. }   private ReflectiveMethodInvocation nextInvocation() throws CloneNotSupportedException { ReflectiveMethodInvocation invocation = (ReflectiveMethodInvocation) clone(); invocation.currentInterceptorIndex = this.currentInterceptorIndex + 1; invocation.parent = this; return invocation; } 这里的nextInvocation就已经包含了当前的拦截链的基本信息,我们看到在Interceptor中的实现比如TransactionInterceptor的实现中: Java代码 1. public Object invoke(final MethodInvocation invocation) throws Throwable {    2.    ......//这里是TransactionInterceptor插入的事务处理代码,我们会在后面分析事务处理实现的时候进行分析    3.         try {    4.             //这里是对配置的拦截器链进行迭代处理的调用    5.             retVal = invocation.proceed();    6.         }    7.    ......//省略了和事务处理的异常处理代码 ,也是TransactionInterceptor插入的处理    8.       else {    9.         try {    10.             Object result = ((CallbackPreferringPlatformTransactionManager) getTransactionManager()).execute(txAttr,    11.                     new TransactionCallback() {    12.                         public Object doInTransaction(TransactionStatus status) {    13.                              //这里是TransactionInterceptor插入对事务处理的代码    14.                             TransactionInfo txInfo = prepareTransactionInfo(txAttr, joinpointIdentification, status);    15.                             //这里是对配置的拦截器链进行迭代处理的调用,接着顺着拦截器进行处理    16.                             try {                            17.                                 return invocation.proceed();    18.                             }    19.    ......//省略了和事务处理的异常处理代码 ,也是TransactionInterceptor插入的处理    20.    }   public Object invoke(final MethodInvocation invocation) throws Throwable { ......//这里是TransactionInterceptor插入的事务处理代码,我们会在后面分析事务处理实现的时候进行分析 try { //这里是对配置的拦截器链进行迭代处理的调用 retVal = invocation.proceed(); } ......//省略了和事务处理的异常处理代码 ,也是TransactionInterceptor插入的处理 else { try { Object result = ((CallbackPreferringPlatformTransactionManager) getTransactionManager()).execute(txAttr, new TransactionCallback() { public Object doInTransaction(TransactionStatus status) { //这里是TransactionInterceptor插入对事务处理的代码 TransactionInfo txInfo = prepareTransactionInfo(txAttr, joinpointIdentification, status); //这里是对配置的拦截器链进行迭代处理的调用,接着顺着拦截器进行处理 try { return invocation.proceed(); } ......//省略了和事务处理的异常处理代码 ,也是TransactionInterceptor插入的处理 } 从上面的分析我们看到了Spring AOP的基本实现,比如Spring怎样得到Proxy,怎样利用JAVA Proxy以及反射机制对用户定义的拦截器链进行处理。 9 Spring声明式事务管理源码解读之事务提交 简介:上次说到spring声明式事务管理的事务开始部分,按流程来讲,下面应该提交事务了, spring的声明式事务管理其实是比较复杂的,事实上这种复杂性正是由于事务本身的复杂性导致的,如果能用两三句话就把这部分内容说清楚是不现实的,也是不成熟的,而我对这部分的理解也可能是不全面的,还是那句话,希望大家和我一起把本贴的质量提交起来。 在下面的文章中,我讲会多次提到第一篇文章,第一篇文章的地址是:http://www.javaeye.com/topic/87426 如果要理解事务提交的话,理解事务开始是一个前提条件,所以请先看第一篇文章,再来看这篇 如果你仔细看下去,我想肯定是有很多收获,因为我们确实能从spring的代码和思想中学到很多东西。 正文: 其实俺的感觉就是事务提交要比事务开始复杂,看事务是否提交我们还是要回到TransactionInterceptor类的invoke方法 Java代码 1. public Object invoke(MethodInvocation invocation) throws Throwable {    2.         // Work out the target class: may be null.    3.         // The TransactionAttributeSource should be passed the target class    4.         // as well as the method, which may be from an interface    5.         Class targetClass = (invocation.getThis() != null) ? invocation.getThis().getClass() : null;    6.             7.         // Create transaction if necessary.    8.         TransactionInfo txInfo = createTransactionIfNecessary(invocation.getMethod(), targetClass);    9.    10.         Object retVal = null;    11.         try {    12.             // This is an around advice.    13.             // Invoke the next interceptor in the chain.    14.             // This will normally result in a target object being invoked.    15.             retVal = invocation.proceed();    16.         }    17.         catch (Throwable ex) {    18.             // target invocation exception    19.             doCloseTransactionAfterThrowing(txInfo, ex);    20.             throw ex;    21.         }    22.         finally {    23.             doFinally(txInfo);//业务方法出栈后必须先执行的一个方法    24.         }    25.         doCommitTransactionAfterReturning(txInfo);    26.         return retVal;    27.     }   public Object invoke(MethodInvocation invocation) throws Throwable { // Work out the target class: may be null. // The TransactionAttributeSource should be passed the target class // as well as the method, which may be from an interface Class targetClass = (invocation.getThis() != null) ? invocation.getThis().getClass() : null; // Create transaction if necessary. TransactionInfo txInfo = createTransactionIfNecessary(invocation.getMethod(), targetClass); Object retVal = null; try { // This is an around advice. // Invoke the next interceptor in the chain. // This will normally result in a target object being invoked. retVal = invocation.proceed(); } catch (Throwable ex) { // target invocation exception doCloseTransactionAfterThrowing(txInfo, ex); throw ex; } finally { doFinally(txInfo);//业务方法出栈后必须先执行的一个方法 } doCommitTransactionAfterReturning(txInfo); return retVal; } 其中的doFinally(txInfo)那一行很重要,也就是说不管如何,这个doFinally方法都是要被调用的,为什么它这么重要呢,举个例子: 我们还是以propregation_required来举例子吧,假设情况是这样的,AService中有一个方法调用了BService中的,这两个方法都处在事务体之中,他们的传播途径都是required。那么调用开始了,AService的方法首先入方法栈,并创建了TransactionInfo的实例,接着BService的方法入栈,又创建了一个TransactionInfo的实例,而重点要说明的是TransactionInfo是一个自身关联的内部类,第二个方法入栈时,会给新创建的TransactionInfo的实例设置一个属性,就是TransactionInfo对象中的private TransactionInfo oldTransactionInfo;属性,这个属性表明BService方法的创建的TransactionInfo对象是有一个old的transactionInfo对象的,这个oldTransactionInfo对象就是AService方法入栈时创建的TransactionInfo对象,我们还记得在createTransactionIfNecessary方法里有这样一个方法吧: Java代码 1. protected TransactionInfo createTransactionIfNecessary(Method method, Class targetClass) {    2.                 // We always bind the TransactionInfo to the thread, even if we didn't create    3.         // a new transaction here. This guarantees that the TransactionInfo stack    4.         // will be managed correctly even if no transaction was created by this aspect.    5.         txInfo.bindToThread();    6.         return txInfo;    7.     }    8.    9. 就是这个bindToThread()方法在作怪:    10. private void bindToThread() {    11.             // Expose current TransactionStatus, preserving any existing transactionStatus for    12.             // restoration after this transaction is complete.    13.             oldTransactionInfo = (TransactionInfo) currentTransactionInfo.get();    14.             currentTransactionInfo.set(this);    15.         }   protected TransactionInfo createTransactionIfNecessary(Method method, Class targetClass) { // We always bind the TransactionInfo to the thread, even if we didn't create // a new transaction here. This guarantees that the TransactionInfo stack // will be managed correctly even if no transaction was created by this aspect. txInfo.bindToThread(); return txInfo; } 就是这个bindToThread()方法在作怪: private void bindToThread() { // Expose current TransactionStatus, preserving any existing transactionStatus for // restoration after this transaction is complete. oldTransactionInfo = (TransactionInfo) currentTransactionInfo.get(); currentTransactionInfo.set(this); } 如果当前线程中已经有了一个TransactionInfo,则拿出来放到新建的transactionInfo对象的oldTransactionInfo属性中,然后再把新建的TransactionInfo设置到当前线程中。 这里有一个概念要搞清楚,就是TransactionInfo对象并不是表明事务状态的对象,表明事务状态的对象是TransactionStatus对象,这个对象同样是TransactionInfo的一个属性(这一点,我在前面一篇文章中并没有讲清楚)。 接下来BService中的那个方法返回,那么该它退栈了,它退栈后要做的就是doFinally方法,即把它的oldTransactionInfo设置到当前线程中(这个TransactionInfo对象显然就是AService方法入栈时创建的,怎么现在又要设置到线程中去呢,原因就是BService的方法出栈时并不提交事务,因为BService的传播途径是required,所以要把栈顶的方法所创建transactioninfo给设置到当前线程中),即调用AService的方法时所创建的TransactionInfo对象。那么在AServie的方法出栈时同样会设置TransactionInfo对象的oldTransactionInfo到当前线程,这时候显然oldTransactionInfo是空的,但AService中的方法会提交事务,所以它的oldTransactionInfo也应该是空了。 在这个小插曲之后,么接下来就应该是到提交事务了,之前在AService的方法出栈时,我们拿到了它入栈时创建的TransactionInfo对象,这个对象中包含了AService的方法事务状态。即TransactionStatus对象,很显然,太显然了,事务提交中的任何属性都和事务开始时的创建的对象息息相关,这个TransactionStatus对象哪里来的,我们再回头看看createTransactionIfNessary方法吧: Java代码 1. protected TransactionInfo createTransactionIfNecessary(Method method, Class targetClass) {    2.             txInfo.newTransactionStatus(this.transactionManager.getTransaction(txAttr));    3.         }   protected TransactionInfo createTransactionIfNecessary(Method method, Class targetClass) { txInfo.newTransactionStatus(this.transactionManager.getTransaction(txAttr)); } 再看看transactionManager.getTransaction(txAttr)方法吧: Java代码 1. public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {    2.             3.         else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||    4.                 definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||    5.             definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {    6.             if (debugEnabled) {    7.                 logger.debug("Creating new transaction with name [" + definition.getName() + "]");    8.             }    9.             doBegin(transaction, definition);    10.             boolean newSynchronization = (this.transactionSynchronization != SYNCHRONIZATION_NEVER);    11.             return newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, null);//注意这里的返回值,返回的就是一个TransactionStatus对象,这个对象表明了一个事务的状态,比如说是否是一个新的事务,事务是否已经结束,等等,这个对象是非常重要的,在事务提交的时候还是会用到它的。        }    12.             }    13.     }   public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException { else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED || definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW || definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) { if (debugEnabled) { logger.debug("Creating new transaction with name [" + definition.getName() + "]"); } doBegin(transaction, definition); boolean newSynchronization = (this.transactionSynchronization != SYNCHRONIZATION_NEVER); return newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, null);//注意这里的返回值,返回的就是一个TransactionStatus对象,这个对象表明了一个事务的状态,比如说是否是一个新的事务,事务是否已经结束,等等,这个对象是非常重要的,在事务提交的时候还是会用到它的。 } } } 还有一点需要说明的是,AService的方法在执行之前创建的transactionstatus确实是通过这个方法创建的,但是,BService的方法在执行之前创建transactionstatus的方法就与这个不一样了,下面会有详解。 回顾了事务开始时所调用的方法之后,是不是觉得现在对spring如何处理事务越来越清晰了呢。由于这么几个方法的调用,每个方法入栈之前它的事务状态就已经被设置好了。这个事务状态就是为了在方法出栈时被调用而准备的。 让我们再次回到BService中的方法出栈的那个时间段,看看spring都做了些什么,我们知道,后入栈的肯定是先出栈,BService中的方法后入栈,拿它肯定要先出栈了,它出栈的时候是要判断是否要提交事务,释放资源的,让我们来看看TransactionInterceptor的invoke的最后那个方法doCommitTransactionAfterReturning: Java代码 1. protected void doCommitTransactionAfterReturning(TransactionInfo txInfo) {    2.         if (txInfo != null && txInfo.hasTransaction()) {    3.             if (logger.isDebugEnabled()) {    4.                 logger.debug("Invoking commit for transaction on " + txInfo.joinpointIdentification());    5.             }    6.             this.transactionManager.commit(txInfo.getTransactionStatus());    7. //瞧:提交事务时用到了表明事务状态的那个TransactionStatus对象了。    8.         }    9.     }   protected void doCommitTransactionAfterReturning(TransactionInfo txInfo) { if (txInfo != null && txInfo.hasTransaction()) { if (logger.isDebugEnabled()) { logger.debug("Invoking commit for transaction on " + txInfo.joinpointIdentification()); } this.transactionManager.commit(txInfo.getTransactionStatus()); //瞧:提交事务时用到了表明事务状态的那个TransactionStatus对象了。 } } 看这个方法的名字就知道spring是要在业务方法出栈时提交事务,貌似很简单,但是事实是这样的吗? 我们接着往下看。 Java代码 1. public final void commit(TransactionStatus status) throws TransactionException {    2.         DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;    3.    4.         if (defStatus.isCompleted()) {    5.             throw new IllegalTransactionStateException(    6.                     "Transaction is already completed - do not call commit or rollback more than once per transaction");    7.         }    8.         if (defStatus.isLocalRollbackOnly()) {    9.             if (defStatus.isDebug()) {    10.                 logger.debug("Transactional code has requested rollback");    11.             }    12.             processRollback(defStatus);    13.             return;    14.         }    15.         if (!shouldCommitOnGlobalRollbackOnly() && defStatus.isGlobalRollbackOnly()) {    16.             if (defStatus.isDebug()) {    17.                 logger.debug("Global transaction is marked as rollback-only but transactional code requested commit");    18.             }    19.             processRollback(defStatus);    20.             throw new UnexpectedRollbackException(    21.                     "Transaction has been rolled back because it has been marked as rollback-only");    22.         }    23.    24.         processCommit(defStatus);    25.     }   public final void commit(TransactionStatus status) throws TransactionException { DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status; if (defStatus.isCompleted()) { throw new IllegalTransactionStateException( "Transaction is already completed - do not call commit or rollback more than once per transaction"); } if (defStatus.isLocalRollbackOnly()) { if (defStatus.isDebug()) { logger.debug("Transactional code has requested rollback"); } processRollback(defStatus); return; } if (!shouldCommitOnGlobalRollbackOnly() && defStatus.isGlobalRollbackOnly()) { if (defStatus.isDebug()) { logger.debug("Global transaction is marked as rollback-only but transactional code requested commit"); } processRollback(defStatus); throw new UnexpectedRollbackException( "Transaction has been rolled back because it has been marked as rollback-only"); } processCommit(defStatus); } 上面这段代码就是transactionmanager中的commit,但是看上去,它又把自己的职责分配给别人了,从代码里我们看到,如果事务已经结束了就抛异常,如果事务是rollbackonly的,那么就rollback吧,但是按照正常流程,我们还是想来看一下,事务的提交,就是processCommit(status)这个方法吧。 Java代码 1. private void processCommit(DefaultTransactionStatus status) throws TransactionException {    2.         try {    3.             boolean beforeCompletionInvoked = false;    4.             try {    5.                 triggerBeforeCommit(status);    6.                 triggerBeforeCompletion(status);    7.                 beforeCompletionInvoked = true;    8.                 if (status.hasSavepoint()) {    9.                     if (status.isDebug()) {    10.                         logger.debug("Releasing transaction savepoint");    11.                     }    12.                     status.releaseHeldSavepoint();    13.                 }    14.                 else if (status.isNewTransaction()) {//这个判断非常重要,下面会详细讲解这个判断的作用    15.                     if (status.isDebug()) {    16.                         logger.debug("Initiating transaction commit");    17.                     }    18.                     boolean globalRollbackOnly = status.isGlobalRollbackOnly();    19.                     doCommit(status);    20.                     // Throw UnexpectedRollbackException if we have a global rollback-only    21.                     // marker but still didn't get a corresponding exception from commit.    22.                     `````````````````````    23.     }   private void processCommit(DefaultTransactionStatus status) throws TransactionException { try { boolean beforeCompletionInvoked = false; try { triggerBeforeCommit(status); triggerBeforeCompletion(status); beforeCompletionInvoked = true; if (status.hasSavepoint()) { if (status.isDebug()) { logger.debug("Releasing transaction savepoint"); } status.releaseHeldSavepoint(); } else if (status.isNewTransaction()) {//这个判断非常重要,下面会详细讲解这个判断的作用 if (status.isDebug()) { logger.debug("Initiating transaction commit"); } boolean globalRollbackOnly = status.isGlobalRollbackOnly(); doCommit(status); // Throw UnexpectedRollbackException if we have a global rollback-only // marker but still didn't get a corresponding exception from commit. ````````````````````` } 我们注意到,在判断一个事务是否是新事务之前还有一个status.hasSavepoint()的判断,我认为这个判断事实上就是嵌套事务的判断,即判断这个事务是否是嵌套事务,如果不是嵌套事务,则再判断它是否是一个新事务,下面这段话就非常重要了,BService的中的方法是先出栈的,也就是说在调用BService之前的创建的那个事务状态对象在这里要先被判断,但是由于在调用BService的方法之前已经创建了一个Transaction和Session(假设我们使用的是hibernate3),这时候在创建第二个TransactionInfo(再强调一下吧,TransactionInfo并不是Transaction,Transaction是真正的事务对象,TransactionInfo只不过是一个辅助类而已,用来记录一系列状态的辅助类)的TransactionStatus的时候就会进入下面这个方法(当然在这之前会判断一下当前线程中是否已经有了一个SessionHolder对象,不清楚SessionHolder作用的同学情况第一篇文章),这个方法其实应该放到第一篇文章中讲的,但是想到如果不讲事务提交就讲这个方法好像没有这么贴切,废话少说,我们来看一下吧: Java代码 1. private TransactionStatus handleExistingTransaction(    2.             TransactionDefinition definition, Object transaction, boolean debugEnabled)    3.             throws TransactionException {    4.    5.         if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {    6.             throw new IllegalTransactionStateException(    7.                     "Transaction propagation 'never' but existing transaction found");    8.         }    9.    10.         if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {    11.             if (debugEnabled) {    12.                 logger.debug("Suspending current transaction");    13.             }    14.             Object suspendedResources = suspend(transaction);    15.             boolean newSynchronization = (this.transactionSynchronization == SYNCHRONIZATION_ALWAYS);    16.             return newTransactionStatus(    17.                     definition, null, false, newSynchronization, debugEnabled, suspendedResources);    18.         }    19.    20.         if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {    21.             if (debugEnabled) {    22.                 logger.debug("Suspending current transaction, creating new transaction with name [" +    23.                         definition.getName() + "]");    24.             }    25.             Object suspendedResources = suspend(transaction);    26.             doBegin(transaction, definition);    27.             boolean newSynchronization = (this.transactionSynchronization != SYNCHRONIZATION_NEVER);    28.             return newTransactionStatus(    29.                     definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);    30.         }    31.    32.         if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {    33.             if (!isNestedTransactionAllowed()) {    34.                 throw new NestedTransactionNotSupportedException(    35.                         "Transaction manager does not allow nested transactions by default - " +    36.                         "specify 'nestedTransactionAllowed' property with value 'true'");    37.             }    38.             if (debugEnabled) {    39.                 logger.debug("Creating nested transaction with name [" + definition.getName() + "]");    40.             }    41.             if (useSavepointForNestedTransaction()) {    42.                 // Create savepoint within existing Spring-managed transaction,    43.                 // through the SavepointManager API implemented by TransactionStatus.    44.                 // Usually uses JDBC 3.0 savepoints. Never activates Spring synchronization.    45.                 DefaultTransactionStatus status =    46.                         newTransactionStatus(definition, transaction, false, false, debugEnabled, null);    47.                 status.createAndHoldSavepoint();    48.                 return status;    49.             }    50.             else {    51.                 // Nested transaction through nested begin and commit/rollback calls.    52.                 // Usually only for JTA: Spring synchronization might get activated here    53.                 // in case of a pre-existing JTA transaction.    54.                 doBegin(transaction, definition);    55.                 boolean newSynchronization = (this.transactionSynchronization != SYNCHRONIZATION_NEVER);    56.                 return newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, null);    57.             }    58.         }    59.    60.         // Assumably PROPAGATION_SUPPORTS.    61.         if (debugEnabled) {    62.             logger.debug("Participating in existing transaction");    63.         }    64.         boolean newSynchronization = (this.transactionSynchronization != SYNCHRONIZATION_NEVER);    65.         return newTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null);    66.     }   private TransactionStatus handleExistingTransaction( TransactionDefinition definition, Object transaction, boolean debugEnabled) throws TransactionException { if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) { throw new IllegalTransactionStateException( "Transaction propagation 'never' but existing transaction found"); } if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) { if (debugEnabled) { logger.debug("Suspending current transaction"); } Object suspendedResources = suspend(transaction); boolean newSynchronization = (this.transactionSynchronization == SYNCHRONIZATION_ALWAYS); return newTransactionStatus( definition, null, false, newSynchronization, debugEnabled, suspendedResources); } if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) { if (debugEnabled) { logger.debug("Suspending current transaction, creating new transaction with name [" + definition.getName() + "]"); } Object suspendedResources = suspend(transaction); doBegin(transaction, definition); boolean newSynchronization = (this.transactionSynchronization != SYNCHRONIZATION_NEVER); return newTransactionStatus( definition, transaction, true, newSynchronization, debugEnabled, suspendedResources); } if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) { if (!isNestedTransactionAllowed()) { throw new NestedTransactionNotSupportedException( "Transaction manager does not allow nested transactions by default - " + "specify 'nestedTransactionAllowed' property with value 'true'"); } if (debugEnabled) { logger.debug("Creating nested transaction with name [" + definition.getName() + "]"); } if (useSavepointForNestedTransaction()) { // Create savepoint within existing Spring-managed transaction, // through the SavepointManager API implemented by TransactionStatus. // Usually uses JDBC 3.0 savepoints. Never activates Spring synchronization. DefaultTransactionStatus status = newTransactionStatus(definition, transaction, false, false, debugEnabled, null); status.createAndHoldSavepoint(); return status; } else { // Nested transaction through nested begin and commit/rollback calls. // Usually only for JTA: Spring synchronization might get activated here // in case of a pre-existing JTA transaction. doBegin(transaction, definition); boolean newSynchronization = (this.transactionSynchronization != SYNCHRONIZATION_NEVER); return newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, null); } } // Assumably PROPAGATION_SUPPORTS. if (debugEnabled) { logger.debug("Participating in existing transaction"); } boolean newSynchronization = (this.transactionSynchronization != SYNCHRONIZATION_NEVER); return newTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null); } 我们看到这个方法其实很明了,就是什么样的传播途径就创建什么样的transactionstatus,这个方法是在事务开始时被调用的,拿到我们之前举的例子中来看下,我们就恍然大悟了,原来,如果之前已经创建过事务,那个这个新建的transactionstauts就不应该是属于一个newTransaction了,所以第3个参数就是false了。 也就是说,在BService的方法出栈要要执行processcommit,但是由于BService的那个TransactionStatus不是一个newTransaction,所以它根本不会触发这个动作: Java代码 1. else if (status.isNewTransaction()) {//这个判断非常重要,下面会详细讲解这个判断的作用    2.                     if (status.isDebug()) {    3.                         logger.debug("Initiating transaction commit");    4.                     }    5. boolean globalRollbackOnly = status.isGlobalRollbackOnly();    6.                     doCommit(status);    7. }   else if (status.isNewTransaction()) {//这个判断非常重要,下面会详细讲解这个判断的作用 if (status.isDebug()) { logger.debug("Initiating transaction commit"); } boolean globalRollbackOnly = status.isGlobalRollbackOnly(); doCommit(status); } 也就是说在BService的方法出栈后,事务是不会提交的。这完全符合propragation_required的模型。 而在AService的方法出栈后,AService的方法所对应的那个TransactionStatus对象的newTransaction属性是为true的,即它会触发上面这段代码,进行真正的事务提交。让我们回想一下AService方法入栈之前创建TransactionStatus对象的情形吧: newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, null);看到第3个参数为true没有。 那么事务该提交了吧,事务的提交我想使用过hibernate的人都知道怎么提交了: txObject.getSessionHolder().getTransaction().commit(); 从当前线程中拿到SessionHolder,再拿到开始事务的那个Transaction对象,然后再commit事务。在没有用spring之前,我们经常这么做。呵呵。 好吧,我已经说到了spring声明式事务管理的70%到80%的内容了,这70%到80%的内容看上去还是非常容易理解的,如果把这两篇文章认真看过,我相信会有所收获的,剩下的内容需要靠大家自己去挖掘了,因为另剩下的内容可是需要花费很多时间的,因为牵扯的东西实在是太多了,呵呵。最后祝大家阅读愉快,因为我的文笔实在是让大家的眼睛受罪了。 10 Spring声明式事务管理源码解读之事务开始 Spring声明式事务管理源码解读 简介:事务是所有企业应用系统的核心,之前人们使用ejb的时候,容器事务管理(CMT),是slsb最令人称道的地方,据说很多人使用ejb,使用slsb就是为了cmt,但是spring出现之后,格局就变了,因为程序员又多了一种选择,就是声明式事务管理,声明式事务管理是基于AOP的,及AOP是它的底层特性,本文的目的就是为了和大家探讨一下spring的声明式事务管理,从源代码来分析它的背后的思想。(谢谢异常的建议,因为本文原来没有简介) 这个是我昨天在解决问题是看源码得一点体验,可能说得比较大概,希望大家多多讨论,把本贴得质量提高上去,因为spring实现的事务管理这部分我相信还是有点复杂的。一个人未必能想得十分清楚 在spring的声明式事务管理中,它是如何判定一个及标记一个方法是否应该是处在事务体之中呢。 首先要理解的是spring是如何来标记一个方法是否应该处在事务体之中的。有这样一个接口TransactionDefinition,其中定义了很多常量,它还有一个子接口TransactionAttribute,其中只有一个方法rollback。 TransactionDefinition中有很多常量定义,它们分别属于两种类型,传播途径和隔离级别 Java代码 1. /**   2.      * Support a current transaction, create a new one if none exists.   3.      * Analogous to EJB transaction attribute of the same name.   4.      * 

This is typically the default setting of a transaction definition.   5.      */   6.     int PROPAGATION_REQUIRED = 0;   /** * Support a current transaction, create a new one if none exists. * Analogous to EJB transaction attribute of the same name. *

This is typically the default setting of a transaction definition. */ int PROPAGATION_REQUIRED = 0; 当然其中也定义了隔离级别 /** Java代码 1. * A constant indicating that dirty reads are prevented; non-repeatable reads    2.  * and phantom reads can occur. This level only prohibits a transaction    3.  * from reading a row with uncommitted changes in it.    4.  * @see java.sql.Connection#TRANSACTION_READ_COMMITTED    5.  */    6. int ISOLATION_READ_COMMITTED   = Connection.TRANSACTION_READ_COMMITTED;   * A constant indicating that dirty reads are prevented; non-repeatable reads * and phantom reads can occur. This level only prohibits a transaction * from reading a row with uncommitted changes in it. * @see java.sql.Connection#TRANSACTION_READ_COMMITTED */ int ISOLATION_READ_COMMITTED = Connection.TRANSACTION_READ_COMMITTED; 同时还有两个对应的方法来得到这样的传播途径和隔离级别 Java代码 1. /**   2.      * Return the propagation behavior.   3.      * Must return one of the PROPAGATION constants.   4.      * @see #PROPAGATION_REQUIRED   5.      * @see org.springframework.transaction.support.TransactionSynchronizationManager#isActualTransactionActive()   6.      */   7.     int getPropagationBehavior();    8.    9.     /**   10.      * Return the isolation level.   11.      * Must return one of the ISOLATION constants.   12.      * 

Only makes sense in combination with PROPAGATION_REQUIRED or   13.      * PROPAGATION_REQUIRES_NEW.   14.      * 

Note that a transaction manager that does not support custom   15.      * isolation levels will throw an exception when given any other level   16.      * than ISOLATION_DEFAULT.   17.      * @see #ISOLATION_DEFAULT   18.      */   19.     int getIsolationLevel();   /** * Return the propagation behavior. * Must return one of the PROPAGATION constants. * @see #PROPAGATION_REQUIRED * @see org.springframework.transaction.support.TransactionSynchronizationManager#isActualTransactionActive() */ int getPropagationBehavior(); /** * Return the isolation level. * Must return one of the ISOLATION constants. *

Only makes sense in combination with PROPAGATION_REQUIRED or * PROPAGATION_REQUIRES_NEW. *

Note that a transaction manager that does not support custom * isolation levels will throw an exception when given any other level * than ISOLATION_DEFAULT. * @see #ISOLATION_DEFAULT */ int getIsolationLevel(); 这个接口有一个默认的实现DefaultTransactionDefinition。然后它还有子类,比如说 DefaultTransactionAttribute。Spring在判断一个方法是否需要事务体的时候其实是创建一个TransactionAttribute实现的实例. 有了上面的简单介绍就可以进入真正判断是否需要事务的地方了。这个方法在TransactionAspectSupport类里, Java代码 1. /**   2.      * Create a transaction if necessary.   3.      * @param method method about to execute   4.      * @param targetClass class the method is on   5.      * @return a TransactionInfo object, whether or not a transaction was created.   6.      * The hasTransaction() method on TransactionInfo can be used to tell if there   7.      * was a transaction created.   8.      */   9.     protected TransactionInfo createTransactionIfNecessary(Method method, Class targetClass) {    10.         // If the transaction attribute is null, the method is non-transactional.    11.         final TransactionAttribute sourceAttr =    12.                 this.transactionAttributeSource.getTransactionAttribute(method, targetClass);//就是在这里判断了这个方法的事务属性    13.         TransactionAttribute txAttr = sourceAttr;    14.    15.         // If no name specified, apply method identification as transaction name.    16.         if (txAttr != null && txAttr.getName() == null) {    17.             final String name = methodIdentification(method);    18.             txAttr = new DelegatingTransactionAttribute(sourceAttr) {    19.                 public String getName() {    20.                     return name;    21.                 }    22.             };    23.         }    24.    25.         TransactionInfo txInfo = new TransactionInfo(txAttr, method);    26. //TransactionInfo是TransactionAspectSupport的一个内部类,它的主要功能是记录方法和对应的事务属性    27.         if (txAttr != null) {    28.             // We need a transaction for this method    29.             if (logger.isDebugEnabled()) {    30.                 logger.debug("Getting transaction for " + txInfo.joinpointIdentification());    31.             }    32.    33.             // The transaction manager will flag an error if an incompatible tx already exists    34.             txInfo.newTransactionStatus(this.transactionManager.getTransaction(txAttr));//这个方法要仔细的看    35.         }    36.         else {    37.             // The TransactionInfo.hasTransaction() method will return    38.             // false. We created it only to preserve the integrity of    39.             // the ThreadLocal stack maintained in this class.    40.             if (logger.isDebugEnabled())    41.                 logger.debug("Don't need to create transaction for [" + methodIdentification(method) +    42.                         "]: this method isn't transactional");    43.         }    44.    45.         // We always bind the TransactionInfo to the thread, even if we didn't create    46.         // a new transaction here. This guarantees that the TransactionInfo stack    47.         // will be managed correctly even if no transaction was created by this aspect.    48.         txInfo.bindToThread();    49.         return txInfo;    50.     }   /** * Create a transaction if necessary. * @param method method about to execute * @param targetClass class the method is on * @return a TransactionInfo object, whether or not a transaction was created. * The hasTransaction() method on TransactionInfo can be used to tell if there * was a transaction created. */ protected TransactionInfo createTransactionIfNecessary(Method method, Class targetClass) { // If the transaction attribute is null, the method is non-transactional. final TransactionAttribute sourceAttr = this.transactionAttributeSource.getTransactionAttribute(method, targetClass);//就是在这里判断了这个方法的事务属性 TransactionAttribute txAttr = sourceAttr; // If no name specified, apply method identification as transaction name. if (txAttr != null && txAttr.getName() == null) { final String name = methodIdentification(method); txAttr = new DelegatingTransactionAttribute(sourceAttr) { public String getName() { return name; } }; } TransactionInfo txInfo = new TransactionInfo(txAttr, method); //TransactionInfo是TransactionAspectSupport的一个内部类,它的主要功能是记录方法和对应的事务属性 if (txAttr != null) { // We need a transaction for this method if (logger.isDebugEnabled()) { logger.debug("Getting transaction for " + txInfo.joinpointIdentification()); } // The transaction manager will flag an error if an incompatible tx already exists txInfo.newTransactionStatus(this.transactionManager.getTransaction(txAttr));//这个方法要仔细的看 } else { // The TransactionInfo.hasTransaction() method will return // false. We created it only to preserve the integrity of // the ThreadLocal stack maintained in this class. if (logger.isDebugEnabled()) logger.debug("Don't need to create transaction for [" + methodIdentification(method) + "]: this method isn't transactional"); } // We always bind the TransactionInfo to the thread, even if we didn't create // a new transaction here. This guarantees that the TransactionInfo stack // will be managed correctly even if no transaction was created by this aspect. txInfo.bindToThread(); return txInfo; } TransactionInfo是TransactionAspectSupport的一个内部类,它的主要功能是记录方法和对应的事务属性,在上面这个方法的最后,这个TransactionInfo对象被保存到当前线程中。 而这个方法会在事务拦截器TransactionInterceptor中被调用,TransactionInterceptor实际上是TransactionAspectSupport的子类,看看其中的invoke方法: Java代码 1. // Work out the target class: may be null.    2.         // The TransactionAttributeSource should be passed the target class    3.         // as well as the method, which may be from an interface    4.         Class targetClass = (invocation.getThis() != null) ? invocation.getThis().getClass() : null;    5.             6.         // Create transaction if necessary.    7.         TransactionInfo txInfo = createTransactionIfNecessary(invocation.getMethod(), targetClass);    8.    9.         Object retVal = null;    10.         try {    11.             // This is an around advice.    12.             // Invoke the next interceptor in the chain.    13.             // This will normally result in a target object being invoked.    14.             retVal = invocation.proceed();    15.         }    16.         catch (Throwable ex) {    17.             // target invocation exception    18.             doCloseTransactionAfterThrowing(txInfo, ex);    19.             throw ex;    20.         }    21.         finally {    22.             doFinally(txInfo);    23.         }    24.         doCommitTransactionAfterReturning(txInfo);//在这里执行方法结束之后需要的操作    25.         return retVal;   // Work out the target class: may be null. // The TransactionAttributeSource should be passed the target class // as well as the method, which may be from an interface Class targetClass = (invocation.getThis() != null) ? invocation.getThis().getClass() : null; // Create transaction if necessary. TransactionInfo txInfo = createTransactionIfNecessary(invocation.getMethod(), targetClass); Object retVal = null; try { // This is an around advice. // Invoke the next interceptor in the chain. // This will normally result in a target object being invoked. retVal = invocation.proceed(); } catch (Throwable ex) { // target invocation exception doCloseTransactionAfterThrowing(txInfo, ex); throw ex; } finally { doFinally(txInfo); } doCommitTransactionAfterReturning(txInfo);//在这里执行方法结束之后需要的操作 return retVal; 这个方法就如同一般的interceptor需要实现的方法一样。只不过在这个方法里判断被反射的方法是否需要事务。 接着我们重点再回头看一下createTransactionIfNecessary方法里的这一句: txInfo.newTransactionStatus(this.transactionManager.getTransaction(txAttr)); 接着我们就应该去看看这个getTransaction方法了,假设我们是使用hibernate3,其他类似。看getTransaction之前我们来看一下这两类和一个接口 接口PlatformTransactionManager 抽象类public abstract class AbstractPlatformTransactionManager implements PlatformTransactionManager 类public class HibernateTransactionManager extends AbstractPlatformTransactionManager,很明显,这里有一个方法模板模式。 那我们看一下AbstractPlatformTransactionManager中得getTransaction方法: Java代码 1. public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {    2.         Object transaction = doGetTransaction();//抽象方法,也需要子类实现,这个方法同样很重要    3.    4.         // Cache debug flag to avoid repeated checks.    5.         boolean debugEnabled = logger.isDebugEnabled();    6.         if (debugEnabled) {    7.             logger.debug("Using transaction object [" + transaction + "]");    8.         }    9.    10.         if (definition == null) {    11.             // Use defaults if no transaction definition given.    12.             definition = new DefaultTransactionDefinition();    13.         }    14.    15.         if (isExistingTransaction(transaction)) {    16.             // Existing transaction found -> check propagation behavior to find out how to behave.    17.             return handleExistingTransaction(definition, transaction, debugEnabled);    18.         }    19.    20.         // Check definition settings for new transaction.    21.         if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {    22.             throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout());    23.         }    24.    25.         // No existing transaction found -> check propagation behavior to find out how to behave.    26.         if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {    27.             throw new IllegalTransactionStateException(    28.                     "Transaction propagation 'mandatory' but no existing transaction found");    29.         }    30.         else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||    31.                 definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||    32.             definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {    33.             if (debugEnabled) {    34.                 logger.debug("Creating new transaction with name [" + definition.getName() + "]");    35.             }    36.             doBegin(transaction, definition);    37.             boolean newSynchronization = (this.transactionSynchronization != SYNCHRONIZATION_NEVER);    38.             return newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, null);    39.         }    40.         else {    41.             // Create "empty" transaction: no actual transaction, but potentially synchronization.    42.             boolean newSynchronization = (this.transactionSynchronization == SYNCHRONIZATION_ALWAYS);    43.             return newTransactionStatus(definition, null, false, newSynchronization, debugEnabled, null);    44.         }    45.     }   public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException { Object transaction = doGetTransaction();//抽象方法,也需要子类实现,这个方法同样很重要 // Cache debug flag to avoid repeated checks. boolean debugEnabled = logger.isDebugEnabled(); if (debugEnabled) { logger.debug("Using transaction object [" + transaction + "]"); } if (definition == null) { // Use defaults if no transaction definition given. definition = new DefaultTransactionDefinition(); } if (isExistingTransaction(transaction)) { // Existing transaction found -> check propagation behavior to find out how to behave. return handleExistingTransaction(definition, transaction, debugEnabled); } // Check definition settings for new transaction. if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) { throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout()); } // No existing transaction found -> check propagation behavior to find out how to behave. if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) { throw new IllegalTransactionStateException( "Transaction propagation 'mandatory' but no existing transaction found"); } else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED || definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW || definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) { if (debugEnabled) { logger.debug("Creating new transaction with name [" + definition.getName() + "]"); } doBegin(transaction, definition); boolean newSynchronization = (this.transactionSynchronization != SYNCHRONIZATION_NEVER); return newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, null); } else { // Create "empty" transaction: no actual transaction, but potentially synchronization. boolean newSynchronization = (this.transactionSynchronization == SYNCHRONIZATION_ALWAYS); return newTransactionStatus(definition, null, false, newSynchronization, debugEnabled, null); } } 上面的代码很多地方都有解释,所以很好理解,这段代码的关键部分在doBegin(transaction,definition)这里(这是一个抽象方法,子类必须实现这个方法, 具体依赖于抽象,这个是对方法模板模式的一个概括。),前面讲到我们假设是使用hibernate,那么就看看HibernateTransactionManager这个类吧,doBegin里的参数1,transaction其实是HibernateTransactionObject的一个实例,这个实例里主要存放的就是sessionholder,sessionholder里存放的就是开始事务的session和transaction对象,如果之前没有sessionholder存放到线程中,那么这个HibernateTransactionObject的实例的属性其实是空的,这一点可以在doBegin方法的实现中看出来 Java代码 1. protected void doBegin(Object transaction, TransactionDefinition definition) {    2.         if (getDataSource() != null && TransactionSynchronizationManager.hasResource(getDataSource())) {    3.             throw new IllegalTransactionStateException(    4.                     "Pre-bound JDBC Connection found - HibernateTransactionManager does not support " +    5.                     "running within DataSourceTransactionManager if told to manage the DataSource itself. " +    6.                     "It is recommended to use a single HibernateTransactionManager for all transactions " +    7.                     "on a single DataSource, no matter whether Hibernate or JDBC access.");    8.         }    9.    10.         Session session = null;    11.    12.         try {    13.             HibernateTransactionObject txObject = (HibernateTransactionObject) transaction;    14.             if (txObject.getSessionHolder() == null) {    15.                 Interceptor entityInterceptor = getEntityInterceptor();    16.                 Session newSession = (entityInterceptor != null ?    17.                         getSessionFactory().openSession(entityInterceptor) : getSessionFactory().openSession());    18.                 if (logger.isDebugEnabled()) {    19.                     logger.debug("Opened new Session [" + newSession + "] for Hibernate transaction");    20.                 }    21.                 txObject.setSessionHolder(new SessionHolder(newSession), true);   protected void doBegin(Object transaction, TransactionDefinition definition) { if (getDataSource() != null && TransactionSynchronizationManager.hasResource(getDataSource())) { throw new IllegalTransactionStateException( "Pre-bound JDBC Connection found - HibernateTransactionManager does not support " + "running within DataSourceTransactionManager if told to manage the DataSource itself. " + "It is recommended to use a single HibernateTransactionManager for all transactions " + "on a single DataSource, no matter whether Hibernate or JDBC access."); } Session session = null; try { HibernateTransactionObject txObject = (HibernateTransactionObject) transaction; if (txObject.getSessionHolder() == null) { Interceptor entityInterceptor = getEntityInterceptor(); Session newSession = (entityInterceptor != null ? getSessionFactory().openSession(entityInterceptor) : getSessionFactory().openSession()); if (logger.isDebugEnabled()) { logger.debug("Opened new Session [" + newSession + "] for Hibernate transaction"); } txObject.setSessionHolder(new SessionHolder(newSession), true); }//我们看到,如果传进来的transaction中并没有存放sessionholder,那么就新建一个session,放到新的sessionholder中,再放到HibernateTransactionObject的实例中去,顺便说一下,这个变量的名字取得真是差,虽然是Juergen Hoeller写的,也要批一下,搞得别人会以为是Transaction的实例 Java代码 1. txObject.getSessionHolder().setSynchronizedWithTransaction(true);    2.             session = txObject.getSessionHolder().getSession();    3.    4.             Connection con = session.connection();    5.             Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);    6.             txObject.setPreviousIsolationLevel(previousIsolationLevel);    7.    8.             if (definition.isReadOnly() && txObject.isNewSessionHolder()) {    9.                 // Just set to NEVER in case of a new Session for this transaction.    10.                 session.setFlushMode(FlushMode.NEVER);    11.             }//如果是只读事务,并且sessionholder是新建的,那么就设置hibernate的flushmode为never    12.    13.             if (!definition.isReadOnly() && !txObject.isNewSessionHolder()) {    14.                 // We need AUTO or COMMIT for a non-read-only transaction.    15.                 FlushMode flushMode = session.getFlushMode();    16.                 if (FlushMode.NEVER.equals(flushMode)) {    17.                     session.setFlushMode(FlushMode.AUTO);    18. //如果session的flushmode是nerver,就设置为auto,因为如果事务定义成非readonly,那么这个session一定是可以flush的    19.                     txObject.getSessionHolder().setPreviousFlushMode(flushMode);    20.                 }    21.             }    22.    23.             // Add the Hibernate transaction to the session holder.    24.             txObject.getSessionHolder().setTransaction(session.beginTransaction());//开始一个事务,并把这个事务对象放到sessionholder中,随后这个sessionholder会通过threadlocal放到线程中,以供在commit时使用    25.    26.             // Register transaction timeout.    27.             if (definition.getTimeout() != TransactionDefinition.TIMEOUT_DEFAULT) {    28.                 txObject.getSessionHolder().setTimeoutInSeconds(definition.getTimeout());//设置超时时间,如果其超时时间为-1,则不进行设置,如果不是-1,那么超时时间是这样设置的new Date(System.currentTimeMillis() + millis*1000);既程序员在配置文件中指定的其实是秒数    29.             }    30.    31.             // Register the Hibernate Session's JDBC Connection for the DataSource, if set.    32.             if (getDataSource() != null) {    33.                 ConnectionHolder conHolder = new ConnectionHolder(con);    34.                 if (definition.getTimeout() != TransactionDefinition.TIMEOUT_DEFAULT) {    35.                     conHolder.setTimeoutInSeconds(definition.getTimeout());    36.                 }    37.                 if (logger.isDebugEnabled()) {    38.                     logger.debug("Exposing Hibernate transaction as JDBC transaction [" + con + "]");    39.                 }    40.                 TransactionSynchronizationManager.bindResource(getDataSource(), conHolder);    41.                 txObject.setConnectionHolder(conHolder);    42.             }    43.    44.             // Bind the session holder to the thread.    45.             if (txObject.isNewSessionHolder()) {    46.                 TransactionSynchronizationManager.bindResource(getSessionFactory(), txObject.getSessionHolder());//如果是新的sessionholder则绑定到线程。这样在进入方法栈中的下一个方法时就能得到整个sessionholder了,connectionholder亦是如此    47.             }    48.         }    49. catch (Exception ex) {    50.             SessionFactoryUtils.releaseSession(session, getSessionFactory());//如果抛出异常就释放这个session,这个操作还会在后面出现    51.             throw new CannotCreateTransactionException("Could not open Hibernate Session for transaction", ex);    52.         }    53.     }   txObject.getSessionHolder().setSynchronizedWithTransaction(true); session = txObject.getSessionHolder().getSession(); Connection con = session.connection(); Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition); txObject.setPreviousIsolationLevel(previousIsolationLevel); if (definition.isReadOnly() && txObject.isNewSessionHolder()) { // Just set to NEVER in case of a new Session for this transaction. session.setFlushMode(FlushMode.NEVER); }//如果是只读事务,并且sessionholder是新建的,那么就设置hibernate的flushmode为never if (!definition.isReadOnly() && !txObject.isNewSessionHolder()) { // We need AUTO or COMMIT for a non-read-only transaction. FlushMode flushMode = session.getFlushMode(); if (FlushMode.NEVER.equals(flushMode)) { session.setFlushMode(FlushMode.AUTO); //如果session的flushmode是nerver,就设置为auto,因为如果事务定义成非readonly,那么这个session一定是可以flush的 txObject.getSessionHolder().setPreviousFlushMode(flushMode); } } // Add the Hibernate transaction to the session holder. txObject.getSessionHolder().setTransaction(session.beginTransaction());//开始一个事务,并把这个事务对象放到sessionholder中,随后这个sessionholder会通过threadlocal放到线程中,以供在commit时使用 // Register transaction timeout. if (definition.getTimeout() != TransactionDefinition.TIMEOUT_DEFAULT) { txObject.getSessionHolder().setTimeoutInSeconds(definition.getTimeout());//设置超时时间,如果其超时时间为-1,则不进行设置,如果不是-1,那么超时时间是这样设置的new Date(System.currentTimeMillis() + millis*1000);既程序员在配置文件中指定的其实是秒数 } // Register the Hibernate Session's JDBC Connection for the DataSource, if set. if (getDataSource() != null) { ConnectionHolder conHolder = new ConnectionHolder(con); if (definition.getTimeout() != TransactionDefinition.TIMEOUT_DEFAULT) { conHolder.setTimeoutInSeconds(definition.getTimeout()); } if (logger.isDebugEnabled()) { logger.debug("Exposing Hibernate transaction as JDBC transaction [" + con + "]"); } TransactionSynchronizationManager.bindResource(getDataSource(), conHolder); txObject.setConnectionHolder(conHolder); } // Bind the session holder to the thread. if (txObject.isNewSessionHolder()) { TransactionSynchronizationManager.bindResource(getSessionFactory(), txObject.getSessionHolder());//如果是新的sessionholder则绑定到线程。这样在进入方法栈中的下一个方法时就能得到整个sessionholder了,connectionholder亦是如此 } } catch (Exception ex) { SessionFactoryUtils.releaseSession(session, getSessionFactory());//如果抛出异常就释放这个session,这个操作还会在后面出现 throw new CannotCreateTransactionException("Could not open Hibernate Session for transaction", ex); } } 通过以上对代码的注释可以知道,如果给service设置声明式事务管理,假设事务传播途径为required,然后一个service调用另一个service时,他们其实是共用一个session,原则是没有就创建,有就不创建,并返回之前已创建的session和transaction。也就是说spring通过threadlocal把session和对应的transaction放到线程之中,保证了在整个方法栈的任何一个地方都能得到同一个session和transaction。 所以如果你的方法在事务体之内,那么你只要通过hibernatesupportdao或者hibernatetemplate来得到session的话,那这个session一定是开始事务的那个session,这个得到session的主要方法在SessionFactoryUtils里,我们来看一下 (这里还有一个小细节,public abstract class SessionFactoryUtils ,Juergen Hoeller在写工具类的时候为了不能让其有实例使用的是abstract,而我们一般的做法是final类加private的构造方法,看上去不怎么雅观,看看源代码还是能学习到不少写代码的技巧的,这里还有一个插曲,上次feiing还说java为什么不能弄成final和abstract同时存在呢,这样就可以确保既不会有实例产生,也不能继承了,呵呵) 在SessionFactoryUtils的doGetSession里写到,如果当前线程有绑定session,则返回这个session,如果没有绑定session,则看是否允许创建(既allowCreate这个参数是true还是false,这个参数将会在很多地方设计到,比如说hibernatetemplate和hibernatedaosupport里都有),如果不允许创建就抛出一个原始的hibernateException,举个例子,如果你没有给某个service方法配置声明式事务管理,而却要在这个service所调用的dao里得到当前得session,这样就会抛这个错了: Java代码 1. if (method.getName().equals("getCurrentSession")) {    2.                 // Handle getCurrentSession method: return transactional Session, if any.    3.                 try {    4.                     return SessionFactoryUtils.doGetSession((SessionFactory) proxy, false);    5. //最后一个参数是false,说明这个方法不能返回一个新的session,没有就抛异常    6.                 }    7.                 catch (IllegalStateException ex) {    8.                     throw new HibernateException(ex.getMessage());    9.                 }    10.             }   if (method.getName().equals("getCurrentSession")) { // Handle getCurrentSession method: return transactional Session, if any. try { return SessionFactoryUtils.doGetSession((SessionFactory) proxy, false); //最后一个参数是false,说明这个方法不能返回一个新的session,没有就抛异常 } catch (IllegalStateException ex) { throw new HibernateException(ex.getMessage()); } } 到这里事务开始部分基本就结束了

下载文档到电脑,查找使用更方便

文档的实际排版效果,会与网站的显示效果略有不同!!

需要 2 金币 [ 分享文档获得金币 ] 0 人已下载

下载文档