代理模式其實就是找替身,要去辦一件事兒,自己不去,找人代替你去,這就是代理模式。在程序中就是,為對象提供一個替身,控制替身去訪問目標對象,這樣做的好處是,除了目標對象能提供的功能外,還可以讓替身多做一些活,即可以擴展目標對象的功能。被代理的可以是遠端物件、建立時開銷很大的物件或是需要安全控制的物件。
代理模式主要分為以下三種:
#靜態代理
#動態代理(又叫JDK代理程式、接口代理)
cglib代理(也屬於動態代理的範疇)
使用靜態代理程式的時候,需要定義介面或父類,被代理的物件和代理物件需要一起實作相同的介面或繼承相同的父類。
定義一個介面:
TeacherDao定義代理程式的物件:
TeacherDaoImpl,需要實現
TeacherDao
定義代理程式物件:
TeacherDaoProxy要呼叫
TeacherDaoImpl對象,然後建立
TeacherDaoImplTeacherDao.java:
<code>public interface TeacherDao {<br> void teach();<br>}<br></code>
TeacherDaoImpl.java:
<code>public class TeacherDaoImpl implements TeacherDao {<br> @Override<br> public void teach() {<br> System.out.println("今天又是没妹子的一天(ノへ ̄、)");<br> }<br>}<br></code>
TeacherDaoProxy.java:
<code>public class TeacherDaoProxy implements TeacherDao {<br> <br> private TeacherDao target; // 被代理的对象<br> <br> public TeacherDaoProxy(TeacherDao target){<br> this.target = target;<br> }<br> <br> @Override<br> public void teach() {<br> System.out.println("代理开始");<br> // 这里可以写一些额外的逻辑,以达到扩展被代理对象的目的,相当于spring的前置通知<br> target.teach();<br> // 这里也可以写一些额外的逻辑,以达到扩展被代理对象的目的,相当于spring的后置通知<br> System.out.println("代理结束");<br> }<br>}<br></code>
Client.java:呼叫代理物件
<code>public class Client {<br><br> public static void main(String[] args){<br> // 创建被代理的对象<br> TeacherDao target = new TeacherDaoImpl();<br> // 创建代理对象<br> TeacherDaoProxy proxy = new TeacherDaoProxy(target);<br> // 通过代理对象调用方法<br> proxy.teach();<br> }<br>}<br></code>「3、靜態代理的優缺點:」
####優點:可以在不修改被代理對象的前提下擴展被代理的對象,做一些增強############缺點:需要實作相同的介面或繼承相同的父類,所以代理類別會很多,而且如果介面或父類有改動,代理物件和被代理物件都需維護 ############三、動態代理(JDK代理)#########「1、動態代理介紹:」#########代理對象不要實作接口,但是被代理對象還是需要實作接口的。動態代理物件的生成,利用的是JDK的API,反射包下的Proxy類,動態地在記憶體中建構代理物件。 #########「2、java.lang.reflect.Proxy:」#########這個類別有一個###newProxyInstance###方法,該方法接收三個參數,如下:###
<code>static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)<br></code>######「3、應用實例:」###############定義一個介面:TeacherDao############定義被代理程式的對象:TeacherDaoImpl,需要實作TeacherDao############定義一個代理工廠ProxyFactory,有一個getProxyInstance方法,需要傳入被代理的對象,然後返回代理對象實例,透過代理對象呼叫被代理對象的方法 ############程式碼實作:############TeacherDao.java:#########
<code>public interface TeacherDao {<br> void teach();<br>}<br></code>#########TeacherDaoImpl.java:#########
<code>public class TeacherDaoImpl implements TeacherDao {<br> @Override<br> public void teach() {<br> System.out.println("今天又是没妹子的一天(ノへ ̄、)");<br> }<br>}<br></code>#########ProxyFactory.java#########
<code>public class ProxyFactory {<br><br> private Object target; // 被代理的对象<br><br> public ProxyFactory(Object target){<br> this.target = target;<br> }<br><br> // 给被代理的对象生成一个代理对象<br> public Object getProxyInstance(){<br> // 参数1:指定被代理对象的类加载器<br> // 参数2:被代理对象实现的接口类型<br> // 参数3:事件处理,执行被代理对象的方法<br> return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {<br> @Override<br> public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {<br> System.out.println("JDK代理开始");<br> // 调用方法,args的方法的参数<br> Object returnValue = method.invoke(target, args);<br> System.out.println("JDK代理结束");<br> // 将执行结果return<br> return returnValue;<br> }<br> });<br> }<br>}<br></code>#########Client.java:透過代理呼叫方法#########
<code>public class Client {<br><br> public static void main(String[] args){<br> // 创建被代理的对象<br> TeacherDao target = new TeacherDaoImpl();<br> // 创建代理对象<br> TeacherDao proxy = (TeacherDao) new ProxyFactory(target).getProxyInstance();<br> // 通过代理对象调用被代理对象的方法<br> proxy.teach();<br> }<br>}</code>###四、cglib代理#########「1、cglib代理介紹: ”#########靜態代理和動態代理,被代理的對象,都需要實現接口,如果一個類沒實現任何接口的,那就要用cglib代理了。 cglib代理也叫子類別代理,它會在記憶體中建構一個子類別對象,從而實現對被代理對象的擴展。 cglib代理底層是透過一個叫ASM的字節碼處理框架來轉換字節碼並產生新的類別從而實現代理的。被代理的類別不能為final,否則會報錯。被代理物件的方法如果是final/static,就不會被攔截,也就是不會執行被代理物件額外的業務方法。 #########「2、應用實例:」######
首先要添加cglib相关依赖:
<code><dependency><br> <groupId>cglib</groupId><br> <artifactId>cglib</artifactId><br> <version>3.3.0</version><br></dependency><br></code>
TeacherDaoImpl.java:
<code>public class TeacherDaoImpl implements TeacherDao {<br> @Override<br> public void teach() {<br> System.out.println("今天又是没妹子的一天(ノへ ̄、)");<br> }<br>}<br></code>
CglibProxyFactory.java:
<code>// 需要实现MethodInterceptor并重写其方法<br>public class CglibProxyFactory implements MethodInterceptor {<br><br> private Object target;<br><br> public CglibProxyFactory(Object target){<br> this.target = target;<br> }<br><br> /**<br> * 返回target的代理对象<br> * @return<br> */<br> public Object getProxyInstance(){<br> // 1. 创建工具类<br> Enhancer enhancer = new Enhancer();<br> // 2. 设置父类<br> enhancer.setSuperclass(target.getClass());<br> // 3. 设置回调函数<br> enhancer.setCallback(this);<br> // 4. 创建子类对象,即代理对象<br> return enhancer.create();<br> }<br> @Override<br> public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {<br> System.out.println("CGLIB代理开始");<br> Object returnValue = method.invoke(target, args);<br> System.out.println("CGLIB代理结束");<br> return returnValue;<br> }<br>}<br></code>
Client.java:通过代理调用方法
<code>public class Client {<br><br> public static void main(String[] args){<br> // 创建被代理的对象<br> TeacherDaoImpl target = new TeacherDaoImpl();<br> // 获取代理对象,并将被代理对象传给代理对象<br> TeacherDaoImpl proxy = (TeacherDaoImpl) new CglibProxyFactory(target).getProxyInstance();<br> // 执行方法,触发intecept方法,从而实现执行被代理对象的方法<br> proxy.teach();<br> }<br>}<br></code>
以上是java代理模式怎麼應用的詳細內容。更多資訊請關注PHP中文網其他相關文章!