设计模式-代理模式

75 阅读2分钟

代理模式

关于代理,代理模式可以避免客户端对原对象的直接操作,客户端通过一个代理类来访问原对象,代理类可以基于这个原理增强对原对象的控制,可以使用措施保护原对象,或者针对该原对象,扩展一些额外的功能,如记录日志等,

代理模式示例

这种代理,原对象和代理类 必须实现同一个接口

public interface Action {  //需要原对象和代理类都实现的接口
    void a();
}
public class MyObject implements Action{ // 原对象

    MyObject(){

    }

    @Override
    public void a() {
        System.out.println("I have a action");
    }
}
public class ProxyObject implements Action{

    MyObject myObject;

    ProxyObject(){
        myObject = new MyObject();
    }

    @Override
    public void a() {
        System.out.println("I am log"); // 代理类可以在这个位置做对原对象的动作控制
        myObject.a();
    }
}
public class Test {
    public static void main(String[] args){
        Action prxoy = new ProxyObject();
        prxoy.a();
    }
}

print:
I am log
I have a action

Java中的代理

静态代理

上面的示例

动态代理

在jvm运行时动态生成的一个代理,代理类不必实现与原对象相同的接口,原对象是必须实现接口的

/**
* 代理类
*/
public class DynamicProxy {

    private Object target;// 维护一个目标对象

    public DynamicProxy(Object target) {
        this.target = target;
    }

    // 为目标对象生成代理对象
    public Object getProxyInstance() {
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),
                new InvocationHandler() {

                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("log start");
                        Object returnValue = method.invoke(target, args);
                        System.out.println("log end");
                        return null;
                    }
                });
    }
}
/**
* 
*/
public class TestDynamicProxy {
    public static void main(String[] args){
        Action myObject = (Action) new DynamicProxy(new MyObject()).getProxyInstance();
        myObject.a();
    }
}
print:
log start
I have a action
log end

cglib代理

这是个三方扩展包,可以看到上述的两种代理模式,均需要某一方实现接口,但是cglib代理的对象无需实现接口。Spring中就使用了该三方包,用于AOP

public class NoInterfaceObject {
    public void aaaa(){
        System.out.println("aaaaa");
    }
}
public class CglibProxy implements MethodInterceptor{

    private Object target;
    public CglibProxy(Object target) {
        this.target = target;
    }

    public Object getProxyInstance() {
        Enhancer en = new Enhancer();
        en.setSuperclass(target.getClass());  //Cglib 使用子类继承的方式来代理原对象类
        en.setCallback(this); //设置回调,当原对象有动作触发时,调用intercept方法
        return en.create();
    }

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("log start");
        Object returnValue = method.invoke(target, args);
        System.out.println("log end");
        return null;
    }
}
public class TestCglibProxy {
    public static void main(String[] args){
        NoInterfaceObject noInterfaceObject = (NoInterfaceObject) new CglibProxy(new NoInterfaceObject()).getProxyInstance();
        noInterfaceObject.aaaa();
    }
}
print:
log start
aaaaa
log end

我们看到代理类使用子类继承的方式代理原对象类,这也说明如果我们的原对象类有final修饰的话,那就不行了