代理模式
1
分类
- 静态代理(了解)
- 动态代理
动态代理之JDK动态代理
jdk动态代理的实现
1.
由Proxy类,创建代理对象
2.
自定义类实现InvocationHandler接口,提供接口服务,增强方法
- 示例1
/* 1.创建接口*/
public interface GameFactory {
void hitBoss();
}
/* 2.创建实现类*/
public class GameFactoryImpl implements GameFactory {
@Override
public void hitBoss() {
System.out.println("青衫正在打Boss");
}
}
/* 3.创建自定义类*/
public class GameProxy implements InvocationHandler {
//接收对象
private Object obj;
public void setObj(Object obj) {
this.obj = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("装备麻痹戒指!");
method.invoke(obj, args); //调用接口方法
System.out.println("自动拾取装备!");
return null;
}
}
/* 4.测试*/
public class GameTest {
public static void main(String[] args) {
//实例化被代理对象
GameFactory game = new GameFactoryImpl();
//实例化InvocationHandler实现类
GameProxy proxy = new GameProxy();
proxy.setObj(game);
//创建代理对象
GameFactory g = (GameFactory) Proxy.newProxyInstance(game.getClass().getClassLoader(),
game.getClass().getInterfaces(),
proxy);
//使用代理对象调用方法,自动调用代理类中的invoke方法
g.hitBoss();
}
}
-
代理方法Proxy.newProxyInstance(args0,args1,args2) 详解
-
args0:类加载器,代理谁,就填谁
-
args1:代理对象实现的接口,代理谁,就填谁
-
args2:实现方法,谁实现了InvocationHandler,就填谁
-
-
再看示例2
/* 1. 创建接口*/ public interface GameFactory { //显示人物属性 void showField(); //打怪 void hitBoss(String name); } /* 创建实现类*/ public class GameFactoryImpl implements GameFactory { @Override public void showField() { System.out.println("当前等级:100"); } @Override public void hitBoss(String name) { System.out.println(name + "正在打怪"); } } /* 创建自定义类*/ public class ProxyGame implements InvocationHandler{ Object obj; public void setObj(Object obj) { this.obj = obj; } public Object getProxy() { //代理谁,就填谁(接收谁,就填谁) return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this); } /** * 实现代理方法 */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if("hitBoss".equals(method.getName())) { System.out.println(args[0] + "已上线!"); System.out.println(args[0] + "带上了麻痹戒指!"); } method.invoke(obj, args); return null; } } /* 测试*/ @Test public void test01() { //实例化被代理对象 GameFactory factory = new GameFactoryImpl(); //实例化InvocationHandler实现类 ProxyGame proxyGame = new ProxyGame(); proxyGame.setObj(factory); //创建代理对象 GameFactory proxy = (GameFactory) proxyGame.getProxy(); //调用代理对象的方法 proxy.hitBoss("青衫"); proxy.showField(); }
源码感悟
- 通过反编译可以获取**$proxy0** 文件,打开后发现:每个代理对象都继承了Proxy类,并实现了代理对象中接口,以此重写接口方法,达到增强方法的目的
1.
注意jdk代理只能代理实现了接口的对象,来重写方法,因为Java不支持多继承
2.
代理类实现接口方法,重写了我们定义的接口方法 --> public final void hitBoss(){…}
3.
然后在重写的接口方法中,调用方法 -->this.h.invoke( args0,args1 ,args2 )
4.
但代理类中没有属性h,h是父类Proxy中的属性,InvocationHandler h;
5.
Invocation是接口,不能直接调用接口中的方法,只能调用实现类重写的方法
6.
所以jdk自动寻找实现了InvocationHandler接口的类,即找到我们编写的实现类
7
最后调用实现类中的invoke方法,完毕