一.什么是代理模式?
代理就是在不修改被代理对象的前提下,扩展被代理对象的功能
二.代理模式有哪些分类?
静态代理:程序运行前就已经存在代理类的字节码文件,代理类和目标类的关系就已经确定
动态代理:程序在运行时通过反射机制动态创建(jdk代理,cglib代理)三.静态代理模式的实现
静态代理是通过代理对象与目标对象实现相同的接口,然后在代理对象中调用目标对象中的方法实现的
1.接口
public interface RentHouse { void rent();}
2.目标对象
public class FindHouse implements RentHouse { @Override public void rent() { System.out.println("我要租房子!"); }}
3.代理对象
public class RentProxy implements RentHouse { private RentHouse rentHouse; public RentProxy(RentHouse rentHouse){ this.rentHouse = rentHouse; } @Override public void rent() { System.out.println("帮你找房子"); rentHouse.rent(); System.out.println("帮你搬家"); }}
4.测试类
public class Test { public static void main(String[] args) { FindHouse findHouse = new FindHouse(); RentProxy proxy = new RentProxy(findHouse); proxy.rent(); }}
四.动态代理之jdk代理
不需要我们手动的创建代理对象,代理对象的生成,是依靠JDK的API(java.lang.reflect.Proxy),动态的在内存中构建代理对象。
1.定义接口
public interface Person { //上交班费 void giveMoney();}
2.目标对象实现接口
public class Student implements Person { private String name; public Student(String name) { this.name = name; } @Override public void giveMoney() { try { //假设数钱花了一秒时间 Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(name + "上交班费50元"); }}
3.代理类
public class StuInvocationHandlerimplements InvocationHandler { //invocationHandler持有的被代理对象 T target; public StuInvocationHandler(T target) { this.target = target; } //绑定一个委托对象并返回一个代理类 public Object bind(T target) { this.target = target; //取得代理对象 return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this); //要绑定接口(这是一个缺陷,cglib弥补了这一缺陷) } /** * proxy:代表动态代理对象 * method:代表正在执行的方法 * args:代表调用目标方法时传入的实参 */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("代理执行" +method.getName() + "方法"); //代理过程中插入监测方法,计算该方法耗时 MonitorUtil.start(); Object result = method.invoke(target, args); MonitorUtil.finish(method.getName()); return result; }}
4.代理类中用到的记时工具
public class MonitorUtil { private static ThreadLocaltl = new ThreadLocal<>(); public static void start() { tl.set(System.currentTimeMillis()); } //结束时打印耗时 public static void finish(String methodName) { long finishTime = System.currentTimeMillis(); System.out.println(methodName + "方法耗时" + (finishTime - tl.get()) + "ms"); }}
5.执行目标对象时动态的调用代理方法
public class ProxyTest { public static void main(String[] args) { //创建一个实例对象,这个对象是被代理的对象 Person zhangsan = new Student("张三"); //创建一个与代理对象相关联的InvocationHandler InvocationHandler stuHandler = new StuInvocationHandler(zhangsan); //创建一个代理对象stuProxy来代理zhangsan,代理对象的每个执行方法都会替换执行Invocation中的invoke方法 Person stuProxy = (Person) ((StuInvocationHandler) stuHandler).bind(zhangsan); //代理执行上交班费的方法 stuProxy.giveMoney(); }}
五.cglib代理
CGLIB即使代理类没有实现任何接口也可以实现动态代理功能。CGLIB具有简单易用,它的运行速度要远远快于JDK的Proxy动态代理:
1.目标对象
public class service { public String services(){ return "My name is JarremDon"; } }
2.代理对象
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 { //需要代理的原始类 public Object object; public CglibProxy(Object object){ this.object=object; } public Object Proxy(){ //创建加强器 Enhancer enhancer=new Enhancer(); //设置需要加强的类 enhancer.setSuperclass(object.getClass()); //设置回调 enhancer.setCallback(this); enhancer.setClassLoader(object.getClass().getClassLoader()); return enhancer.create(); } @Override public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable { //这里实现加强 Object invoke=arg3.invoke(object, arg2); return invoke.toString().toUpperCase(); } }
3.测试类
public class MyTest { public static void main(String args[]){ service s=new service(); CglibProxy proxy=new CglibProxy(s); service s1=(service) proxy.Proxy(); System.out.println(s1.services()); } }