JAVA反射_代理

一、什么是动态代理

动态代理可以提供对另一个对象的访问,同时隐藏实际对象的具体事实。代理一般会实现它所表示的实际对象的接口。代理可以访问实际对象,但是延迟实现实际对象的部分功能,实际对象实现系统的实际功能,代理对象对客户隐藏了实际对象。客户不知道它是与代理打交道还是与实际对象打交道。

目的:主要用来做方法的增强,让你可以在不修改源码(不用改变这个方法的签名,原来调用这个方法的类依然能正常工作)的情况下,增强一些方法。在方法执行前后做任何你想做的事情(甚至根本不去执行这个方法),因为在InvocationHandler的invoke方法中,你可以直接获取正在调用方法对应的Method对象,具体应用的话,比如可以添加调用日志,做事务控制等。

还有一个有趣的作用是可以用作远程调用,比如现在有Java接口,这个接口的实现部署在其它服务器上,在编写客户端代码的时候,没办法直接调用接口方法,因为接口是不能直接生成对象的,这个时候就可以考虑代理模式(动态代理)了,通过Proxy.newProxyInstance代理一个该接口对应的InvocationHandler对象,然后在InvocationHandler的invoke方法内封装通讯细节就可以了。具体的应用,最经典的当然是Java标准库的RMI,其它比如hessian,各种webservice框架中的远程调用,大致都是这么实现的。
而像 AspectJ 这种 AOP 刚不同,它直接把人家的 class 代码修改了,它就不需要使用代理。
这些在新的 JDK 6 中都可以通过 Instrument 来做到,不过也是个通用的方法,还得通过规则来定制什么情况下处理,什么时候不处理。

二、jdk的动态代理
  目前Java开发包中包含了对动态代理的支持,但是其实现只支持对接口的的实现。 其实现主要通过java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口。 

Proxy类主要用来获取动态代理对象,InvocationHandler接口用来约束调用者实现。

动态代理是很多框架和技术的基础, spring 的AOP实现就是基于动态代理实现的。了解动态代理的机制对于理解AOP的底层实现是很有帮助的。



平常写的代码,一般是一个对象直接持有另外一个对象的引用,称为

静态代理

public class StaticProxyMain {

    //这里传入的是接口类型的对象,方便向上转型,实现多态
    public static void consumer(ProxyInterface pi){
        pi.say();
    }
    public static void main(String[] args) {
        StaticProxyMain.consumer(new ProxyObject());
    }
}


//代理接口
interface ProxyInterface{
    void say();
}


//被代理者
class RealObject implements ProxyInterface{
    //实现接口方法
    @Override
    public void say() {
        System.out.println("say");
    }

}


//代理者
class ProxyObject implements ProxyInterface{

    @Override
    public void say() {

        System.out.println("hello proxy");
        new RealObject().say();
        System.out.println("this is method end");
    }

}


动态代理:

例子1:

public class DProxyMain {

    public static void main(String[] args) {
        ArrayList<String> content = new ArrayList<>();
        MyInvocationHandler handler = new MyInvocationHandler(content);
        Object proxy = Proxy.newProxyInstance(null, new Class[]{List.class}, handler);

        if (proxy instanceof List) {
            System.out.println("proxy is list");

            List<String> mlist = (List<String>) proxy;
            mlist.add("one");
            mlist.add("two");
            mlist.add("three");
            mlist.add("apple");

        }

        System.out.println("proxy:"+proxy.toString());
        System.out.println("content:"+content.toString());
    }

}

class MyInvocationHandler implements InvocationHandler {

    private Object target;

    public MyInvocationHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        System.out.println("method name:"+method.getName());

        if (method.getName().equals("add")) {
            if (args[0].equals("apple")) {
                return false;
            }
        }


        return method.invoke(this.target, args);
    }
}

例子2:

public class DynamicProxyMain {

    public static void main(String[] args) {
        RealObject realObject = new RealObject();
        ProxyInterface proxyInterface = (ProxyInterface) Proxy.newProxyInstance(ProxyInterface.class.getClassLoader(), new Class[]{ProxyInterface.class}, new ProxyObject(realObject));
        proxyInterface.say();
    }
}


//代理接口
interface ProxyInterface{
    void say();
}

//被代理类
class RealObject implements ProxyInterface {

    @Override
    public void say() {
        System.out.println("I'm talking...");
    }
}

//代理类,实现InvocationHandler 接口
class ProxyObject implements InvocationHandler {
    private Object target = null;

    public ProxyObject(Object proxied){
        this.target  = proxied;
    }


    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("method name:"+method.getName());

        return method.invoke(this.target, args);
    }
}


应用场景:

1. 利用动态代理实现设计模式,修饰器和适配器

2. AOP编程(Spring AOP)


猜你喜欢

转载自blog.csdn.net/kingdam578/article/details/78550910