代理是一种设计模式,提供了对目标对象另外的访问方式,即通过代理对象访问目标对象。可以不修改目标对象,对目标对象功能进行拓展
代理模式的实现:代理模式的实现分为两大类:静态实现和动态实现,动态实现根据实现的方式分为:jdk 动态实现,cglib动态实现
静态实现: 组成部分:
代理目标接口:定义代理类和目标实现类的基本模板,代理类和目标实现类都要实现这个接口
目标对象: 实现代理目标接口的实现类
代理类: 持有目标对象,根据不同的策略选择不同的方法调用目标对象的方法。
静态代理的优缺点:
优点: 做到不修改目标对象的功能前提下,对目标功能扩展
缺点: 因为代理对象需要与目标对象实现同样的接口,所以会有很多代理类,目标类,同时修改接口,目标类和代理类都要维护。
实现:
代理目标接口:
public interface Person { void say();}实现类:
public class LiudeHua implements Person { public void say() { System.out.println("hello,I`m 刘德华"); }}
实现类2:
public class ZhangSan implements Person { public void say() { System.out.println("hello,I`m zhangSan"); }}工具类:虽然不是必须的,但是为了体现拓展性,所以还是要:
public class MonitorUtil { private static ThreadLocal<Long> threadLocal = new ThreadLocal<Long>(); public static void start(){ System.out.println("开始调用" +System.currentTimeMillis()); threadLocal.set(System.currentTimeMillis()); } public static void finish(String methodName){ System.out.println("调用结束" +System.currentTimeMillis()); System.out.println(methodName + "方法耗时" + (System.currentTimeMillis() - threadLocal.get()) + "ms"); }}
代理类:
public class PersonProxy implements Person { Person liuDeHua = new LiudeHua(); Person zhangSan = new ZhangSan(); public void say() { }public void say(String name){ MonitorUtil.start(); if("zhangsan".equals(name)){ zhangSan.say(); }else if("liudehua".equals(name)){ liuDeHua.say(); } MonitorUtil.finish(name);}
方法调用:
public static void main(String args[]){ PersonProxy proxy = new PersonProxy(); proxy.say("zhangsan"); proxy.say("liudehua"); }
结果:
Jdk动态代理:
组成部分:
目标类接口目标实现类Java.lang.reflect.Proxy类的Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)InvocationHandler接口的实现类:实现调用目标类的扩展逻辑JDK动态代理的优缺点:
优点:动态实现了不改变目标对象逻辑的扩展
缺点:目标必须实现接口,不然无法实现动态代理
Java代码实现:
目标接口:
public interface Person { void say(String word);}实现类:
实现类1:
public class Student implements Person { public void say(String word) { System.out.println("我是学生"+word); System.out.println("我是学生"+word); System.out.println("我是学生"+word); }}实现类2:
public class Teacher implements Person { public void say(String word) { System.out.println(word); System.out.println(word); System.out.println(word); }}
InvocationHandler接口实现
public class ProxyInvocationHandler implements InvocationHandler { private Object target; public ProxyInvocationHandler(Object target){ this.target = target; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { MonitorUtil.start(); Object resultValue = method.invoke(target,args); MonitorUtil.finish(target.getClass().getName()); return resultValue;}Main类调用:
public class Main { public static void main(String args []){ Person statudent = new Student(); Person tearcher = new Teacher(); InvocationHandler statudentInvocation = new ProxyInvocationHandler(statudent); InvocationHandler tearcherInvocation = new ProxyInvocationHandler(tearcher); Person studentProxy = (Person) Proxy.newProxyInstance(statudent.getClass().getClassLoader(),statudent.getClass().getInterfaces(),statudentInvocation); Person TearcherProxy = (Person) Proxy.newProxyInstance(tearcher.getClass().getClassLoader(),tearcher.getClass().getInterfaces(),tearcherInvocation); studentProxy.say("我要好好学习"); TearcherProxy.say("我要带好学生"); }}
实现结果:
Cglib实现代理
组成部分:
实现类:实现具体目标的逻辑
代理类:实现MethodInterceptor接口,扩展逻辑实现
Enhancer 设置代理类,并且生成代理对象,
优点:
实现了不适用接口就可以实现动态代理
缺点: 实现类没有统一的限定格式
Java代码实现:
目标类:
public class Student { public void say(){ System.out.println("哈喽"); }}
代理类:
public class ProxyFactory implements MethodInterceptor { private Object target; public ProxyFactory(Object target) { this.target = target; } public Object getInstance(){ Enhancer en = new Enhancer(); en.setSuperclass(target.getClass()); en.setCallback(this); return en.create(); } public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { MonitorUtil.start(); Object object = method.invoke(target,objects); MonitorUtil.finish("intercept"); return object; }}
启动类:public class Main {
public static void main(String args []) { Student target = new Student(); Student proxy = (Student) new ProxyFactory(target).getInstance(); proxy.say(); }}结果:
三种方法类的思维导图: