Loading
0

java中的动态代理

假设有如下接口和类的定义:

public interface Action {
    void execute(Object target);
}

public abstract class BaseAction implements Action {

    @Override
    public abstract void execute(Object target);
}

public class RunAction extends BaseAction implements Action {

    @Override
    public void execute(Object target) {
        System.out.println(target+":run");
    }
}

public class WalkAction extends BaseAction implements Action {

    @Override
    public void execute(Object target) {
        System.out.println(target+":walk");
    }
}

下面是使用jdk的动态代理类:

public class ActionProxy implements InvocationHandler {

    private Action target;

    public void bind(Action target)
    {
        this.target=target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        method.invoke(target,args);
        return null;
    }
}

调用动态代理的代码片断:

RunAction runAction=new RunAction();
ActionProxy actionProxy=new ActionProxy();
actionProxy.bind(runAction);
Action action=(Action)Proxy.newProxyInstance( actionProxy.getClass().getClassLoader(),runAction.getClass().getInterfaces() , actionProxy );
action.execute("Max Woods");

Java中使用JDK实现动态代理类,需要实现InvocationHandler接口,如上面的ActionProxy,该接口的定义为:

public interface InvocationHandler {
    public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable;
}

而委托类则需要实现同一接口,如上面的RunAction和WalkAction都实现了Action接口,并且共同继承了BaseAction这个抽象基类,注意尽管BaseAction的抽象方法execute实现了Action接口,但在RunAction和WalkAction还是要显示声明实现了Action接口,否则在创建动态代理对象时会抛出类型转换异常。

如果使用cglib来实现代理,则要简单许多,也不需要被委托对象实现接口,下面是cglib实现的代理类,需要实现MethodInterceptor接口:

public class ActionInterceptor implements MethodInterceptor {

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("代理执行方法:"+method.getName());
        return methodProxy.invokeSuper(o, objects);
    }
}

通过cglib代理调用,则更加简单:

Action action=(Action)Enhancer.create(WalkAction.class,new ActionInterceptor());
action.execute("Max Woods");

最后编辑于:2023/5/7作者: joycode

我不入地狱,谁入地狱?

评论已关闭