「这是我参与2022首次更文挑战的第30天,活动详情查看:2022首次更文挑战」。
一、动态代理与静态代理
静态代理在使用的过程中,代理对象必须要实现接口的所有方法,为解决这种问题,JDK提供了动态代理,通过JDK提供的方法,在运行过程中动态的创建代理对象,所以动态代理也可以称为JDK代理。
二、动态代理的实现
public interface Shop002 {
void sell();
}
商店,拥有售卖接口。
public class WholesaleShop002 implements Shop002 {
@Override
public void sell() {
System.out.println("瓶酒售卖价格2元");
}
}
批发商,实现了售卖接口。
public class ShopProxy002 {
private final Shop002 target;
public ShopProxy002(Shop002 target) {
this.target = target;
}
public Object getProxyInstance() {
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), (proxy, method, args) -> {
Object invoke = method.invoke(target, args);
System.out.println("跑腿费2元");
return invoke;
});
}
}
获取动态代理实体的对象,可以称为代理对象的工厂。此处是通过Proxy的newProxyInstance创建代理对象。
public class ShopTest002 {
public static void main(String[] args) {
Shop002 shop = new WholesaleShop002();
ShopProxy002 proxy = new ShopProxy002(shop);
Shop002 proxyInstance = (Shop002) proxy.getProxyInstance();
proxyInstance.sell();
}
}
可以看到,这里先使用ShoProxy002获取代理对象,代理对象是在运行过程中生成的,获取到代理对象后,调用sell方法。
三、总结
动态代理不需要实现接口的所有方法,动态代理对象在运行时创建,使用java.lang.reflect.Proxy类进行创建。代理对象不需要实现接口,但目标对象需要实现接口。 动态代理主要依据Proxy的静态方法newProxyInstance
可以看到,这个方法有3个参数,分别代表:
- ClassLoader loader:目标对象使用的类加载器。
- Class<?>[] interfaces:target对象使用的接口类型,使用泛型的方式确认类型。
- InvocationHandler h:事件处理,执行目标对象target的方法时,会触发事件处理器的方法,把当前执行的target的方法作为参数传入。