代理模式
代理模式(Proxy):对其他对象提供一种代理以控制对这个对象的访问
一、静态代理:代理和被代理对象在代理之前是确定的,它们都是实现了相同的接口或者继承了相同抽象类。
1.首先定义一个呗代理对象和被代理对象实现的接口GiveGift
package com.design.proxy;
/**
-
礼物
-
@author Administrator
*/
public interface GiveGift {
//送花
public void Flowers();
}
2.创建人物实体Goddess
package com.design.proxy;
/**
- 女神
- @author Administrator
*/
public class Goddess {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
3.创建被代理对象实现GiveGift接口
package com.design.proxy;
import java.util.Random;
/**
- 追求者
- @author Administrator
*/
public class Pursuit implements GiveGift {
private Goddess mm;
public Pursuit(Goddess mm){
this.mm = mm;
}
@Override
public void Flowers() {
try {
Thread.sleep(new Random().nextInt(1000));
System.out.println(mm.getName() + "送你鲜花");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
4.创建代理对象实现GiveGift接口
package com.design.proxy;
/**
- 代理
- @author Administrator
*/
public class Proxy implements GiveGift {
public Proxy(Goddess mm) {
gg = new Pursuit(mm);
}
private Pursuit gg;
@Override
public void Flowers() {
gg.Flowers();
}
}
5.测试类
package com.design.proxy;
public class Test {
public static void main(String[] args) {
Goddess mm = new Goddess();
mm.setName("Jane");
new Proxy(mm).Flowers();;
}
}
测试结果:Jane送你鲜花
二、动态代理
所谓Dynamic Proxy是这样一个class:它是在运行时生成class,该class需要实现一组interface,使用动态代理时必须实现InvocationHandler接口
Ⅰ. JDK动态代理

Java动态代理类位于java.lang.reflect包下,一般主要涉及两个类:
(1)Interface InvocationHandler:该接口定义一个方法
public object invoke(Object obj, Method method, Object[] args)
在实际应用时,第一个参数obj一般为代理类,method是被代理的方法,args为该方法的参数数组。这个抽象方法在代理类中动态实现。
(2) Proxy:该类即为动态代理类
static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h): 返回代理类的一个实例,返回后的代理类可以当作被代理类使用(可使用被代理类的在接口中声明过的方法)
JDK动态代理Demo:
1.创建一个TimeHandler类实现InvocationHandler接口
package com.design.jdkproxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class TimeHandler implements InvocationHandler {
public TimeHandler(Object target){
super();
this.target = target;
}
private Object target;
/**
* 参数:
* proxy 被代理的对象
* method 被代理对象的方法
* args 方法的参数
*
* 返回值:
* Object 方法的返回值
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
long starttime = System.currentTimeMillis();
System.out.println("委托送花开始...");
method.invoke(target);
long endtime = System.currentTimeMillis();
System.out.println("女神收到鲜花... 花费时间:"+(endtime-starttime)+"毫秒~");
return null;
}
}
2.创建测试类
package com.design.jdkproxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import com.design.proxy.GiveGift;
import com.design.proxy.Goddess;
import com.design.proxy.Pursuit;
public class Test {
public static void main(String[] args) {
Goddess mm = new Goddess();
mm.setName("Jane");
Pursuit cp = new Pursuit(mm);
InvocationHandler th = new TimeHandler(cp);
Class<?> cls = cp.getClass();
ClassLoader loader = cls.getClassLoader();
Class<?>[] interfaces = cls.getInterfaces();
/**
* loader 类加载器
* interfaces 实现接口
* h InvocationHandler
*/
GiveGift m = (GiveGift)Proxy.newProxyInstance(loader, interfaces, th);
m.Flowers();
}
}
测试结果:
委托送花开始...
Jane送你鲜花
女神收到鲜花... 花费时间:825毫秒~
JDK动态代理总结:
1.创建一个实现接口InvocationHandler的类,它必须实现invoke方法。
2.创建被代理类以及接口。
3.调用Proxy的静态方法,创建一个代理类 newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)。
4.通过代理调用方法。
Ⅱ.CGLIB动态代理(需要cglib-node.jar包)
链接:http://pan.baidu.com/s/1b27bae 密码:sfza
1.创建一个FlowerExecute类
package com.design.cglibproxy;
public class FlowerExecute {
public void Flower(){
System.out.println("鲜花派送中...");
}
}
2.创建CglibProxy代理类实现MethodInterceptor接口
package com.design.cglibproxy;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class CglibProxy implements MethodInterceptor {
private Enhancer enhancer = new Enhancer();
/**
* 动态创建给定类型的子类
*
* @param clazz 要代理的原始对象
* @return
*/
public Object getProxy(Class clazz) {
//设置创建子类的类
enhancer.setSuperclass(clazz);//设置代理目标
enhancer.setCallback(this); //设置回调
return enhancer.create();
}
/**
* 拦截所有目标类方法的调用
*
* 参数:
* obj 目标类的实例
* m 目标反射的方法对象
* args 方法的参数
* proxy 代理类的实例
*/
@Override
public Object intercept(Object obj, Method m, Object[] args,
MethodProxy proxy) throws Throwable {
System.out.println("前置代理");
//代理类调用父类的方法
proxy.invokeSuper(obj, args);
System.out.println("后置代理");
return null;
}
}
3.测试
package com.design.cglibproxy;
public class Test {
public static void main(String[] args) {
CglibProxy cp = new CglibProxy();
FlowerExecute fe = (FlowerExecute)cp.getProxy(FlowerExecute.class);
fe.Flower();
}
}
4.测试结果:
前置代理
鲜花派送中...
后置代理
Ⅲ.综合JDK动态代理与CGLIB动态代理可以发现
JDK动态代理:
1.只能代理实现了接口的类
2.没有实现接口的类不能实现JDK的动态代理
CGLIB动态代理:
1.针对类来实现代理的
2.对指定目标类产生一个子类,通过方法拦截技术拦截所有父类方法的调用。

浙公网安备 33010602011771号