代理模式
为其他对象提供一个代理以控制对某个对象的访问,其实就是代理类替被代理类实现业务,对被代理类的一种加强,代理分两种:静态代理和动态代理
以现实中的明星和代理人为例子吧
静态代理
接口:就是代理类和被代理的共同行为,明星唱跳是基本了
public interface Star{
void sing();
}
被代理类:不面向外部,业务都由代理类承接,以明星夏洛为例
public class Xialuo implements Star{
@Override
public void sing() {
System.out.println("雪花飘飘,北风萧萧,天地一片苍茫");
}
}
代理类:面向外部,首先你得跟经纪人马冬梅预约夏洛,他才会出席给你唱歌
public class Madongmei implements Star{
private Xialuo xialuo = new Xialuo();
@Override
public void sing() {
System.out.println("让我们欢迎夏洛来一首一剪梅" );
xialuo .sing();
}
}
代理类调用:
被代理类被传递给了代理类Madongmei ,代理类在执行具体方法时通过所持用的被代理类完成调用。
public static void main(String[] args) {
Madongmei madongmei = new Madongmei ();
madongmei .sing();
}
输出:
让我们欢迎夏洛来一首一剪梅
雪花飘飘,北风萧萧,天地一片苍茫
使用静态代理很容易就完成了对一个类的代理操作。 但是静态代理的缺点也暴露了出来:由于代理只能为一个类服务,如果需要代理的类很多,那么就需要编写大量的代理类,比较繁琐, 毕竟马冬梅这个经纪人名下也不是只有夏洛一个明星--------动态代理就来了
动态代理
如何理解静态和动态?
静态:代理类是创建了的,比如例子中的刘小爱
动态:代理类是不用创建的
在Java里有一个类叫Proxy,翻译过来就是代理的意思。
用这个类可以动态构建一个代理类对象,它有一个静态方法newProxyInstance(),用类名直接可以调用,我们来看看这个方法的参数
public static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)
①ClassLoader loader
类加载器,就是被代理类的类加载器
②Class<?>[] interfaces
interfaces,接口的意思,这个参数就是接口对应的Class对象,什么接口?就是被代理类实现的接口,因为它可以实现很多个接口,所以是一个数组。
③InvocationHandler h
InvocationHandle,翻译过来就是调用处理器,再看看这个接口,其实也就是例子中Madongmei这个类对star接口中的三个抽象方法的重写。
具体的业务逻辑,根据不同的需求编写不同的代码,其它的代码都是基本不变的。
public interface InvocationHandler extends Callback {
Object invoke(Object var1, Method var2, Object[] var3) throws Throwable;
}
该接口只有一个方法invoke:
proxy:这个就是代理对象
method:这个也就是代理对象调用的方法(例子中的sing方法)
args:这个是方法中的参数
好,以上就是对newProxyInstance()方法的说明,完全弄懂了这个方法,也就弄懂了动态代理。
接口、被代理类不变,我们构建一个handler类来实现InvocationHandler接口,这是方便代理对象构建InvocationHandler的。
public class ProxyHandler implements InvocationHandler{
private Object object;
public ProxyHandler(Object object){
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(method.getName());
method.invoke(object, args);
return null;
}
}
执行动态代理:
public static void main(String[] args) {
Xialuo xiaLuo= new Xialuo ();-------先创建被代理类的的加载器、接口
ClassLoader classLoader = xiaLuo.getClass().getClassLoader()
Class<?>[] interfaces = xiaLuo.getClass().getInterfaces();
InvocationHandler handler = new ProxyHandler(xiaLuo);
Star proxy= (Star) Proxy.newProxyInstance(classLoader , interfaces , handler);
-------代理类Madongmei我们是没有创建的,所以用的是它的父接口star来接受代理类对象,这是多态。----------
proxy.sing();
}
输出:
让我们欢迎夏洛来一首一剪梅
雪花飘飘,北风萧萧,天地一片苍茫