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

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

    下面,我们将使用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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值