Java中的代理模式

2018-12-09  本文已影响0人  王魔王

动态代理:

代理:本来应该自己做的事情,却请了别人来做,被请来的人就是代理对象
例如:
动态代理:在程序运行的过程中产生的这个对象
在代理的过程中,可以在本类基础上添加新的功能,使其功能更强大
注意,代理对象代理(执行)的是被代理对象的方法。即本来就是被代理对象拥有的方法,只是原来由被代理对象执行,现在换成了代理对象去执行,但是这个方法本来就是被代理者拥有的方法。
jdk提供的代理只能针对接口做代理,我们有更强大的代理cglib

java中的代理

java在java.lang.reflect包下给我们提供了一个Proxy类和一个InvocationHandler接口,通过这个类和接口我们就可以生成动态代理对象。

使用方式

再次强调,java提供的动态代理只能针对接口做代理
1.定义接口

/**
 * 将要被代理的接口
 * eat为有参,无返回值的示例方法
 * sleep为无参,有返回值的示例方法
 */
public interface Aniamal {
    void  eat(String food);
    boolean  sleep();
}

2.定义接口的实现类

/**
 * 接口的具体实现类
 *
 */
public class Person implements Aniamal {
    private static final String TAG = "Person";
    @Override
    public void eat(String food) {
        Log.d(TAG, "eat: 吃了"+food);
    }

    @Override
    public boolean sleep() {
        Log.d(TAG, "sleep: 睡的不错");
        return true;
    }
}

3.实现InvocationHandler类

/**
 * 定义InvocationHandler的实现类
 *
 */
public class PersonInvocationHandler implements InvocationHandler {
    private Aniamal aniamal;// 被代理对象

    //被代理对象要构造传参进来
    public PersonInvocationHandler(Aniamal aniamal) {
        this.aniamal = aniamal;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //我们可以在方法执行前或者执行之后加入自己的逻辑
        //proxy为代理对象
        //这里的method就是将来我们调用的method
        //args就是我们传进来的参数
        //result是我们调用的method的返回值
        Object result = method.invoke(aniamal, args);
        return result;
    }
}

4.使用

 //创建被代理对象
        Person person = new Person();
        //创建InvocationHandler对象
        PersonInvocationHandler handler = new PersonInvocationHandler(person);
        //创建代理对象,将代理对象转换成被代理对象接口类型
        //创建方式一
        Aniamal proxyInstance =(Aniamal) Proxy.newProxyInstance(person.getClass().getClassLoader(),
                person.getClass().getInterfaces(), handler);
  //创建方式二
 Aniamal proxyInstance =(Aniamal) Proxy.newProxyInstance(Aniamal.class.getClassLoader(),
                Person.class.getInterfaces(), handler);

        //代理对象执行被代理对象的方法
        proxyInstance.eat("羊蝎子");
        boolean sleep = proxyInstance.sleep();
下面我们看PersonInvocationHandler中的逻辑

修改委托类的方法

@Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //修改委托类的方法
        String name = method.getName();
        //如果发现让我吃羊蝎子,就强制改成吃烤鸭
        if (name.equals("eat") && args[0].equals("羊蝎子")) {
           return method.invoke(aniamal,"烤鸭");
        }
        return method.invoke(aniamal,args);
    }

过滤委托类的方法

  @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //过滤委托类的方法
        String name = method.getName();
        //如果发现要调用睡觉的方法,那么就不执行
        if (name.equals("sleep")) {
           return false;
        }
        return method.invoke(aniamal,args);
    }

修改方法的返回值

这个更容易,只要return自己想要的任何值就可以类

动态代理作用

1、不需要得到对应委托类的对象
2、获取委托类的方法中的参数
3、通过代理类对象,对委托类的方法进行过滤(修改)等
4、修改委托类方法的返回值

上一篇下一篇

猜你喜欢

热点阅读