動態代理主要有兩種實現方式 :
- 基於接口的動態代理 : JDK動態代理
- 基於類的動態代理 : cglib
下面演示的是 JDK動態代理
1 JDK動態代理需要了解的一個接口和一個類
1.1 InvocationHandler (調用處理程序)
InvocationHandler 是生成代理實例的類需要實現的接口,然后需要實現接口中的 invoke() 方法,在這個方法中進行對代理實例的處理
1.2 Proxy (代理)
Proxy 是所有代理實例的父類,它提供了創建動態代理實例的靜態方法.
2 代碼演示一
2.1 創建一個抽象對象
//租房
public interface Rend {
public void rend();
}
2.2 創建一個 真實對象
public class Homeowner implements Rend {
@Override
public void rend(){
System.out.println("房東出租了房子");
}
}
3.3 創建一個生成代理實例的類(核心)
//這個類是用來生成代理實例的類
public class ProxyInvocationHandle implements InvocationHandler {
//被代理的接口
private Rend rend;
public void setRend(Rend rend) {
this.rend = rend;
}
//生成得到代理類
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),rend.getClass().getInterfaces(),this);
}
//處理代理實例,並返回結果
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//動態代理的本質,就是使用反射機制實現!
seeHouse();
Object result = method.invoke(rend, args);
fare();
return result;
}
public void seeHouse(){
System.out.println("中介帶你看房子");
}
public void fare(){
System.out.println("收中介費");
}
}
3.4 創建客戶類
public class Client {
public static void main(String[] args) {
//真實角色
Homeowner homeowner = new Homeowner();
//代理角色:現在沒有
ProxyInvocationHandle pih = new ProxyInvocationHandle();
//通過調用程序處理角色來處理我們要調用的接口對象!
pih.setRend(homeowner);
Rend proxy = (Rend) pih.getProxy();//這里的proxy就是動態生成的,我們並沒有寫
proxy.rend();
}
}
3.5 執行結果
3 代碼演示二
3.1 創建一個抽象對象
public interface UserService {
public void query();
public void add();
public void delete();
public void update();
}
3.2 創建一個真實對象
public class UserServiceImpl implements UserService{
@Override
public void query() {
System.out.println("查詢用戶");
}
@Override
public void add() {
System.out.println("增加用戶");
}
@Override
public void delete() {
System.out.println("刪除用戶");
}
@Override
public void update() {
System.out.println("修改用戶");
}
}
3.3 創建一個生成代理實例的類(核心)
//用這個類,自動生成代理類
public class ProxyInvocationHandle implements InvocationHandler {
//被代理的接口
private Object target;
public void setTarget(Object target) {
this.target = target;
}
//生成得到代理類
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
}
//處理代理實例,並返回結果
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//動態代理的本質,就是使用反射機制實現!
log(method.getName());
Object result = method.invoke(target, args);
return result;
}
public void log(String msg){
System.out.println("執行了"+msg+"方法");
}
}
3.4 創建客戶類
public class Client {
public static void main(String[] args) {
//真實角色
UserServiceImpl userService = new UserServiceImpl();
//代理角色,不存在
ProxyInvocationHandle pih = new ProxyInvocationHandle();
pih.setTarget(userService);//設置要代理的對象
//動態生成代理類
UserService proxy = (UserService) pih.getProxy();
proxy.add();
}
}
3.5 執行結果
4 總結
- 動態代理解決了靜態代理創建過多的代理類導致開發效率降低的問題
- 動態代理的角色和靜態代理的是相同的
- 動態代理的代理類是動態生成的 . 靜態代理的代理類是我們提前寫好的
- 一個動態代理 , 一般代理某一類業務
- 一個動態代理可以代理多個類,代理的是接口
- 可以使得我們的真實角色更加純粹 . 不再去關注一些公共的事情
- 公共的業務由代理來完成 . 實現了業務的分工
- 公共業務發生擴展時變得更加集中和方便