Core Java:使用java.lang.reflect实现JDK动态代理的小DEMO

时间:2022-03-23 13:52:29
    代理模式在Java的体系结构中具有非常重要的地位,包括Spring的整个庞大的IOC体系都是建立在代理模式之上,而AOP也是在代理模式的基础上发展起来,增加了触发动作行为的时机。因此掌握代理模式是非常必要的技能。
    下面通过一个简单的DEMO,来探究一下java.lang.reflect是如何实现代理模式的,重点在main方法上,我们明明为flyImpl实现类的wing(String)赋值为null,但是最终的输出结果中,却发现这个flyImpl对象的fly域变成了“A injected swing value....”,这一切是如何发生的呢?

    首先,定义一个接口类,fly,它具有两个方法,一个而是addWing,一个是fly。

package com.ziwen.vo;

public interface Flyable {
    public void addWing(String wing);
    public String fly();
}

    编写一个实现类,LittleBird实现Flyable。

package com.ziwen.vo;

public class LittleBird implements Flyable {
    private String wing;
    
    public String getWing() {
        return wing;
    }

    public void setWing(String wing) {
        this.wing = wing;
    }

    @Override
    public void addWing(String wing) {
        setWing(wing);
    }

    @Override
    public String fly() {
        return "wing:"+getWing()+"...fly";
    }

}


    按照JDK API的要求,需要有一个实现了Invocation的实现类:

package com.ziwen.vo;

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

public class ObjectHandler implements InvocationHandler {
    private Object target;
    public ObjectHandler(Object object){
        this.target = object;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        if("addWing".equals(method.getName())){
            args[0]="A injected swing value.";
        }
        return method.invoke(target, args);
    }

}

    最后,编写一个工厂方法,用于获取代理类,简便起见,将main方法也写在里面。

package com.ziwen.vo;

import java.lang.reflect.Proxy;

public class FlyFactory {
    public static Flyable getFlayImpl() {
        Flyable fly = new LittleBird();
        return (Flyable) Proxy.newProxyInstance(
                fly.getClass().getClassLoader(), new Class[] { Flyable.class },
                new ObjectHandler(fly));
    }
    public static void main(String[] args) {
        Flyable fly = FlyFactory.getFlayImpl();
        fly.addWing(null);
        System.out.println(fly.fly());
    }
}

    核心类说明:
    JDK提供了一个类,名字叫做Proxy.newProxyInstance(1,2,3)。其中,第一个参数是用于规定使用哪一个类的加载器?第二个参数是实现了哪些接口的数组,第三个参数是描述调用和它关联的一个invocationHandler的类型的对象。
    任何一个动态代理对象都要关联一个invocationHandler对象,只有这个对象才知道要代理什么事情。代理对象会调用invocationHandler中的invoke方法,这个invoke方法是被动态代理对象调用的,这样我们就可以扩展invoke方法,实现很多我们想做的事情。