JDK动态代理

来源:互联网 发布:企业家的特质知乎 编辑:程序博客网 时间:2024/06/03 19:48
认真读好本篇内容,日后非常有用:还记得上一篇的代理模式吗?那种代理模式叫做静态代理。为什么要学动态代理?首先跟你这样讲一下:小苏找小胖代替自己去找小美表白,这样看上去没什么不妥。可是现在小苏我有竞争对手了,小胖的另一个朋友大苏,他也要找小胖替他去表白想班里的另一个同学表白,这时候该怎么办呢?你要在小胖代理类里再加多一个送礼物的方法吗?如果隔壁班的老王,找一个叫大胖的替他向大美表白;这个时候你要加多一个代理类吗?这显然很不妥,项目中到处都出现着XxxProxy类的身影。所以这里就需要我们的动态代理。传说中的AOP也是针对代理的一种应用,读懂动态代理有助于你更好的读懂之后要写的AOP模式。
(要使用JDK动态代理,前提条件是:被代理的类一定要有接口,也就是说需要是一个实现类。)
1.既然是我追小美,那就先建一个Su接口(并且定义一个送礼物的方法):

public interface Su {
//定义送礼物的方法。
String songLW();
}

 
2.接下来就去实现Su接口,创建我们的SuImpl实现类(并且实现送礼物方法):

public class SuImpl implements Su {
@Override
public String songLW() {
//我要送的礼物
System.out.println("礼物:电影票!");
//我送完礼物出去的心情
String ruselt="兴奋、有点担忧、又很期待!";
return rusel
}
}
 
3.又是我们可爱的小胖出场的时候了,创建一个小胖代理模式类 XiaoPang_JDK_Proxy代理类:
(这个类很重要,请认真读)

public class
XiaoPang_JDK_Proxy implements InvocationHandler {
private Object target;
//1.把创建的接口实现类(new xxxImpl())传进这个构造函数进行初始化,现在很多人叫它:注入。
public XiaoPang_JDK_Proxy
(Object target) {
this.target = target;
}

// 调用gerProxy相当于:Su.newInstancenew(new XiaoPang_JDK_Proxy());→Su su = new XiaoPang_JDK_Proxy();
@SuppressWarnings
("unchecked")
public < T > T getProxy() {
//再调用JDK提供给我们的Proxy类工厂的newProxyInstance去动态的创建一个xxx接口的代理类。
//nweProxyInstance(
//1.加载target这个参数值(被代理接口的实现类)
//2.获得target参数值(实现类)的接口类
//3.获得当前这个类this=XiaoPang_JDK_Proxy()类)

return
(T) Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(), this);
}
//invoke方法是InvocationHandler接口的定义方法,必须实现
// 1.proxy,代理类的实例。2.method,被代理的实现类中的方法。3.args,被代理方法中传入的参数
@Override
public
Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//这一次小胖再帮我送礼物,他觉得这份礼物不够诚意,偷偷替我写了一份情书,在送礼物之前还不忘浪漫的地上一封情书。
before();
// 调用被代理的方法:method.invoke(target,args) 从target的值(实例化对象)中,调用该方法(method的值),并传入参数args
//通俗点讲,这一次就是启动 我SuImpl实现类 送礼物的songLW方法。
Object result = method.invoke(target, args);
//小胖想着送完礼物还是不够诚意,于是他把偷来的玫瑰冒充我送了出去,然后潇洒离场。
after();
// result是用来接收被代理方法的返回值的。
return
result;
}
//小胖偷偷替我写情书。
private void before
() {
System.out.println("情书:" + "小美,我很喜欢你。明天放假,下午陪我一起看电影!");
}
//小胖偷玫瑰。
private void after
() {
System.out.println("附加礼物:红玫瑰!");
}
}

4.这时小胖要去找小美了,那我们就创一个小美类XiaoMi(并且创建收礼物方法):

public class
XiaoMi {
//小美收礼物方法
public void Shou_gift
() {

//调用 代理类,并且把 Su接口的实现类传到代理方法中进行初始化(注入)
//为Su接口动态的创建接口代理类(调用jdk动态代理的getProxy方法),意思就是小胖代替我来找小美了
Su su = new XiaoPang_JDK_Proxy(new SuImpl()).getProxy();

// 调用代理类中的送礼物方法,就是像小胖想好的那样,把情书,礼物,玫瑰送给小美。
// 并且把还我送完礼物的表情告诉了小美。(心情:SuImpl类,送礼物方法songLW()的返回值rusel)
String xinQing = su.songLW();
System.out.println("小苏的心情:" + xinQing);
}
}
 
5.像第一篇那样,把main写在小美XiaoMi类是不对的,应该把视图和对象分离开来,所以我们创建JDK代理视图类:

public class JDK_Proxy_View {
public static void main(String [] args){
XiaoMi xm = new XiaoMi();
//显示小苏追小美的故事,视图调用小美收礼物的方法:
xm.Shou_gift();
}
}

运行结果是:
JDK动态代理

 
至此,JDK代理模式讲解完毕,还有一个问题,就是开头提到的,JDK代理模式只能代理有接口的类,那没接口的类该怎么代理呢?这个就是我们下一篇要学的CGlib代理模式。

 

 
原创粉丝点击