一、代理模式
1. 代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用
2. 代理模式一般涉及到的角色
(1)抽象角色:声明真实对象和代理对象的共同接口
(2)代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装
(3)真实角色:代理角色所代表的真实对象,是我们最终要引用的对象
二、动态代理与静态代理
若代理类在程序运行前就已经存在,那么这种代理方式被成为 静态代理 ,这种情况下的代理类通常都是我们在Java代码中定义的。 通常情况下, 静态代理中的代理类和委托类会实现同一接口或是派生自相同的父类
代理类在程序运行时创建的代理方式被成为 动态代理。 也就是说,这种情况下,代理类并不是在Java代码中定义的,而是在运行时根据我们在Java代码中的“指示”动态生成的。相比于静态代理, 动态代理的优势在于可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类的函数
执行委托类中的方法之前输出“before”,在执行完毕后输出“after”,通过静态代理实现我们的需求需要我们在每个方法中都添加相应的逻辑,这里只存在两个方法所以工作量还不算大,假如接口中包含上百个方法呢?这时候使用静态代理就会编写许多冗余代码。通过使用动态代理,我们可以做一个“统一指示”,从而对所有代理类的方法进行统一处理,而不用逐一修改每个方法
三、反射和动态代理区别
如果只是告诉我们委托类对象和要调用的方法,是不足以完成反射方法的调用,还需要参数类型和参数个数,但是每个方法的参数类型和参数个数其实都是不一样的,所以这个实现是有点难处的。总结,反射是不能直接坐到动态代理的功能的。
实际使用时,一个真实角色必须对应一个代理角色,如果大量使用会导致类的急剧膨胀;此外,如果事先并不知道真实角色,该如何使用代理呢?这个问题可以通过Java的动态代理类来解决
四、 动态代理的步骤
(1).创建一个实现接口InvocationHandler的类,它必须实现invoke方法
(2).创建被代理的类以及接口
(3).通过Proxy的静态方法
newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h) 创建一个代理
(4).通过代理调用方法
五、代理的使用
代理可以帮助我们进行很好的封装,使底层的代码能够有效的隐藏起来。为了区别,我们先来看看静态代理吧。
public class Main2 {
//这里传入的是接口类型的对象,方便向上转型,实现多态
public static void consumer(ProxyInterface pi){
pi.say();
}
public static void main(String[] args) {
// TODO Auto-generated method stub
consumer(new ProxyObject());
}
}
//代理接口
interface ProxyInterface{
public void say();
}
//被代理者
class RealObject implements ProxyInterface{
//实现接口方法
@Override
public void say() {
// TODO Auto-generated method stub
System.out.println("say");
}
}
//代理者
class ProxyObject implements ProxyInterface{
@Override
public void say() {
// TODO Auto-generated method stub
//dosomething for example
System.out.println("hello proxy");
new RealObject().say();
System.out.println("this is method end");
}
}
output:
hello proxy
say
this is method end
这就是静态代理,理解这个应该不难。
下面我们再来看看动态代理
import java.lang.reflect.*;
public class Main {
static void customer(ProxyInterface pi){
pi.say();
}
public static void main(String[] args){
RealObject real = new RealObject();
ProxyInterface proxy = (ProxyInterface)Proxy.newProxyInstance(ProxyInterface.class.getClassLoader(),new Class[]{ProxyInterface.class}, new ProxyObject(real));
customer(proxy);
}
}
interface ProxyInterface{
void say();
}
//被代理类
class RealObject implements ProxyInterface{
public void say(){
System.out.println("i'm talking");
}
}
//代理类,实现InvocationHandler 接口
class ProxyObject implements InvocationHandler{
private Object proxied = null;
public ProxyObject(){
}
public ProxyObject(Object proxied){
this.proxied = proxied;
}
public Object invoke(Object arg0, Method arg1, Object[] arg2) throws Throwable {
System.out.println("hello");
return arg1.invoke(proxied, arg2);
};
}