代理模式

定义:为另一个对象提供一个替身或者占位符,以控制对这个对象的访问。

代理模式和装饰者模式

  • 装饰者模式是为对象附加新的行为
  • 代理模式是让访问者通过代理类访问对象,从而可以在代理类中添加对对象访问的控制。

类图

示例

复制代码
//Subject
public interface Actor {
    void  visit();
}

//Proxy
public class ActorProxy implements Actor {
    RealActor realActor;
    @Override
    public void visit() {
        if(realActor==null){
            realActor = new RealActor();
        }
        System.out.println("访问之前要做的事!");
        realActor.visit();
        System.out.println("访问之后要做的事!");
    }
}

//RealSubject
public class RealActor implements Actor{
    @Override
    public void visit() {
        System.out.println("访问真正的演员!");
    }
}

public class Client {
    public static void main(String[] args){
        Actor actorProxy = new ActorProxy();
        actorProxy.visit();
    }
}
复制代码

运行结果

 

 

 

Java动态代理

  • JDK中的动态代理是通过反射类Proxy以及InvocationHandler回调接口实现的,但是,JDK中所要进行动态代理的类必须要实现一个接口
  •  java.lang.reflect.InvocationHandler:需要实现这个接口,实现自己的处理器。处理器控制对象的访问。
  •  java.lang.reflect.Proxy:产生代理对象,需要指定实现的处理器试

示例

复制代码
//Subject
public interface Actor {
    void  visit();
}

//ConcreteInvocationHandler
public class ActorInvocationHandler implements InvocationHandler {
    Actor actor;
    public ActorInvocationHandler(Actor actor){
        this.actor = actor;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("访问前");
        Object object = method.invoke(actor,args);
        System.out.println("访问后");
        return object;
    }
}

public class Client {
    public static void main(String[] args) {
        Actor realActor = new RealActor();
        Actor actor = (Actor) Proxy.newProxyInstance(realActor.getClass().getClassLoader(),
                realActor.getClass().getInterfaces(),
                new ActorInvocationHandler(realActor));
        actor.visit();
    }
}
复制代码

运行结果

 

 Cglib动态代理

使用CGLib实现动态代理,完全不受代理类必须实现接口的限制,需要注意的是,CGLib不能对声明为final的方法进行代理,因为CGLib原理是动态生成被代理类的子类。

Jar包:

  • cglib-nodep.jar:使用nodep包不需要关联asm的jar包,jar包内部包含asm的类。
  • cglib.jar:使用此jar包需要关联asm的jar包,否则运行时报错。

示例

复制代码
//RealSubject
public class RealActor {
    public void visit() {
        System.out.println("访问真正的演员!");
    }
}

public class CglibProxy implements MethodInterceptor {
    private Object target;
    public CglibProxy(Object target){
        this.target = target;
    }
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("调用前");
        Object obj = method.invoke(target,objects);
        System.out.println("调用后");
        return obj;
    }
    public static Object getProxy(Object target){
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(target.getClass());
        enhancer.setCallback(new CglibProxy(target));
        return enhancer.create();
    }
}

public class Client {
    public static void main(String[] args){
        RealActor realActor = (RealActor) CglibProxy.getProxy(new RealActor());
        realActor.visit();
    }
}
复制代码

运行结果

 

posted @   Camcay  阅读(141)  评论(0编辑  收藏  举报
努力加载评论中...
点击右上角即可分享
微信分享提示