静态代理和动态代理
程序员文章站
2022-06-09 22:00:46
...
使用代理的目的是可以实现在目标对象的方法作拦截、过滤、预处理,对目标对象进行封装。根据代理类创建的时期又可以分为静态代理和动态代理。
一、静态代理
- 只代理一个类;
- 事先知道要代理的是什么;
- 实现与目标对象一样的接口;
- 由程序员创建或由特定工具自动生成源代码。
静态代理的例子可见如下代码:
//接口
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...");
}
}
二、动态代理
- 可代理多个实现类;
- 事先不知道要代理的是什么,只有在运行时才能确定;
- 一种动态代理是通过实现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传入的参数得到接口信息,然后生成代理对象,之后就可以使用这个代理对象了。
上一篇: 求字符串数组长度的一种方法
下一篇: 前端面试--函数防抖和函数节流