动态代理

代理模式概述

为什么要有“代理”?生活中就有很多代理的例子,例如,我现在需要出国,但是我不愿意自己去办签证、预定机票和酒店(觉得麻烦 ,那么就可以找旅行社去帮我办,这时候旅行社就是代理,而我自己就是被代理了。

代理模式的定义:被代理者没有能力或者不愿意去完成某件事情,那么就需要找个人代替自己去完成这件事,这个人就是代理者, 所以代理模式包含了3个角色: 被代理角色 代理角色 抽象角色(协议)

静态代理:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
public interface Happy {// 协议,被代理者需要代理的方法,就定义在这里,然后让代理者和被代理者去实现
// 被代理者实现: 为了确保和代理者实现的方法一致
// 代理者实现: 为了增强被代理者的这些方法
public abstract void happy();
}


public class JinLian implements Happy {

public void happy(){
System.out.println("金莲在happy...");
}

}


public class WangPo implements Happy{
// 成员变量
JinLian jl;

// 构造方法
public WangPo(JinLian jl) {
this.jl = jl;
}

// 成员方法
@Override
public void happy() {
System.out.println("王婆以做衣服的名义开好房间,并把2人约到房间里...");
// 金莲happy
jl.happy();
System.out.println("王婆打扫战场...");
}
}


public class XiMen {
public static void main(String[] args) {
/*
案例: 金莲要找西门happy
代理模式的定义:被代理者没有能力或者不愿意去完成某件事情,那么就需要找个人代替自己去完成这件事,这个人就是代理者,
所以代理模式包含了3个角色: 被代理角色 代理角色 抽象角色(协议)

*/
// 不请代理: 金莲直接找西门happy
// 创建金莲对象
JinLian jl = new JinLian();
// happy
// jl.happy();

// 请代理: 静态代理,代理类真实存在
Happy wp = new WangPo(jl);// wp:代理对象 WangPo类: 代理类 Happy接口: 协议 JinLian: 被代理类
wp.happy();
}
}

动态代理介绍

  • 概述 : 动态代理就是直接通过反射生成一个代理对象,代理对象所属的类是不需要存在的

  • 动态代理的获取:

    ​ jdk提供一个Proxy类可以直接给实现接口类的对象直接生成代理对象

动态代理相关api介绍

Java.lang.reflect.Proxy类可以直接生成一个代理对象

  • Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)生成一个代理对象
    • 参数1:ClassLoader loader 被代理对象的类加载器
    • 参数2:Class<?>[] interfaces 被代理对象的要实现的接口
    • 参数3:InvocationHandler h (接口)执行处理类
    • 返回值: 代理对象
    • 前2个参数是为了帮助在jvm内部生成被代理对象的代理对象,第3个参数,用来监听代理对象调用方法,帮助我们调用方法
  • InvocationHandler中的Object invoke(Object proxy, Method method, Object[] args)方法:调用代理类的任何方法,此方法都会执行
    • 参数1:代理对象(慎用)
    • 参数2:当前执行的方法
    • 参数3:当前执行的方法运行时传递过来的参数
    • 返回值:当前方法执行的返回值

案例-代理方法无参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
public interface Happy {// 协议,被代理者需要代理的方法,就定义在这里,然后让代理者和被代理者去实现
// 被代理者实现: 为了确保和代理者实现的方法一致
// 代理者实现: 为了增强被代理者的这些方法
public abstract void happy();
}


public class JinLian implements Happy {

public void happy(){
System.out.println("金莲在happy...");
}

}


public class XiMen {
public static void main(String[] args) {
/*
案例: 金莲要找西门happy
代理模式的定义:被代理者没有能力或者不愿意去完成某件事情,那么就需要找个人代替自己去完成这件事,这个人就是代理者,
所以代理模式包含了3个角色: 被代理角色 代理角色 抽象角色(协议)

*/
// 不请代理: 金莲直接找西门happy
// 创建金莲对象
JinLian jl = new JinLian();
// happy
// jl.happy();

// 请代理: 静态代理,代理类真实存在
Happy wp = new WangPo(jl);// wp:代理对象 WangPo类: 代理类 Happy接口: 协议 JinLian: 被代理类
wp.happy();

/*
问题:
1.金莲不方便直接找西门happy
2.金莲的happy方法需要增强一下,例如:happy之前需要开房,happy之后需要打扫战场

静态代理: 代理类是真实存在的,通过代理类产生代理对象
动态代理: 代理类是不真实存在的,在程序运行中,直接产生代理对象
前提: 被代理类需要实现接口
动态代理实现获取代理对象:
jdk提供一个Proxy类可以直接给实现接口类的对象直接生成代理对象
Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)生成一个代理对象
参数1loader:被代理类的类加载器
参数2interfaces: 被代理类所有实现的接口的Class对象
参数3InvocationHandler: 执行处理类
前2个参数是为了帮助在jvm内部生成被代理类的代理对象,第3个参数用来监听代理对象调用的方法,帮助我们代理对象调用方法
*/
System.out.println("=========================================");

// 使用动态代理直接产生金莲的代理对象
// 动态代理: 代理类是不真实存在的,但代理类是一定实现了被代理类的接口的
// p:动态代理产生的代理对象 代理类是不真实存在的
Happy p = (Happy) Proxy.newProxyInstance(JinLian.class.getClassLoader(), JinLian.class.getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 回调方法: 当代理对象调用了方法,就会来执行该invoke方法, 在该方法中就可以增强被代理类的方法
// 参数1: 生成的代理对象 这里就是p这个代理对象 (慎用)
// 参数2: 当前代理对象执行的方法 这里method就是happy()方法对象
// 参数3: 当前代理对象执行的方法,传入的实际参数
// 返回值:当前代理对象执行的方法的返回值
// System.out.println("invoke");
if (method.getName().equals("happy")){
System.out.println("王婆以做头发的名义把金莲和西门约到房间...");
// 通过反射来调用被代理对象的方法
method.invoke(jl);
System.out.println("王婆打扫战场...");
}
return null;
}
});

// 代理happy
p.happy();// 无参数
}
}