代理設計模式的核心含義在於一個業務操做除了真實實現以外,也須要有代理支持,代理負責全部與真實操做有關的輔助性功能實現,而真實主題只負責核心業務操做。java
代理使用分析:數據庫
在傳統編寫DAO程序操做過程之中,一直是存在有一個問題的,業務層的真實功能是調用數據層,可是發如今咱們以前寫的代碼之中,業務層除了要調用數據層組織數據以外,還要負責數據庫的打開和關閉。設計模式
範例:定義業務層接口ide
1
2
3
4
|
package com.zmcheng.Demo;
public interface Service {
public void print() throws Exception;
}
|
範例:定義真實主題類this
1
2
3
4
5
6
7
8
9
|
package com.zmcheng.Demo;
public class ServiceImpl implements Service {
@Override
public void print() throws Exception {
System.out.println("********操做前的準備:打開數據庫鏈接*******");
System.out.println("********操做數據層的若干操做*******");
System.out.println("********操做後的收尾:關閉數據庫鏈接*******");
}
}
|
以上是最先的設計思路,可是若是說如今結合代理設計模式來看,實現就很是槽糕了,由於全部的核心業務操做業務與輔助業務都同時寫在了一個方法裏。必須解決這樣的問題。spa
範例:設計一個靜態代理類設計
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
package com.zmcheng.Demo;
public class SeriverProxy implements Service {
Service service;
public SeriverProxy(Service service){
this.service = service;
}
public void pre() throws Exception{
System.out.println("********操做前的準備:打開數據庫鏈接*******");
}
public void end() throws Exception{
System.out.println("********操做後的收尾:關閉數據庫鏈接*******");
}
public void print() throws Exception {
this.pre();
this.service.print();
this.end();
}
}
|
範例:真實主題實現類代理
1
2
3
4
5
6
7
|
package com.zmcheng.Demo;
public class ServiceImpl implements Service {
@Override
public void print() throws Exception {
System.out.println("********操做數據層的若干操做*******");
}
}
|
而在使用的時候應該也經過工廠類取得接口實例化對象。code
範例:定義serviceFactory對象
1
2
3
4
5
6
|
package com.zmcheng.Demo;
public class serviceFactory {
public static Service getServiceInstance(){
return new SeriverProxy(new ServiceImpl());
}
}
|
此時繼續編寫客戶端,客戶端依然是經過工廠取得接口實例化對象,客戶端不會關心是代理主題仍是真實主題,只是它知道,利用你這個工廠的方法就能夠取得Seriver接口,就能夠操做了。
範例:編寫客戶端
1
2
3
4
5
6
7
|
package com.zmcheng.Demo;
public class Test {
public static void main(String[] args) throws Exception{
Service service = serviceFactory.getServiceInstance();
service.print();
}
}
|
這個時候的代理髮生了做用,也就是說在實際的環境之中,代理設計模式應該和工廠設計模式聯合起來,這樣客戶端在操做的時候就不會有任何的不適應感。
動態代理設計模式:
使用代理模式能夠有效的抽取出核心業務與輔助業務,可是回顧整個項目的開發過程裏面,可能會存在幾百個業務層接口。但是這個時候全部的代理層的功能發現都同樣,都只是負責真實主題業務調用,以及打開關閉數據庫。若是每個業務層接口都編寫一個代理,基本上的表現:代理也是折磨人的。因此必須想辦法讓一個代理類能夠負責全部真實主題的操做。
若是想要實現動態代理設計模式,必須有一個類來實現java.lang.reflect InvocationHandler接口。此接口有一個方法:
Object invoke(Object proxy, Method method,Object[] args) throws Throwable
實際上invoke()這個方法是屬於反射調用的方法,證實動態代理也屬於反射調用,而在invoke方法裏面參數:
Object proxy:表示要代理的對象;
Method method:表示要操做的方法;
Object args[]:方法調用時傳遞的參數。
若是要想讓代理設計真正可使用,必須有一個代理類對象產生,而這個代理類對象的產生能夠經過java.lang.reflect.Proxy類完成,而在Proxy類裏面有一個取得代理對象的實例化方法:
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h)
throws IllegalArgumentException
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
package com.zmcheng.Demo;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ServiceProxy implements InvocationHandler {
private Object target=null;
public Object getProxy(Object obj){
this.target = obj;
return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
}
public void prepare(){
System.out.println("********操做前的準備:打開數據庫鏈接*******");
}
public void end() throws Exception{
System.out.println("********操做後的收尾:關閉數據庫鏈接*******");
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object retValue = method.invoke(this.target, args);
return retValue;
}
}
|
下篇博客將對剖析動態代理類的原理。