|
常用链接
留言簿(1)
随笔档案
文章分类
文章档案
搜索
最新评论
Powered by: 博客园
模板提供:沪江博客
|
|
|
|
|
发新文章 |
|
|
最近在寫學校案子用到hibernate,正巧以前打工的地方學習到一個方法,
在javaworld@tw也有人提到過,因此整理一下.
Hibernate + Struts 學習筆記提到過的使用dynamic proxy的做法,
來避免巢狀呼叫,也可以讓service delegate不會跟hibernate綁的死死的.
首先dynamic proxy會利用到java.lang.reflect.Proxy跟java.lang.reflect.InvocationHandler. 直接看以下程式碼
HogeIF.java
1 2 3
|
public interface HogeIF { public void printMessage(String message); }
|
Hoge.java
1 2 3 4 5
|
public class Hoge implements HogeIF{ public void printMessage(String message) {
System.out.println(message); } }
|
執行時必須寫成
1 2
|
HogeIF hoge = new Hoge(); hoge.printMessage("hogehoge");
|
如果想對此方法做點前後置處理,那就寫個proxy
HogeProxy.java
1 2 3 4 5 6 7 8
9 10
11
|
public class HogeProxy implements HogeIF{ private HogeIF hoge; public HogeProxy(HogeIF hoge) { this.hoge = hoge; } public void printMessage(String message) { System.out.println("before"); hoge.printMessage(message); System.out.println("after" ); } }
|
這樣就會變成
如果每個method都需要加工,需要加工的class都implement不同interface,或者每個class有不同method,那麼........就要寫非常多的proxy來用... 在這邊改個方法使用dynamic proxy...
DynamicHogeProxy.java
1 2 3 4 5 6 7 8
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
|
import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method ; public class DynamicHogeProxy implements InvocationHandler { private Object obj; public static Object newInstance(Object obj)
{ return java.lang.reflect.Proxy.newProxyInstance(obj.getClass() .getClassLoader(), obj.getClass().getInterfaces(), new DynamicHogeProxy(obj)); } private DynamicHogeProxy(Object obj) { this.obj = obj; } public Object invoke(Object proxy, Method m, Object[] args) throws Throwable { Object result; try { System.out.println( "before"); result = m.invoke(obj, args); System.out.println("after"); return result;
} catch (InvocationTargetException e) { throw e.getTargetException(); }finally { } } }
|
執行時寫成
1 2
|
HogeIF hoge = (HogeIF)DynamicHogeProxy.newInstance(new Hoge()); hoge.printMessage("hogehoge");
|
這樣就可以達到跟上一個例子一樣的效果了.
回到本篇正題,最近用hibernate希望他自動關閉session,但是又不希望在dao的每個method都開開關關,也不希望service
delegate裡面去做開關,因此我把每個service delegate都使用dynamic
proxy來invoke...這樣就可以做到整個呼叫過程,session的開關只有一次,也就不用擔心巢狀呼叫了.
因此我在每個dao的每個操作的method的開頭加上ThreadLocalSession.currentSession();
然後每個service delegate都使用dynamic proxy 去invoke. dynamic proxy的內容如下
1 2 3 4 5 6 7 8
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
|
import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method ; import java.lang.reflect.Proxy; public class DynamicHogeProxy implements InvocationHandler{ private Object obj; private DynamicHogeProxy(Object obj) { this.obj = obj; } public static Object newInstance(Object obj) { return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), new DynamicHogeProxy( obj)); } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object result = null; if (obj != null) { try { result = method.invoke(obj, args); } catch (InvocationTargetException e) { throw e.getCause(); } finally { ThreadLocalSession.closeSession(); } } return result; } }
|
這種寫法缺點是一定得撰寫interface才可以,不然會發生ClassCastException.
1 2
|
HogeIF hoge = (HogeIF)DynamicHogeProxy.newInstance(new Hoge()); //ok!!! Hoge hoge = (Hoge)DynamicHogeProxy.newInstance( new Hoge()); //ClassCastException
|
而且一開始產生proxy時效能會稍微差一點. 另外,要達到上述功能現在也可以用AspectJ來做...恩...
|
|