知识点:静态代理和动态代理
参考博客:https://www.cnblogs.com/daniels/p/8242592.html
https://blog.csdn.net/familyshizhouna/article/details/78905997
一:什么是代理模式
代理模式是给某个对象提供一个代理对象,由代理对象调用原对象的方法,类似我们生活中的中介,经纪人的角色,本人不直接去做,找一个人代替我们去做一些事情。
二:使用代理模式的好处
a.中介隔离作用:当我们不想直接调用一个对象时,代理对象可以起一个中介隔离的作用,被代理对象和代理对象都实现相同的接口
b.遵循开闭原则:我们可以通过代理类,在被代理类功能前后,加入一些公共服务,比如缓存,日志等,而不用修改原被代理类
三:代理模式的分类
按创建代理的时间分类可以分为:静态代理和动态代理
静态代理是代码创建后编译,运行之前,代理类的.class文件就已经创建了;
动态代理:是在程序运行时,通过反射机制动态创建代理对象的(另一篇博客简略地介绍Java中的反射:https://www.cnblogs.com/shuaifing/p/10863645.html)
(1)静态代理
//代理模式(静态代理) //测试类 public class StaticProxy { public static void main(String[] args) { Object obj=new ProxyObject(); obj.action(); } } //公共接口 interface Object{ void action(); } //代理类 class ProxyObject implements Object{ Object obj; public ProxyObject(){ System.out.println("代理类构造方法创建被代理类"); obj=new ObjectImp(); } @Override public void action() { System.out.println("代理类执行被代理类中的方法"); obj.action(); } } //被代理类 class ObjectImp implements Object{ @Override public void action() { System.out.println("被代理类输出的内容!"); } } 运行结果:
(2)动态代理
当有多个类要代理的话,手动创建多个代理对象比较麻烦,代码冗余,动态产生代理对象的话,代码更加灵活,方便
//动态代理,反射是动态语言的关键 //测试类 public class DynamicProxy { public static void main(String[] args) { //1.被代理类的对象 RealSubject realSubject=new RealSubject(); //2.创建一个实现InvocationHandler接口类的对象 MyInvocationHandler handler=new MyInvocationHandler(); //3.调用blind()方法,动态返回一个实现了跟被代理类所实现接口的代理对象 Object obj=handler.blind(realSubject); Subject subject=(Subject) obj;//subject是代理类对象 subject.action();//代理类对象调用action(),会转到对InvocationHandler接口实现类的invoke()方法调用 //增加另一个 ObjectImp的被代理对象,返回相应的代理对象 ObjectImp objIml=new ObjectImp(); com.kdgc.interfacetest.Object proxyObject= (com.kdgc.interfacetest.Object)handler.blind(objIml); proxyObject.action(); } } //公共接口 interface Subject{ void action(); } //被代理类 class RealSubject implements Subject{ @Override public void action() { System.out.println("被代理类要执行的方法!"); } } class MyInvocationHandler implements InvocationHandler{ Object obj;//实现了接口的被代理对象的声明 //1.给被代理对象实例化 2.返回一个代理类的对象 public Object blind(Object obj){ this.obj=obj; return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),this); } //当通过代理类的对象发起对被重写方法的调用时,会转化为对下面的invoke方法的调用 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object val=method.invoke(obj,args); return val; } } 运行结果:
(3)补充:动态代理与AOP
在固定的代码的位置,动态地调用不同对象的方法
//测试类
public class AOPTest { public static void main(String[] args) { Man man = new Man(); Person person = (Person) MyProxy.getProxyInstance(man); person.drink(); person.eat(); } } //公共接口 interface Person{ void eat(); void drink(); } //被代理类 class Man implements Person{ @Override public void eat() { System.out.println("吃东西!"); } @Override public void drink() { System.out.println("喝水!"); } } //固定的方法 class ChangelessMethodUtil{ public void method1(){ System.out.println("===========方法1=========="); } public void method2(){ System.out.println("============方法2==========="); } } class MyInvocationHanlder implements InvocationHandler{ Object obj;//代理类的声明 public void setObject(Object obj){ this.obj=obj; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { ChangelessMethodUtil changelessMethodUtil=new ChangelessMethodUtil(); changelessMethodUtil.method1(); method.invoke(obj,args); changelessMethodUtil.method2(); return null; } } class MyProxy{ //动态创建一个代理类的对象 public static Object getProxyInstance(Object obj){ MyInvocationHanlder hanlder=new MyInvocationHanlder(); hanlder.setObject(obj); return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),hanlder); } }
运行结果: