动态代理

来源:互联网 发布:mac版搜狗输入法设置 编辑:程序博客网 时间:2024/06/04 19:38

动态代理机制:通过Proxy的newProxyInstance方法创建一个代理对象,该对象调用的原对象方法时,会调用代理方法,代理的方法内通过反射机制调用被代理方法。


Proxy.newProxyInstance 方法参数 

ClassLoader loader//被代理的对象的类加载器        Class<?>[] interfaces//被代理的对象的接口
InvocationHandler h//代理类的代理方法
动态代理作用:通过代理可以实现解耦方法内的代码。
【例】应用场景:在某个方法执行后,需要进行日志记录。
      原始方式:方法体内部,当执行完所有逻辑且在返回之前增加日志记录功能
      缺陷:方法体内的业务逻辑与日志记录功能紧密耦合在了一起,日志记录功能本不该出现在业务逻辑之中。
      代理实现方法:将日志记录功能从方法体内抽离出来,将其放在代理类的代理方法中的反射调用的被代理方法之后。
【Demo】
Step1:创建接口
public interface Taxi {    public void driveTo(String destination);}
Step2:实现接口
public class TaxiImpl implements Taxi {    @Override    public void driveTo(String destination) {        System.out.println("驶向目的地:" + destination);//原方法    }}

Step3:代理方法
public class TaxiHandler implements InvocationHandler {    private Object o;//代理对象    public TaxiHandler(Object o) {        this.o = o;    }    @Override    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        System.out.println("前置:开始打表");//原方法前增加逻辑        method.invoke(o, args);//反射调用原方法        System.out.println("后置:已达目的地,结账");//原方法后增加逻辑        return null;    }}

Step4:测试
public static final void main(String[] args){    TaxiImpl taxi = new TaxiImpl();    TaxiHandler taxiHandler = new TaxiHandler(taxi);    Taxi taxiProxy = (Taxi)Proxy.newProxyInstance(taxi.getClass().getClassLoader(), taxi.getClass().getInterfaces(), taxiHandler);//生成代理对象    taxiProxy.driveTo("人民广场");}

Step5:控制台输出
前置:开始打表驶向目的地:人民广场后置:已达目的地,结账
总结:
动态代理可以对被代理方法进行需求上的改造,AOP机制的前置通知、后置通知、环绕通知等就源于此。
在method.invoke(o, args)前增加内容,则变成了前置通知
method.invoke(o, args)后增加内容,则变成了后置通知
method.invoke(o, args)前后都增加内容,则变成了环绕通知