java动态代理

静态代理

现在有一个接口IUser

1
2
3
4
5
public interface IUser {
void show();
//void delete();
//void insert();
}

UserImpl类实现了IUser接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class UserImpl implements IUser{
public UserImpl(){

}
@Override
public void show() {
System.out.println("调用show()");
}
/*@Override
public void delete() {
System.out.println("delete()");
}
@Override
public void insert() {
System.out.println("insert()");
}*/
}

下面是代理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class UserProxy implements IUser{
IUser user;
public UserProxy(){
}
public UserProxy(IUser user){
this.user=user;
}
@Override
public void show(){
user.show();
System.out.println("代理调用了show()");
}
}

下面主函数简单运行一下

1
2
3
4
5
6
7
public class ProxyTest {
public static void main(String[] args) {
IUser user = new UserImpl();
IUser userProxy = new UserProxy(user);
userProxy.show();
}
}

会发现输出了:

调用show()

代理调用了show

这就是静态代理,在这种情况下,同一个接口的每个函数都要有相对应的代理实现,在这里是show方法的代理,如果一个接口还有delete方法、insert方法等等呢,每个方法都要写一个代理方法吗?显然太麻烦了,所以有了动态代理。

动态代理

现在取消IUser接口和UserImpl类的注释,写一个UserInvocationHandler类,即动代理中 中介的角色

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{
method.invoke(user,args);
return null;
}
}

注:中介类必须要实现InvocationHandler接口

主函数采用如下写法:

1
2
3
4
5
6
7
8
public class ProxyTest {
public static void main(String[] args) {
IUser user = new UserImpl();
InvocationHandler userinvocationhandler = new UserInvocationHandler(user);
IUser userProxy=(IUser)Proxy.newProxyInstance(user.getClass().getClassLoader(), user.getClass().getInterfaces(),userinvocationhandler);//Java 动态代理的核心,它用于创建一个动态代理对象
userProxy.show();
}

主函数第二行代码创建了 UserInvocationHandler 的实例 userinvocationhandler,并将之前创建的 user 传递给它。这样UserInvocationHandler 可以在方法被调用时对 user 进行操作。

第三行将创建的代理对象赋给 IUser userProxy,此时 userProxy 是一个可以调用 IUser 接口方法的代理对象,第三个参数是 InvocationHandler 实例 userinvocationhandler,用于处理对代理对象的方法调用。

在借助代理对象调用具体的方法时,show在此处作为method传递到invoke方法中,args在这里为空,method.invoke(user, args)实际上执行了 user 的 show() 方法

到这就很清晰了,如果要调用delete、insert方法,只需要改userProxy.xxxxx就行了

参考

https://www.bilibili.com/video/BV16h411z7o9?p=3&vd_source=9fe5dd16d67801322fd30df51f7b3fd8

Java 静态代理&动态代理学习 – 天下大木头 (wjlshare.com)

GPT


java动态代理
http://example.com/2024/09/05/java动态代理/
作者
想有双手
发布于
2024年9月5日
许可协议