一个生活中的例子:明星都有一个自己的经纪人,这个经纪人就是他们的代理人。 当我们需要找明星表演时,不能直接找到该明星,只能是找明星的代理人。比如张学友在没有出名之前,我们可以直接找他唱歌,跳舞,拍戏;但是张学友出名之后,他干的第一件事就是找一个经纪人,这个经纪人就是张学友的代理人(代理)。 当我们需要找刘德华表演时,不能直接找到张学友了,只能是找其代理人,具体事务和代理人谈,相当于和张学友本人洽谈。张学友这个代理人存在的价值就是拦截我们对张学友的直接访问!
这个现实中的例子和我们在开发中是一样的,我们在开发中之所以要产生一个对象的代理对象,主要用于拦截对真实业务对象的访问。那么代理对象应该具有什么方法,代理对象应该具有和目标对象相同的方法。
一个典型的代理模式通常有三个角色(代理三要素)
若代理类在程序运行前就已经存在,那么这种代理方式被成为 静态代理 ,静态代理中的代理类和委托类会实现同一接口或是派生自相同的父类。
(1)共同接口
public interface Action {
void sing(String name);//唱歌
}
(2)真实对象
public class Star implements Action{//明星
@Override
public void sing(String name){
System.out.println("下面为大家演唱:"+name);
}
}
(3)代理人
public class Proxy implements Action{
private Action person;
public Proxy(Action person) {
this.person = person;
}
@Override
public void sing(String name) {
System.out.println("代理人通知明星:");
person.sing(name);
}
}
(4)测试
public class Main {
public static void main(String[] args) {
Proxy proxy = new Proxy(new Star());
proxy.sing("饿狼传说");
}
}
(5)运行结果
代理人通知明星:
下面为大家演唱:饿狼传说
静态代理的局限在于运行前必须编写好代理类(当多个对象需要代理时,需要事先定义好对应代理类)。 动态代理的目的就是为了解决静态代理的不足,动态代理的代理类是在程序运行期间动态生成的。
使用动态代理的五大步骤
1 通过实现InvocationHandler接口来自定义自己的InvocationHandler。
2 通过Proxy类的getProxyClass方法获取代理类。
3 通过反射机制获取代理类的构造方法,方法签名为getConstructor(InvocationHandler.class)。
4 将目标对象作为参数传入,通过构造方法获取自定义的InvocationHandler实例对象。
5 将自定义的InvocationHandler实例对象作为参数传入,通过构造方法获取代理对象。
6 代理对象调用目标方法。
package dynamic;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class DynamicProxyHandler implements InvocationHandler {
private Object person;
public DynamicProxyHandler(Object person) {
this.person = person;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//代理扩展逻辑
System.out.println("代理人通知被代理人:");
return method.invoke(person, args);
}
}
package dynamic;
import java.lang.reflect.Proxy;
import proxy.Action;
import proxy.Star;
public class DynamicProxyDemo {
public static void main(String[] args) {
Star star = new Star();
Action proxy = (Action)Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{Action.class}, new DynamicProxyHandler(star));
proxy.sing("饿狼传说");
}
}
Proxy.newProxyInstance 传入的是一个ClassLoader, 一个代理接口,和我们定义的handler,返回的是一个Proxy的实例。 运行结果
代理人通知被代理人:
下面为大家演唱:饿狼传说