动态代理

115 阅读1分钟

代理模式

假如目前有一个Peoper类,实现了说话的功能。

public class People {
    public void say() {
        System.out.println("Hello!");
    }
}

现在我想要在说话之前,添加一个思考的动作。最简单的方法就是直接在方法前加上思考的动作。

public class People {
    public void say() {
        System.out.println("思考!")
        System.out.println("Hello!");
    }
}

虽然问题解决了,但是这样做违反了面向对象的开闭原则,如果代码中其他地方也调用了这个方法,就会出现问题。那么还可以添加一个新的方法,或者直接创建一个新的类继承People并重写say()方法来解决这个问题,但是如果People类有非常多的方法,我要在所有的方法前都加上思考动作,这样我就只能创建多新的方法或者在继承类中重写所有的方法并加上这个思考动作,这样会使代码变得非常的冗余并且很不美观。

为了解决的上述问题,可以使用静态代理的,但是静态代理同样需要添加为所有的方法添加额外统一的动作,也会是代码便的非常的冗余。

public class StaticPeopleProxy implements IPeople{
    private People people;

    public StaticPeopleProxy(){
        this.people = new People();
    }

    @Override
    public void say() {
        System.out.println("思考!");
        people.say();
    }

    @Override
    public void walk() {
        System.out.println("思考!");
        people.walk();
    }
}

为了解决上述问题,动态代理应运而生,jdk提供了invocationHandler接口和Proxy类,利用Proxy类生成目标对象的代理对象,通过实现invocationHandler接口的invoke()方法来实现统一的动作。

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class PeopleProxyHandler implements InvocationHandler {
    private Object targetObject;

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

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("思考!");
        return method.invoke(targetObject, args);
    }
}