代理模式

所谓代理模式,代理就是类似中介的意思,比如买房,可以选择自己买房或者委托中介(代理)买房,如果委托中介,中介除了买房,还会做一些额外的事情。

 

 

静态代理 

买房接口:

public interface BuyHouse {
    void buyHouse();
}
View Code

自己买房实现:

public class BuyHouseImpl implements BuyHouse {

    @Override
    public void buyHouse() {
        System.out.println("buy house!");
    }
}
View Code

中介买房实现:

public class BuyHouseProxy implements BuyHouse {

    private BuyHouse buyHouse;

    public BuyHouseProxy(final BuyHouse buyHouse){
        this.buyHouse=buyHouse;
    }

    @Override
    public void buyHouse() {
        System.out.println("before");
        buyHouse.buyHouse();
        System.out.println("after");
    }
}
View Code

客户类测试:

public class Client {

    public static void main(String[] args) {
        // 自己买房
        System.out.println("自己买房:");
        BuyHouse buyHouse=new BuyHouseImpl();
        buyHouse.buyHouse();

        System.out.println();

        // 通过中介(代理)买房
        System.out.println("通过中介买房:");
        BuyHouse buyHouseProxy=new BuyHouseProxy(buyHouse);
        buyHouseProxy.buyHouse();
    }
}
View Code

输出结果:

 

 

优点:可以对某个已经实现的功能做扩充,而不更改原来的类。

缺点:一个中介只能给某个类提供服务,不能给其它类做代理。

jdk动态代理

动态代理就是通过反射把代理类中的target成员由买房服务换成通用的Object,这样这个代理就可以给任何服务提供代理。

动态代理类:

public class DynamicProxyHandler implements InvocationHandler {

    private Object object;

    public DynamicProxyHandler(final Object object){
        this.object=object;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("before");
        Object result=method.invoke(object,args);
        System.out.println("after");
        return result;
    }
}
View Code

客户类:

public class Client {

    public static void main(String[] args) {
        // 自己买房
        System.out.println("自己买房:");
        BuyHouse buyHouse=new BuyHouseImpl();
        buyHouse.buyHouse();

        System.out.println();

        // 通过静态中介(代理)买房
        System.out.println("通过静态中介买房:");
        BuyHouse buyHouseProxy=new BuyHouseProxy(buyHouse);
        buyHouseProxy.buyHouse();

        // 通过动态中介(代理)买房
        System.out.println("通过动态中介买房:");
        BuyHouse dynamicProxy=
                (BuyHouse) Proxy.newProxyInstance(BuyHouse.class.getClassLoader(),new Class[]{BuyHouse.class},new DynamicProxyHandler(buyHouse));
        dynamicProxy.buyHouse();
    }
}
View Code

 注意Proxy.newProxyInstance()方法接受三个参数:

  • ClassLoader loader:指定当前目标对象使用的类加载器,获取加载器的方法是固定的
  • Class<?>[] interfaces:指定目标对象实现的接口的类型,使用泛型方式确认类型
  • InvocationHandler:指定动态处理器,执行目标对象的方法时,会触发事件处理器的方法

CGLIB动态代理

静态代理和jdk动态代理都需要业务类有接口interface,对于没有接口的业务类,就需要用cglib代理了。

cglib的动态代理是基于子类的动态代理,不需要目标对象实现接口,要求被代理类不能由final修饰。

public class CglibProxy implements MethodInterceptor {
    private Object target;
    public Object getInstance(final Object target) {
        this.target = target;
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(this.target.getClass());
        enhancer.setCallback(this);
        return enhancer.create();
    }

    public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.out.println("买房前准备");
        Object result = methodProxy.invoke(object, args);
        System.out.println("买房后装修");
        return result;
    }
}
View Code

客户类:

public class CglibProxyTest {
    public static void main(String[] args){
        BuyHouse buyHouse = new BuyHouseImpl();
        CglibProxy cglibProxy = new CglibProxy();
        BuyHouseImpl buyHouseCglibProxy = (BuyHouseImpl) cglibProxy.getInstance(buyHouse);
        buyHouseCglibProxy.buyHosue();
    }
}
View Code

 

---

参考:

https://www.cnblogs.com/daniels/p/8242592.html

posted @ 2020-01-01 23:23  野鸟  阅读(140)  评论(0)    收藏  举报