jdk动态代理与cglib动态代理例子
1.JAVA的動態(tài)代理特征:特征是代理類與委托類有同樣的接口,代理類主要負(fù)責(zé)為委托類預(yù)處理消息、過濾消息、把消息轉(zhuǎn)發(fā)給委托類,以及事后處理消息等。代理類與委托類之間通常會存在關(guān)聯(lián)關(guān)系,一個代理類的對象與一個委托類的對象關(guān)聯(lián),代理類的對象本身并不真正實現(xiàn)服務(wù),而是通過調(diào)用委托類的對象的相關(guān)方法,來提供特定的服務(wù)。
它是在運行是生成的class對象,在生成時必須提供一組或一個interface給它,然后該class就宣稱它實現(xiàn)了這些interface。你當(dāng)然可以把該class的實例當(dāng)做這些interface中的任何一個來用,當(dāng)然,這個DynamicProxy其實就是一個Proxy,他不會替你做實質(zhì)性的工作,在生成它的實例時你必須提供一個handler,由它接管實際的工作。因此,DynamicProxy必須實現(xiàn)InvocationHandler接口。
5) 一個動態(tài)代理了和一個InvocationHandler 實現(xiàn)關(guān)聯(lián)的。每一個動態(tài)代理實例的調(diào)用都要通過InvocationHandler接口的handler(調(diào)用處理器)來調(diào)用,動態(tài)代理不做任何執(zhí)行操作,只是在創(chuàng)建動態(tài)代理時,把要實現(xiàn)的接口和handler關(guān)聯(lián),動態(tài)代理要幫助被代理執(zhí)行的任務(wù),要轉(zhuǎn)交給handler來執(zhí)行。其實就是調(diào)用invoke方法
動態(tài)代理:在程序運行時,運用反射機(jī)制動態(tài)創(chuàng)建而成
2.實用動態(tài)代理步驟:
A. 創(chuàng)建一個實現(xiàn)接口InvocationHandler的類,他必須實現(xiàn)invoke方法
B. 創(chuàng)建被代理的類以及接口。
C. 通過Proxy的靜態(tài)方法newProxyInstance(ClassLoader loader,Class【】interfaces,InvocationHandler handler)創(chuàng)建一個代理
D. 通過代理調(diào)用方法
?
3.jdk動態(tài)代理例子:
文件列表:
業(yè)務(wù)接口:UserService
業(yè)務(wù)實現(xiàn):UserServiceImpl
代理類的調(diào)用Handler實現(xiàn):ProxyHandler
JUnit測試類:SpringProxyTest
package com.niewj.service;
import com.niewj.model.User;
public class UserServiceImpl implements UserService {
?@Override
?public void add(User user) {
??System.out.println("User Saved. & ");
?}
?@Override
?public void delete(User user) {
??System.out.println("User Deleted. &");
?}
}
?
package com.niewj.service;
import com.niewj.model.User;
public class UserServiceImpl implements UserService {
?@Override
?public void add(User user) {
??System.out.println("User Saved. & ");
?}
?@Override
?public void delete(User user) {
??System.out.println("User Deleted. &");
?}
}
?
package com.niewj.service;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
?* JDK動態(tài)代理模擬
?*
?* 1.首先明確什么是目標(biāo)對象target,什么是代理對象proxy!!
?*
?* 2.每個代理對象對象都會有一個相關(guān)的InvocationHandler對象。
?* 當(dāng)代理對象生成的時候,是創(chuàng)建的代理對象,
?* 拿著相關(guān)的這個InvocationHandler對象,去自動調(diào)Handler類中實現(xiàn)的invoke方法的。
?* 下面一段話來自@javadoc@
?* <p>Each proxy instance has an associated invocation handler.
?* When a method is invoked on a proxy instance, the method
?* invocation is encoded and dispatched to the <code>invoke</code>
?* method of its invocation handler.
?*
?* 3.還有就是我發(fā)現(xiàn),我的Eclipse控制臺TMD輸出的順序有誤,害的老以為我人品出了什么問題,
?* 不知道控制臺的信息是不是不是棧式輸出的。(好繞口)
?*
?*/
public class ProxyHandler implements InvocationHandler {
?// 就是要給這個目標(biāo)類創(chuàng)建代理對象。
?private Object target;
?// 傳遞代理目標(biāo)的實例,因為代理處理器需要。也可以用set等方法。
?public ProxyHandler(Object target) {
??this.target = target;
?}
?/*
? * 這個方法是給代理對象調(diào)用的。
? * 留心的是內(nèi)部的method調(diào)用的對象是目標(biāo)對象,可別寫錯。
? */
?@Override
?public Object invoke(Object proxy, Method method, Object[] args)
???throws Throwable {
??Object ret = null;
??// 1.調(diào)用前
??cutIntoBefore(method.getName());
??ret = method.invoke(target, args);
??// 2.調(diào)用后
??cutIntoAfter(method.getName());
??return ret;
?}
?public void cutIntoBefore(String mName) {
??System.err.println("調(diào)用____" + mName + "()____方法之前");
?}
?public void cutIntoAfter(String mName) {
??System.err.println("調(diào)用____" + mName + "()____方法完后");
?}
}
?
package com.niewj;
import java.lang.reflect.Proxy;
import org.junit.Test;
import com.niewj.model.User;
import com.niewj.service.ProxyHandler;
import com.niewj.service.UserService;
import com.niewj.service.UserServiceImpl;
public class SpringProxyTest {
?@Test
?@SuppressWarnings("rawtypes")
?public void testJDKDynamicProxy() {
??/* 1.獲取UserServiceImpl對象--目標(biāo)對象--也就是需要被代理的對象。 */
??UserService userService = new UserServiceImpl();
??// 獲取當(dāng)前類名
??Class clazz = userService.getClass();
??/*
?? * 2.獲得代理對象。
?? * 每一個代理對象都有一個相關(guān)的InvocationHandler對象,通過這個handler對象的invoke來實現(xiàn)調(diào)用中要完成的自定義貓膩行為
?? * 。 可以使用Proxy類和自定義的調(diào)用處理邏輯來生成一個代理對象的。
?? */
??UserService userServiceProxy = (UserService) Proxy.newProxyInstance(
????clazz.getClassLoader(), clazz.getInterfaces(),
????new ProxyHandler(userService));
??userServiceProxy.add(new User("dotjar"));
??userServiceProxy.delete(new User("DDD"));
?}
}
?
4.cglib動態(tài)代理
JDK實現(xiàn)動態(tài)代理需要實現(xiàn)類通過接口定義業(yè)務(wù)方法,對于沒有接口的類,如何實現(xiàn)動態(tài)代理呢,這就需要CGLib了。CGLib采用了非常底層的字節(jié)碼技術(shù),其原理是通過字節(jié)碼技術(shù)為一個類創(chuàng)建子類,并在子類中采用方法攔截的技術(shù)攔截所有父類方法的調(diào)用,順勢織入橫切邏輯。JDK動態(tài)代理與CGLib動態(tài)代理均是實現(xiàn)Spring AOP的基礎(chǔ)。
它的運行速度要遠(yuǎn)遠(yuǎn)快于JDK的Proxy動態(tài)代理。
?
使用CGLIB需要導(dǎo)入以下兩個jar文件:
?
??? asm.jar – CGLIB的底層實現(xiàn)。
?
??? cglib.jar – CGLIB的核心jar包。
?
例子:
package com.niewj.service;
import java.lang.reflect.Method;
import com.niewj.model.User;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class CgLibProxyImitation implements MethodInterceptor {
?private Enhancer enhancer = new Enhancer();
?/** 創(chuàng)建代理對象
? * @param targetClass
? * @return 返回代理對象
? */
?@SuppressWarnings("rawtypes")
?public Object getProxy(Class targetClass) {
??enhancer.setSuperclass(targetClass); //設(shè)置需要創(chuàng)建子類的類
??enhancer.setCallback(this);
??return enhancer.create(); //通過字節(jié)碼技術(shù)動態(tài)創(chuàng)建子類實例
?}
?public void cutIntoBefore(String mName) {
??System.err.println("調(diào)用____" + mName + "()____方法之前");
?}
?public void cutIntoAfter(String mName) {
??System.err.println("調(diào)用____" + mName + "()____方法完后");
?}
?/*? 生成的代理對象調(diào)用此對象來替代原始對象
? *
? * @java.lang.Object 增強(qiáng)對象
? * @java.lang.reflect.Method 攔截方法
? * @java.lang.Object[] 參數(shù)數(shù)組
? * @net.sf.cglib.proxy.MethodProxy? 用于調(diào)用父類,按需要調(diào)用多次
? */
?@Override
?public Object intercept(Object obj, Method method, Object[] args,
???MethodProxy proxy) throws Throwable {
??cutIntoBefore(method.getName());
??Object result = proxy.invokeSuper(obj, args);
??cutIntoAfter(method.getName());
??return result;
?}
?
?public static void main(String[] args) {
//??UserService userService = new UserServiceImpl();
??CgLibProxyImitation cglib = new CgLibProxyImitation();
??UserServiceImpl userService = (UserServiceImpl)cglib.getProxy(UserServiceImpl.class);
??userService.add(new User("dotjar"));
??userService.delete(new User("hill"));
?}
}
?
總結(jié)
以上是生活随笔為你收集整理的jdk动态代理与cglib动态代理例子的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SQLPlus 在连接时通常有四种方式
- 下一篇: 圣殿骑士-移民结婚了,而且很年轻~