JDK动态代理
为什么要动态代理
想要知道为什么需要动态代理我们需要先知道什么是静态代理,有了静态代理为什么又需要动态代理
首先其实代理就是将一个实现接口的类,进行调用的类,其可以在调用的继承上增加一些自己的功能
一个简单的DEMO代码如下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//IUser.java
public interface IUser {
public void getName();
}
//User.java
public class User implements IUser{
public void getName() {
System.out.println("User");
}
}
//UserProxy.java
public class UserProxy implements IUser {
private IUser user;
public UserProxy(IUser user) {
this.user = user;
}
public void getName() {
user.getName();
System.out.println("调用getName");
}
}
//Main.java
public class Main {
public static void main(String[] args) {
User user=new User();
UserProxy proxy= new UserProxy(user);
proxy.getName();
}
}
在我们运行Main时,通过了UserProxy这个代理来调用了User的getName()方法并且因为代理自身添加了一些功能还会输出调用getName,其实这就是一个简单的日志功能
但是这种静态代理有个很明显的弊端就是如果接口发送修改,我们不仅要修改完成接口的User.javaha还要修改我们的代理类,这是非常繁琐的。
所以我们需要运用动态代理。
动态代理
动态代理我们需要用到下面的方法来获取动态代理类
Proxy.newProxyInstance()
这个方法接受三个参数,需要代理的类的加载器,需要代理的类的接口,继承了InvocationHandler的类
DEMO的代码如下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//Main.java
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class Main {
public static void main(String[] args) {
User user=new User();
InvocationHandler handler=new UserInvocationHandler(user);
IUser proxy=(IUser)Proxy.newProxyInstance(user.getClass().getClassLoader(),user.getClass().getInterfaces(),handler);
proxy.getName();
proxy.getage();
proxy.gethigh();
}
}
//UserInvocationHandler.java
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class UserInvocationHandler implements InvocationHandler {
IUser user;
public UserInvocationHandler(){
}
public UserInvocationHandler(IUser user){
this.user = user;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
method.invoke(user, args);
System.out.println("调用"+method.getName());
return null;
}
}
//User.java
public class User implements IUser{
public void getName() {
System.out.println("User");
}
public void getage() {
System.out.println("18");
}
public void gethigh() {
System.out.println("181");
}
}
//IUser.java
public interface IUser {
public void getName();
public void getage();
public void gethigh();
}
上面的代码实现了一个简单的动态代理。其中定义的UserInvocationHandler.java是一个实现了InvocationHandler接口的一个类。该接口需要实现一个invoke方法该方法在动态代理类proxy调用了一个方法时触发,而invok中的实例user需要我们自己在构造方法中定义。
其实动态代理的过程就是我们定义的一个代理proxy调用了一个方法如proxy.getname时会自动跳到我们在定义这个proxy时传入的第三个参数的UserInvocationHandler类的invoke方法,然后运行invoke方法。
这个调用动态代理的知识点在学习CC1中的LazyMap的调用链的过程中有用到