程序中的解释:代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用,
中介隔离作用:在某些情况下,一个客户类不想或者不能直接引用一个委托对象,而代理类对象可以在客户类和委托对象之间起到中介的作用,其特征是代理类和委托类实现相同的接口。
开闭原则,增加功能:代理类除了是客户类和委托类的中介之外,我们还可以通过给代理类增加额外的功能来扩展委托类的功能,这样做我们只需要修改代理类而不需要再修改委托类,符合代码设计的开闭原则。代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后对返回结果的处理等。代理类本身并不真正实现服务,而是同过调用委托类的相关方法,来提供特定的服务。真正的业务功能还是由委托类来实现,但是可以在业务功能执行的前后加入一些公共的服务。例如我们想给项目加入缓存、日志这些功能,我们就可以使用代理类来完成,而没必要打开已经封装好的委托类
所学的框架中使用的代理: spring AOP,MyBatis中mapper接口,等。。。
我们有多种不同的方式来实现代理。如果按照代理创建的时期来进行分类的话, 可以分为两种:
静态代理、(基于接口/基于父类)其实继承,重写父类方法就是一种代理的简单实现, 静态代理是由程序员创建或特定工具自动生成源代码,在对其编译。在程序员运行之前,代理类.class文件就已经被创建了。
动态代理。(JDK/CGLIB) 动态代理是在程序运行时通过反射机制动态的在内存中创建的。
静态代理:继承方式
package cn.sta; /** * 顾客类,自定义点餐方法 */ public class Customer { public String order(String foodName) { System.out.println("顾客点了一道:"+foodName+"菜"); return foodName; } } package cn.sta; /** * 外卖员,继承顾客,代替顾客完成点餐 */ public class Takeaway extends Customer { @Override public String order(String foodName) { //对目标类进行增强 System.out.println("准备接单。。。。。。"); foodName = super.order(foodName); System.out.println("外卖员成功接单,正在配送。。。。。。"); System.out.println("成功送到顾客手中,此订单已完成。。"); return "很鲜美的"+foodName; } } package cn.sta; public class Test { public static void main(String[] args) { Customer customer = new Takeaway();//代理类,实际为外卖员引用,帮助顾客,完成点餐 String foodName = customer.order("鱼香肉丝"); System.out.println("吃到了,"+foodName);//表面并未做任何事情,就可以完成目的, } }静态代理 :实现接口的方式
点餐接口
package cn.sta; /** * 点餐接口 */ public interface OrderingFood { String order(String foodName); }顾客类,实现点餐接口
package cn.sta; /** * 顾客类,实现点餐接口 */ public class Customer implements OrderingFood { @Override public String order(String foodName) { System.out.println("顾客点了一道:"+foodName+"菜"); return foodName; } }代理类:同样实现点餐接口,内部包含一个要代理的对象,即顾客引用
package cn.sta; public class Takeaway implements OrderingFood { //代理的对象 private OrderingFood orderingFood; //传入要代理的对象 public Takeaway (OrderingFood orderingFood){ this.orderingFood=orderingFood; } @Override public String order(String foodName) { //对目标类进行增强 System.out.println("准备接单。。。。。。"); foodName = orderingFood.order(foodName); System.out.println("外卖员成功接单,正在配送。。。。。。"); System.out.println("成功送到顾客手中,此订单已完成。。"); return "很鲜美的"+foodName; } }测试类
package cn.sta; public class Test { public static void main(String[] args) { Customer customer = new Customer();//顾客, OrderingFood orderingFood = new Takeaway(customer);//代理类, String foodName = orderingFood.order("鱼香肉丝");//外卖员,帮助顾客,完成点餐 System.out.println("吃到了,"+foodName);//表面并未做任何事情,就可以完成目的, } }输出结果 从上面看到,被代理的类,表面未做任何操作,就可以达到目的, 缺点:当需要代理大量接口时,需要,为每一个接口编写代理类,动态代理正是解决了这一缺点
动态代理:jdk(接口)
package cn.dynamic; /** * 模拟用户删除,进行增强处理 */ public interface UserService { int delUser(Integer id); } package cn.dynamic; /** * 要进行增强的类 */ public class UserServiceImpl implements UserService { @Override public int delUser(Integer id) { System.out.println("用户id为"+id+"的用户以删除!"); return id; } } package cn.dynamic; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; //测试 public class Test { public static void main(String[] args) throws Exception { UserServiceImpl userServiceImpl = new UserServiceImpl(); UserService UserService =(UserService)Proxy.newProxyInstance( userServiceImpl.getClass().getClassLoader(), userServiceImpl.getClass().getInterfaces(), new InvocationHandler() { @Override//proxy:代理对象 method:执行的具体方法 args:方法的入参 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println(method.getName()+"方法执行前,日志记录。。。"); Object rs = method.invoke(userServiceImpl,args[0]); System.out.println("方法执行结束!事物提交。。。"); return rs; } } ); int i = UserService.delUser(1); System.out.println(i); } }Proxy.newProxyInstance(类加载器,所实现的接口数组,InvocationHandler接口)
未完结