静态代理和动态代理

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/Today_1st/article/details/81774825

使用代理的目的是可以实现在目标对象的方法作拦截、过滤、预处理,对目标对象进行封装。根据代理类创建的时期又可以分为静态代理和动态代理。

一、静态代理

  1. 只代理一个类;
  2. 事先知道要代理的是什么;
  3. 实现与目标对象一样的接口;
  4. 由程序员创建或由特定工具自动生成源代码。

静态代理的例子可见如下代码:

//接口
public interface IAnimal {

    void doSomeThing();

    void doBThing();

}
//目标对象
public class People implements IAnimal {

    @Override
    public void doSomeThing() {
        System.out.println("I'm People, I'm working!");
    }

    @Override
    public void doBThing() {
        System.out.println("I'm People, I'm doing B thing!");
    }
}
//静态代理类
public class PeopleQuietProxy implements IAnimal {

    private People realObject;

    public PeopleQuietProxy(People people){
        this.realObject = people;
    }

    @Override
    public void doSomeThing() {
        System.out.println("before invoke realMethod...");
        realObject.doSomeThing();
        System.out.println("after invoke realMethod...");
    }

    @Override
    public void doBThing() {
        System.out.println("before invoke realMethod...");
        realObject.doBThing();
        System.out.println("after invoke realMethod...");
    }
}

二、动态代理

  1. 可代理多个实现类;
  2. 事先不知道要代理的是什么,只有在运行时才能确定;
  3. 一种动态代理是通过实现JDK的InvocationHandler接口的invoke方法,然后调用Proxy.newProxyInstance得到代理对象,代理的是接口;
    还有一种动态代理CGLIB,代理的是类,不需要业务类继承接口,通过派生的子类来实现代理。通过在运行时,动态修改字节码达到修改类的目的。

动态代理类可见如下代码:

public class PeopleProxy implements InvocationHandler {

    private Object realObject;

    public Object getInstance(Object realObject){
        this.realObject = realObject;
        return Proxy.newProxyInstance(this.getClass().getClassLoader(), realObject.getClass().getInterfaces(), this);
    }

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

//测试对象
public class TestPeopleProxy {

    public static void main(String[] args) {
        PeopleProxy proxy = new PeopleProxy();
        IAnimal animal = (IAnimal) proxy.getInstance(new People());
        animal.doBThing();
        animal.doSomeThing();
    }
}

从动态代理类PeopleProxy可以看到虽然类型跟People有关,但是类中却跟People没有一毛钱关系,即在创建和编译的时候,生成class文件之前都不知道目标对象是什么,而是在测试类中main方法运行的时候才从proxy.getInstance传入的参数得到接口信息,然后生成代理对象,之后就可以使用这个代理对象了。

展开阅读全文

没有更多推荐了,返回首页