Java中的动态代理--JDK动态代理

来源:互联网 发布:如何卸载管家婆软件 编辑:程序博客网 时间:2024/05/22 00:32

       首先,我们用一个通俗的例子来理解一下代理。假设有一位明星,他会唱歌和跳舞。那么在这位明星成名之前,我们可以直接找这位明星唱歌和跳舞。但是他出名之后,肯定会找一个经济人,我们再想听这位明星唱歌或者看他跳舞,就只能先找到他的经济人,经纪人可能会向我们收费,然后再安排这位明星唱歌或者跳舞。这个经济人扮演的角色,其实就和我们今天要讲的代理特别相似。代理的目的是拦截对真实业务对象的直接访问。

    下面,我们将使用Java代码来实现动态代理。

(1)首先创建一个人类的接口

package com.sunyb.proxy;/** * 人类的接口 */public interface Person {    /**     * 唱歌方法     * @param songName 歌名     */    public abstract void sing(String songName);    /**     * 跳舞方法     * @param name 舞蹈名称     * @return     */    public abstract String dance(String name);}

(2)然后创建一个明星类,并实现人类接口

package com.sunyb.proxy;/** * 明星类 * @author sunyb * @since 2016-05-21 * @version 1.0 */public class PopStar implements Person {    @Override    public void sing(String songName) {        System.out.println("PopStar is singing " + songName);    }    @Override    public String dance(String name) {        System.out.println("PopStar is dancing " + name);        return "谢谢你们!";    }}

(3)创建代理对象类

package com.sunyb.proxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;/** * 明星类的代理类 * @author sunyb * @since 2016-05-21 * @version 1.0 */public class PopStarProxy {    public static Object createProxy(final Object targetObject){        /**         * @param   loader the class loader to define the proxy class         * @param   interfaces the list of interfaces for the proxy class         *          to implement         * @param   h the invocation handler to dispatch method invocations to         * @return  a proxy instance with the specified invocation handler of a         *          proxy class that is defined by the specified class loader         *          and that implements the specified interfaces         */        return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),                targetObject.getClass().getInterfaces(),                new InvocationHandler() {                    /**                     * @param proxy the proxy instance that the method was invoked on                     * @param method 被调用的方法                     * @param args 被调用方法上的参数                     * @return                     * @throws Throwable                     */                    @Override                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {                        Object result = null;                        System.out.println("我是代理对象,方法调用前...");                        String methodName = method.getName();                        switch (methodName){                            case "sing":                                System.out.println("唱歌前,需要先付8000元...");                                break;                            case "dance":                                System.out.println("跳舞前,需要先付12000元...");                                break;                            default:                                System.out.println("对不起,该明星没有这项技能!");                                break;                        }                        //开始调用真实对象的方法                        /**                         * 通过反射的方式调用method方法                         * targetObject 是被反射的对象,也就是调用它的method方法                         * args是调用该方法时需要的参数                         */                        result = method.invoke(targetObject, args);                        System.out.println("我是代理对象,方法调用后...");                        return result;                    }                });    }}

(4)编写测试程序

----->唱歌

PopStar popStar = new PopStar();        Person person = (Person) PopStarProxy.createProxy(popStar);        person.sing("南山南");

---结果

我是代理对象,方法调用前...
唱歌前,需要先付8000元...
PopStar is singing 南山南
我是代理对象,方法调用后...

--->跳舞

PopStar popStar = new PopStar();        Person person = (Person) PopStarProxy.createProxy(popStar);        String result = person.dance("天鹅湖");        System.out.println(result);

--结果

我是代理对象,方法调用前...
跳舞前,需要先付12000元...
PopStar is dancing 天鹅湖
我是代理对象,方法调用后...
谢谢你们!

(5)当业务逻辑复杂时可以像上面这么写,但是当业务简单时,不需要单独创建一个代理类,可以直接这么写:

final PopStar popStar = new PopStar();        Person person = (Person) Proxy.newProxyInstance(popStar.getClass().getClassLoader(),                popStar.getClass().getInterfaces(), new InvocationHandler() {                    @Override                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {                        System.out.println("唱歌或者跳舞前,需要先给8000块!");                        return method.invoke(popStar, args);                    }                });        String result = person.dance("钢管舞");        System.out.println(result);


0 0
原创粉丝点击