JDK动态代理
1 | public interface SayService { |
编写测试方法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
38public class JDKProxyTest {
public static void main(String[] args) {
SayService sayService = new SayServiceImpl();
SayService proxy = new DynamicProxy(sayService).getProxy();
proxy.say("changjie");
//将jdk中生成代理类输出到本地.Class文件,之后可以通过反编译软件打开查看
createProxyClassFile("SayService",sayService.getClass().getInterfaces());
}
private static void createProxyClassFile(String name, Class<?> [] interfaces){
//该方法为jdk中生成代理类的核心方法
byte[] data = ProxyGenerator.generateProxyClass(name,interfaces);
FileOutputStream out =null;
try {
out = new FileOutputStream(name+".class");
System.out.println((new File(name)).getAbsolutePath());
out.write(data);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(null!=out){
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
输出1
2
3
4代理前
changjie
代理后
/Users/admin/IdeaProjects/spring-note/SayService
反编译其生成的动态代理类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
64public final class SayService extends Proxy implements me.changjie.aop.proxy.SayService {
private static Method m1;
private static Method m2;
private static Method m3;
private static Method m0;
public SayService(InvocationHandler var1) throws {
super(var1);
}
public final boolean equals(Object var1) throws {
try {
return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final String toString() throws {
try {
return (String)super.h.invoke(this, m2, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final void say(String var1) throws {
try {
//调用父类Proxy持有的InvocationHandle对象的invoke方法
super.h.invoke(this, m3, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final int hashCode() throws {
try {
return (Integer)super.h.invoke(this, m0, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
m3 = Class.forName("me.changjie.aop.proxy.SayService").getMethod("say", Class.forName("java.lang.String"));
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
可知JDK通过多态和反射生成的动态代理类,生成的代理类继承了Proxy类(持有InvocationHandler对象),实现了与被代理类相同的接口,这里也能反映出为什么JDK只能代理实现了接口的类,因为生成的代理类需要继承Proxy,由于单继承限制,只能和被代理类实现相同的接口来达到兄弟关系
CGLIB动态代理
1 | public class CglibProxyTest { |
CGLIB是生成目标类的子类,来织入目标类方法,所以对于final修饰的方法无法代理
总结
JDK生成的动态代理类与被代理类是兄弟关系,二者实现了相同接口,所以只能对实现了接口的类进行代理
CGLIB生成的代理类与被代理类是父子关系,所以无法对final修饰的方法进行代理