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