標籤:
當net.sf.cglib.proxy.MethodInterceptor做為所有代理方法的回調(callback)時,當對基於代理的方法調用時,在調用原對象的方法的之前會調用這個方法,3所示。第一個參數是代理對像,第二和第三個參數分別是攔截的方法和方法的參數。原來的方法可能通過使用java.lang.reflect.Method對象的一般反射調用,或者使用net.sf.cglib.proxy.MethodProxy對象調用。net.sf.cglib.proxy.MethodProxy通常被首選使用,因為它更快。在這個方法中,我們可以在調用原方法之前或之後注入自己的代碼。
Figure 3: CGLIB MethodInterceptor
net.sf.cglib.proxy.MethodInterceptor能夠滿足任何的攔截(interception )需要,當對有些情況下可能過度。為了簡化和提高效能,CGLIB包提供了一些專門的回調(callback)類型。例如:
net.sf.cglib.proxy.FixedValue
為提高效能,FixedValue回調對強制某一特別方法返回固定值是有用的。
net.sf.cglib.proxy.NoOp
NoOp回調把對方法調用直接委派到這個方法在父類中的實現。
net.sf.cglib.proxy.LazyLoader
當實際的對象需要延遲裝載時,可以使用LazyLoader回調。一旦實際對象被裝載,它將被每一個調用代理對象的方法使用。
net.sf.cglib.proxy.Dispatcher
Dispathcer回調和LazyLoader回調有相同的特點,不同的是,當代理方法被調用時,裝載對象的方法也總要被調用。
net.sf.cglib.proxy.ProxyRefDispatcher
ProxyRefDispatcher回調和Dispatcher一樣,不同的是,它可以把代理對象作為裝載對象方法的一個參數傳遞。
3所示,代理類的所以方法經常會用到回調(callback),當是你也可以使用net.sf.cglib.proxy.CallbackFilter 有選擇的對一些方法使用回調(callback),這種考慮周詳的控制特性在JDK的動態代理中是沒有的。在JDK代理中,對java.lang.reflect.InvocationHandler方法的調用對代理類的所以方法都有效。
除了代理類外,CGLIB通過提供一個對java.lang.reflect.Proxy的drop-in替代來實現對對介面的代理。因為這種代理能力的替代很少被用到,因此相應的APIs也很少提到。
CGLIB的代理包也對net.sf.cglib.proxy.Mixin提供支援。基本上,它允許多個對象被綁定到一個單個的大對象。在代理中對方法的調用委託到下面相應的對象中。
接下來我們看看如何使用CGLIB代理APIs建立代理。
建立一個簡單的代理CGLIB代理最核心的是net.sf.cglib.proxy.Enhancer類,為了建立一個代理,最起碼你要用到這個類。首先,讓我們使用NoOp回調建立一個代理:
/**
* Create a proxy using NoOp callback. The target class
* must have a default zero-argument constructor.
*
* @param targetClass the super class of the proxy
* @return a new proxy for a target class instance
*/
public Object createProxy(Class targetClass) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(targetClass);
enhancer.setCallback(NoOp.INSTANCE);
return enhancer.create();
}
傳回值是target類一個執行個體的代理。在這個例子中,我們為net.sf.cglib.proxy.Enhancer 配置了一個單一的回調(callback)。我們可以看到很少直接建立一個簡單的代理,而是建立一個net.sf.cglib.proxy.Enhancer的執行個體,在net.sf.cglib.proxy.Enhancer類中你可使用靜態協助方法建立一個簡單的代理。一般推薦使用上面例子的方法建立代理,因為它允許你通過配置net.sf.cglib.proxy.Enhancer執行個體很好的控制代理的建立。
要注意的是,target類是作為產生的代理的父類傳進來的。不同於JDK的動態代理,它不能在建立代理時傳target對象,target對象必須被CGLIB包來建立。在這個例子中,預設的無參數構造器時用來建立target執行個體的。如果你想用CGLIB來建立有參數的執行個體,用net.sf.cglib.proxy.Enhancer.create(Class[], Object[])方法替代net.sf.cglib.proxy.Enhancer.create()就可以了。方法中第一個參數定義了參數的類型,第二個是參數的值。在參數中,基本類型應被轉化成類的類型。
------------
如果要裝載,請註明出處
[@more @]
使用CGLIB包建立動態代理(2)(轉)