java动态代理-java

代理模式

代理模式是设计模式之一,我们通常通过new一个对象然后调用其对应的方法来访问我们需要的服务。代理模式则是通过创建代理类(proxy)的方式来访问服务,代理类通常会持有一个委托类对象,代理类不会自己实现真正服务,而是通过调用委托类对象的相关方法,来提供服务,所以其实我们调用的还是委托类的服务,但是中间隔了一个代理类。这么做的好处是我们可以在访问服务之前或者之后加一下我们需要的操作,而这些操作与原本的服务关联性不大,我们如果直接写到原本的服务中会增加代码的复杂性,是不合理的

静态代理

静态代理在使用时,需要定义接口或者父类,被代理对象与代理对象一起实现相同的接口或者是继承相同父类

1
2
3
public interface Person {
public void rentHouse();//创建一个person接口,这个接口就是租客和中介的公共接口,这个接口有一个rentHouse()方法
}
1
2
3
4
5
6
public class Renter implements Person{
@Override
public void rentHouse() {
System.out.println("租客租房成功!");//创建租客Renter类,实现上述接口
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
public class RenterProxy implements Person{
private Person renter;
public RenterProxy(Person renter){//创建中介类RenterProxy,同样实现Person接口,但是还另外持有一个租客类对象
this.renter = renter;
}
@Override
public void rentHouse() {
System.out.println("中介找房东租房,转租给租客!");
renter.rentHouse();
System.out.println("中介给租客钥匙,租客入住!");

}
}

创建测试类

1
2
3
4
5
6
7
8
9
public class StaticProxyTest {

public static void main(String[] args) {
Person renter = new Renter();
RenterProxy proxy = new RenterProxy(renter);
proxy.rentHouse();
}

}

image-20230321195159831

我们可以看到在需要代理的类方法较少的时候我们还可以直接在代理类中针对相应的方法做出修改,但是实际情况往往是需要做代理的类中有很多方法,我们不能把所有的方法都装饰一遍

动态代理

代理类在程序运行时创建的代理方式被成为动态代理,上述静态代理我们在程序运行前已经规划好了哪个方法惠之星哪些操作

在java的java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,通过这个类和这个接口可以生成JDK动态代理类和动态代理对象

接口

1
2
3
4
5
6
7
8
public interface IUser {

void show();
void creat();
void update();

}

需要被代理的类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class UserImpl implements IUser{
@Override
public void show() {
System.out.println("展示");
}

@Override
public void creat() {
System.out.println("创建");
}

@Override
public void update() {
System.out.println("更新");
}
}

接下来创建一个调用处理器类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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 {
System.out.println("调用了"+method+"方法");
method.invoke(user,args);
return null;
}
}

创建测试类

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.Proxy;

public class ProxyTest {
public static void main(String[] args) {
IUser user = new UserImpl();
//user.show();
//动态代理

InvocationHandler userInvocationHandler = new UserInvocationHandler(user);

IUser userProxy = (IUser) Proxy.newProxyInstance(user.getClass().getClassLoader(), user.getClass().getInterfaces(), userInvocationHandler);
userProxy.show();
userProxy.update();
}
}

image-20230322102020998