JDK动态代理实现原理Word下载.docx
《JDK动态代理实现原理Word下载.docx》由会员分享,可在线阅读,更多相关《JDK动态代理实现原理Word下载.docx(21页珍藏版)》请在冰点文库上搜索。
18.
/**
19.
构造方法
20.
@param
target
21.
22.
public
MyInvocationHandler(Object
target)
23.
super();
24.
this.target
=
25.
}
26.
27.
28.
29.
执行目标对象的方法
30.
31.
invoke(Object
proxy,
Method
method,
Object[]
args)
throws
Throwable
32.
33.
在目标对象的方法执行之前简单的打印一下
34.
System.out.println("
------------------before------------------"
);
35.
36.
37.
result
method.invoke(target,
args);
38.
39.
在目标对象的方法执行之后简单的打印一下
40.
-------------------after------------------"
41.
42.
return
result;
43.
44.
45.
46.
获取目标对象的代理对象
47.
@return
代理对象
48.
49.
getProxy()
50.
Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
51.
target.getClass().getInterfaces(),
this);
52.
53.}
54.
55.package
56.
57./**
58.
目标对象实现的接口,用JDK来生成代理对象一定要实现一个接口
59.
60.
61.
62.
63.public
interface
UserService
64.
65.
66.
目标方法
67.
68.
abstract
void
add();
69.
70.}
71.
72.package
73.
74./**
75.
76.
77.
78.
79.
80.public
UserServiceImpl
81.
82.
/*
(non-Javadoc)
83.
@see
dynamic.proxy.UserService#add()
84.
85.
add()
86.
--------------------add---------------"
87.
88.}
89.
90.package
91.
92.import
org.junit.Test;
93.
94./**
95.
动态代理测试类
96.
97.
98.
99.
100.public
ProxyTest
101.
102.
@Test
103.
testProxy()
104.
实例化目标对象
105.
userService
new
UserServiceImpl();
106.
107.
实例化InvocationHandler
108.
invocationHandler
MyInvocationHandler(userService);
109.
110.
根据目标对象生成代理对象
111.
proxy
(UserService)
invocationHandler.getProxy();
112.
113.
调用代理对象的方法
114.
proxy.add();
115.
116.
117.}
执行结果如下:
------------------before------------------
--------------------add---------------
-------------------after------------------
用起来是很简单吧,其实这里基本上就是AOP的一个简单实现了,在目标对象的方法执行之前和执行之后进行了增强。
Spring的AOP实现其实也是用了Proxy和InvocationHandler这两个东西的。
用起来是比较简单,但是如果能知道它背后做了些什么手脚,那就更好不过了。
首先来看一下JDK是怎样生成代理对象的。
既然生成代理对象是用的Proxy类的静态方newProxyInstance,那么我们就去它的源码里看一下它到底都做了些什么?
1./**
loader:
类加载器
3.
interfaces:
目标对象实现的接口
4.
h:
InvocationHandler的实现类
5.
6.public
static
newProxyInstance(ClassLoader
loader,
7.
Class<
?
>
[]
interfaces,
h)
IllegalArgumentException
if
(h
==
null)
throw
NullPointerException();
13.
Look
up
or
generate
the
designated
class.
Class
cl
getProxyClass(loader,
interfaces);
Invoke
its
constructor
with
invocation
handler.
try
调用代理对象的构造方法(也就是$Proxy0(InvocationHandler
h))
Constructor
cons
cl.getConstructor(constructorParams);
生成代理类的实例并把MyInvocationHandler的实例传给它的构造方法
(Object)
cons.newInstance(new
h
});
catch
(NoSuchMethodException
e)
InternalError(e.toString());
(IllegalAccessException
(InstantiationException
(InvocationTargetException
我们再进去getProxyClass方法看一下
1.public
getProxyClass(ClassLoader
...
interfaces)
如果目标类实现的接口数大于65535个则抛出异常(我XX,谁会写这么NB的代码啊?
)
(interfaces.length
65535)
IllegalArgumentException("
limit
exceeded"
声明代理对象所代表的Class对象(有点拗口)
proxyClass
null;
String[]
interfaceNames
String[interfaces.length];
Set
interfaceSet
HashSet();
for
detecting
duplicates
遍历目标类所实现的接口
(int
i
0;
<
interfaces.length;
i++)
拿到目标类实现的接口的名称
String
interfaceName
interfaces[i].getName();
interfaceClass
加载目标类实现的接口到内存中
Class.forName(interfaceName,
false,
loader);
(ClassNotFoundException
(interfaceClass
!
interfaces[i])
IllegalArgumentException(
interfaces[i]
+
"
is
not
visible
from
loader"
中间省略了一些无关紧要的代码
.......
把目标类实现的接口代表的Class对象放到Set中
interfaceSet.add(interfaceClass);
interfaceNames[i]
interfaceName;
把目标类实现的接口名称作为缓存(Map)中的key
key
Arrays.asList(interfaceNames);
Map
cache;
synchronized
(loaderToCache)
从缓存中获取cache
cache
(Map)
loaderToCache.get(loader);
(cache
如果获取不到,则新建地个HashMap实例
HashMap();
把HashMap实例和当前加载器放到缓存中
53.
loaderToCache.put(loader,
cache);
55.
57.
(cache)
do
根据接口的名称从缓存中获取对象
value
cache.get(key);
63.
(value
instanceof
Reference)
(Class)
((Reference)
value).get();
(proxyClass
如果代理对象的Class实例已经存在,则直接返回
proxyClass;
else
pendingGenerationMarker)
70.
cache.wait();
72.
(InterruptedException
74.
continue;
cache.put(key,
pendingGenerationMarker);
break;
while
(true);
80.
中间省略了一些代码
这里就是动态生成代理对象的最关键的地方
byte[]
proxyClassFile
ProxyGenerator.generateProxyClass(
proxyName,
88.
根据代理类的字节码生成代理类的实例
90.
defineClass0(loader,
proxyClassFile,
0,
proxyClassFile.length);
92.
(ClassFormatError
IllegalArgumentException(e.toString());
94.
add
to
set
of
all
generated
classes,
isProxyClass
proxyClasses.put(proxyClass,
null);
100.
进去ProxyGenerator类的静态方法generateProxyClass,这里是真正生成代理类class字节码的地方。
generateProxyClass(final
name,
Class[]
ProxyGenerator
gen
ProxyGenerator(name,
这里动态生成代理类的字节码,由于比较复杂就不进去看了
final
classFile
gen.generateClassFile();
如果saveGeneratedFiles的值为true,则会把所生成的代理类的字节码保存到硬盘上
(saveGeneratedFiles)
java.security.AccessController.doPrivileged(
java.security.PrivilegedAction<
Void>
()
Void
run()
FileOutputStream
file
FileOutputStream(dotToSlash(name)
.class"
file.write(classFile);
file.close();
(IOException
InternalError(
I/O
exception
saving
file:
e);
返回代理类的字节码
classFile;
}