java动态代理简单实例

代理是基本的设计模式之一,它是你为了提供额外的或不同的操作,而插入用来代替实际对象的对象,这些操作通常涉及与"实际"对象的通讯,因此代理通常充当中间人的角色.
动态代理并非是日常使用的工具,但是它可以非常好的解决某些类型的问题.
下面是一个用来展示代理结构的简单示例:

public interface Interface {
    void doSomething();
    void somethingElse(String arg);
}
public class RealObject implements Interface{
    @Override
    public void doSomething() {
        System.out.println("doSomething");
    }

    @Override
    public void somethingElse(String arg) {
        System.out.println("somethingElse "+arg);
    }
}
public class SimpleProxy implements Interface{
    private Interface proxied;

    public SimpleProxy(Interface proxied) {
        this.proxied = proxied;
    }

    @Override
    public void doSomething() {
        System.out.println("SimpleProxy doSomething");
        proxied.doSomething();
    }

    @Override
    public void somethingElse(String arg) {
        System.out.println("SimpleProxy somethingElse");
        proxied.somethingElse(arg);
    }
}
public class SimpleProxyDemo {

    public static void consumer(Interface inter){
        inter.doSomething();
        inter.somethingElse("boon");
    }

    public static void main(String[] args) {
        consumer(new RealObject());
        consumer(new SimpleProxy(new RealObject()));

    }

}

输出结果:

doSomething
somethingElse boon
SimpleProxy doSomething
doSomething
SimpleProxy somethingElse
somethingElse boon

在任何时刻,只要你想将额外的操作从"实际"对象中分离到不同的地方,特别是当你希望能够很容易的做出修改,从没有使用额外操作转为使用这些操作,或者反过来时,代理就显得很有用(设计模式的关键就是封装修改,因此你需要修改事务以证明这种模式的正确性)

java的动态代理比代理的思想更迈进了一步,因此它可以动态的创建代理并动态的对所代理方法的调用,在动态代理上所做的调用都会被重定向到单一的 调用处理器上,它的工作是确定调用的类型并确定相应的策略,下面是重写动态代理的SimpleProxyDemo

public class DynamicProxyHandler implements InvocationHandler {
    private Object proxied;

    public DynamicProxyHandler(Object proxied) {
        this.proxied = proxied;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("**** proxy :"+proxy.getClass()+
                ",method :"+method+",args :"+args);
        if (args != null){
            for (Object arg : args) {
                System.out.println(" "+arg);
            }
        }
        return method.invoke(proxied,args);
    }
}

修改SimpleProxyDemo

    public static void main(String[] args) {
//        consumer(new RealObject());
//        consumer(new SimpleProxy(new RealObject()));
        RealObject real = new RealObject();
        Interface proxy = (Interface)Proxy.newProxyInstance(Interface.class.getClassLoader(),
                new Class[]{Interface.class}, new DynamicProxyHandler(real));
        consumer(proxy);
    }

输出结果:

**** proxy :class com.sun.proxy.$Proxy0,method :public abstract void thinking_java14.proxy.Interface.doSomething(),args :null
doSomething
**** proxy :class com.sun.proxy.$Proxy0,method :public abstract void thinking_java14.proxy.Interface.somethingElse(java.lang.String),args :[Ljava.lang.Object;@50040f0c
 boon
somethingElse boon

通过调用静态方法Proxy.newProxyInstance()可以创建动态代理,这个方法需要得到一个类加载器(通常可以自己从已经被加载的对象中获取类加载器,然后传递给它),一个希望该代理实现的接口列表(不是类或抽象类),以及InvocationHandler接口的一个实现类.动态代理可以将所有调用重定向到调用处理器,因此通常会向调用处理器的构造参数传递一个实际对象的引用,从而使得调用处理器在执行其中介任务时,可以将请求转发/
invoke()方法中传递进来了代理对象,以防你需要区分请求的来源,但在多数情况下,你不需要关心这一点,然而,在invoke内部,在代理上调用方法时需要格外小心,因为对接口的调用会被重定向到对代理的调用.
通常,你会执行被代理的操作,然后使用Method.invoke()将请求转发给代理对象,并传入需要的参数.这初看起来有些受限,就像你只能执行范化操作一样,但是可以通过传入其他的参数,来过滤某些方法调用:

public interface SomeMethods {
    void boring1();
    void boring2();
    void boring3();
    void interesting(String arg);
}
public class Implementation implements SomeMethods{

    @Override
    public void boring1() {
        System.out.println("boring1");
    }

    @Override
    public void boring2() {
        System.out.println("boring2");
    }

    @Override
    public void boring3() {
        System.out.println("boring3");
    }

    @Override
    public void interesting(String arg) {
        System.out.println("interesting :"+arg);
    }
}
public class MethodSelector implements InvocationHandler {
    private Object proxied;

    public MethodSelector(Object proxied) {
        this.proxied = proxied;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if (method.getName().equals("interesting")){
            System.out.println("Proxy detected the interesting method");
        }
        return method.invoke(proxied,args);
    }
}
public class SelectingMethods {
    public static void main(String[] args) {
        SomeMethods proxy= (SomeMethods)Proxy.newProxyInstance(SomeMethods.class.getClassLoader(),
                new Class[]{SomeMethods.class}, new MethodSelector(new Implementation()));

        proxy.boring1();
        proxy.boring2();
        proxy.boring3();
        proxy.interesting("boon");
    }
}

输出结果:

boring1
boring2
boring3
Proxy detected the interesting method
interesting :boon

这里只查看了方法名,你还可以查看方法签名的其他方面,甚至可以搜索特定的参数值.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值