在上一篇靜態代理模式的基礎上改爲動態代理模式
案例一
1.接口
//租房
public interface Rent {
public void rent();
}
2.真實角色
//房東
public class Host implements Rent {
public void rent(){
System.out.println("房東出租房子!");
}
}
3.自動生成代理類的類
InvocationHandler會自動生成代理類,創建一個類實現這個類
public class ProxyInvocationHandler implements InvocationHandler {
//被代理的按口
private Rent rent;
public void setRent(Rent rent) {
this.rent = rent;
}
//生成得到代理類
public Object getProxy() {
return Proxy.newProxyInstance(this.getClass().getClassLoader(), rent.getClass().getInterfaces(), this);
}
//處理代理實例。並返回結果
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//動態代理的本質,就是使用反射機制實現!
seeHouse();
Object result = method.invoke(rent, args);
fare();
return result;
}
public void seeHouse() {
System.out.println("中介帶看房子");
}
public void fare() {
System.out.println("收取中介費");
}
}
4.客戶訪問
public class Client {
public static void main(String[] args) {
//真實角色
Host host = new Host();
//代理角色:現在沒有
ProxyInvocationHandler pih = new ProxyInvocationHandler();
//通過調用程序處理角色米處理我們要調用的按口對象!
pih.setRent(host);
Rent proxy = (Rent) pih.getProxy();//這裏的proxy就是動態生成的,我們並沒有寫
proxy.rent();
}
}
案例二
1.接口
public interface UserService{
void add();
void delete();
void update();
void query();
}
2.真實角色
public class UserServiceImpl implements UserService {
public void add() {
System.out.println("增加了一個用戶");
}
public void delete() {
System.out.println("刪除了一個用戶");
}
public void update() {
System.out.println("修改了一個用戶");
}
public void query() {
System.out.println("查詢了一個用戶");
}
}
3.自動生成代理類的類
//等我們會用這個類, 自動生成代理類!
public class ProxyInvocationHandler 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 + "方法");
}
}
4.客戶訪問
public class Client {
public static void main(String[] args) {
//真實角色
UserServiceImpl userService = new UserServiceImpl();
//代理角色,不存在
ProxyInvocationHandler pih = new ProxyInvocationHandler();
pih.setTarget(userService);
//動態生成代理類
UserService proxy = (UserService) pih.getProxy();
proxy.query();
}
}
總結
動態代理的好處:
- 可以使真實角色的操作更加純粹,不用去關注一些公共的業務
- 公共也就交給代理角色,實現了業務的分工
- 公共業務發生擴展的時候,方便集中管理
- 一個動態代理類代理類代理的是一個接口,一般就是對應的一類業務
- 一個動態代理類可以代理多個類,只要是實現了同一個接口即可