先思考两个问题
为什么需要代理?
代理是什么样子?
===============================👇举个栗子👇===============================
鸡哥是一个大明星,唱跳rap篮球无所不精,有一天,很多真爱粉找到鸡哥说:咯咯,给我唱一首歌吧!
于是鸡哥开始着手准备,话筒,场地,门票,节目单等等,搞得鸡哥焦头烂额,唱歌也没有唱好。于是鸡哥说这样不行,我负责的太多了,搞得本职工作都搞不好。我非常心疼自家哥哥,于是告诉他,你去找一个经纪人吧,这样一来,话筒,场地,门票,节目单等等工作都交给了经纪人(方法增强),也就是代理,鸡哥只负责去唱跳rap篮球即可,也不需要来接待客户(中介隔离)。后来哥哥唱歌再没掉过链子。
综上所述:
为什么需要代理?答:对象自身方法过于复杂,可以使用代理来转移一些职责,换句话说,使用代理可以让对象的方法比之前更牛逼,而且不会侵入对象源代码。(这就是中介隔离和方法增强)
代理是什么样子?答:代理中是对象需要被代理的方法和其他一些实现。
那么引出一个新的问题:
代理是怎么知道他自己要代理哪些方法的?
换句话说,是怎么规范代理和被代理对象的方法的。
提取关键字,规范 。什么可以用来规范行为?当然是接口!
如果以上内容全部看懂了,那么就可以试着敲一敲下面的这个例子
可以把接口理解成鸡哥和经纪人签的合同,合同里写的是经纪人需要管理鸡哥的事情。
package com.apesource.dynamic;
public interface Singer {
String sing();
void dance();
}
鸡哥本体,被代理对象
package com.apesource.dynamic;
public class ChickenSingerImpl implements Singer{
@Override
public String sing() {
System.out.println("只因你太美~~~");
return "感谢聆听";
}
@Override
public void dance() {
System.out.println("篮球舞");
}
}
经纪人,也就是代理对象
package com.apesource.dynamic;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class JinJiRenProxyUtil {
public static Object createProxy(final Object obj) {
/**
* 参数一:用于指定用哪个类加载器,去加载生成的代理类
* 参数二:指定接口,这些接口用于指定生成的代理长什么,也就是有哪些方法
* 参数三:用来指定生成的代理对象要干什么事情
*/
return Proxy.newProxyInstance(obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object res = null;
if (method.getName().equals("sing")) {
System.out.println("准备话筒,收钱");
res = method.invoke(singer, args);
System.out.println("唱完了,准备晚会");
} else if (method.getName().equals("dance")) {
System.out.println("准备场地收钱");
method.invoke(singer, args);
}
return res;
}
});
}
}
粉丝(测试类,调用者)
package com.apesource.dynamic;
public class TestClient {
public static void main(String[] args) {
// 不能找明星 直接找经纪人
Singer proxy = (Singer) JinJiRenProxyUtil.createProxy(new ChickenSingerImpl());
System.out.println(proxy.sing());
}
}
代码就是这么写,很规范,主要是这种思想:对纵向代码的横向扩展需要理解,多想着这个例子,敲两遍就拿下了。