PRoxyTest:
package app.java.proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class ProxyTest { public static void main(String[] args) { /** * Proxy類的newProxyInstance(ClassLoader,Class[])方法: * * 獲取對應(yīng)委托類的代理對象. * * 參數(shù)一:指定對應(yīng)委托類的類加載器. 也可以選擇當(dāng)前類 * * 參數(shù)二:指定委托類的Class * * 參數(shù)三:InvocationHandler的實例(重寫invoke) * * 動態(tài)代理的作用: * * 不需要得到對應(yīng)委托類的對象. * * 通過代理類對象,對委托類的方法進(jìn)行過濾(修改)等. */ Star fbb = (Star)Proxy.newProxyInstance(Star.class.getClassLoader(), Fbb.class.getInterfaces(), new InvocationHandler() { /** * invoke(Object proxy, Method method, Object[] args) * * 該方法的作用:調(diào)用對應(yīng)的委托類的方法. * * 參數(shù)一:返回的是代理類對象. * * 參數(shù)二:返回的是對應(yīng)委托類方法的Method類型對象. * * 參數(shù)三:返回的是對應(yīng)委托類方法接收的實參. */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 可以獲取到對應(yīng)委托類方法的參數(shù). /*String name = (String)args[0]; if(name.equals("zhangwuji")){ method.invoke(new Fbb(), "zhouzhiruo"); }*/ // 阻止調(diào)用對應(yīng)委托類的方法 /*String methodName = method.getName(); if(methodName.equals("movie")){ System.out.println("范冰冰最近太累了,不能拍電影,改唱歌了!"); }*/ // 修改委托類方法的返回值 String methodName = method.getName(); if(methodName.equals("movie")){ return "武媚娘傳奇,重播了!!!"; } return null; } }); // fbb.song("zhangwuji"); String value = fbb.movie(); System.out.println(value); } } spring中動態(tài)代理:(具體代碼在spring的AOP中)
底層:
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class MyBeanFactory { public static UserService createService(){ //1 目標(biāo)類 final UserService userService = new UserServiceImpl(); //2切面類 final Myaspect myAspect = new MyAspect(); /* 3 代理類:將目標(biāo)類(切入點)和 切面類(通知) 結(jié)合 --> 切面 * Proxy.newProxyInstance * 參數(shù)1:loader ,類加載器,動態(tài)代理類 運行時創(chuàng)建,任何類都需要類加載器將其加載到內(nèi)存。 * 一般情況:當(dāng)前類.class.getClassLoader(); * 目標(biāo)類實例.getClass().get... * 參數(shù)2:Class[] interfaces 代理類需要實現(xiàn)的所有接口 * 方式1:目標(biāo)類實例.getClass().getInterfaces() ;注意:只能獲得自己接口,不能獲得父元素接口 * 方式2:new Class[]{UserService.class} * 例如:jdbc 驅(qū)動 --> DriverManager 獲得接口 Connection * 參數(shù)3:InvocationHandler 處理類,接口,必須進(jìn)行實現(xiàn)類,一般采用匿名內(nèi)部 * 提供 invoke 方法,代理類的每一個方法執(zhí)行時,都將調(diào)用一次invoke * 參數(shù)3.1:Object proxy :代理對象 * 參數(shù)3.2:Method method : 代理對象當(dāng)前執(zhí)行的方法的描述對象(反射) * 執(zhí)行方法名:method.getName() * 執(zhí)行方法:method.invoke(對象,實際參數(shù)) * 參數(shù)3.3:Object[] args :方法實際參數(shù) * */ UserService proxService = (UserService)Proxy.newProxyInstance( MyBeanFactory.class.getClassLoader(), userService.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //前執(zhí)行 myAspect.before(); //執(zhí)行目標(biāo)類的方法 Object obj = method.invoke(userService, args); //后執(zhí)行 myAspect.after(); return obj; } }); return proxService; } }
新聞熱點
疑難解答