代理模式的定义
代理模式: 由于某些原因需要给某对象提供一个代理以控制对该对象的访问,这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介
特点
- *优点: *
- 代理模式在客户端与目标对象之间起到一个中介作用和保护目标对象的作用
- 代理对象可以扩展目标对象的功能
- 代理模式能将客户端与目标对象分离,在一定程度上降低了系统的耦合度
- *缺点: *
- 在客户端和目标对象之间增加一个代理对象,会造成请求处理速度变慢
- 增加了系统复杂度
模式的结构与实现
模式的结构
抽象主题(Subject)类:通过接口或抽象类声明真实主题和代理对象实现的业务方法
真实主题(Real Subject)类:实现了抽象主题中的具体业务,是代理对象所代表的真实对象,是最终要引用的对象
代理(Proxy)类:提供了与真实主题相同的接口,其内部含有对真实主题的引用,它可以访问、控制或扩展真实主题的功能
模式的实现
静态代理
- 代理对象和目标对象实现相同的接口(保证代理对象与目标对象类型一致,面向接口编程代理对象可完全替换目标对象进行传参)
可以做到不修改目标对象功能的前提下对目标对象进行扩展
- 一旦接口增加方法,目标对象与代理对象都需要维护(缺点)
//抽象主题 public interface Dao { void save(); } //真实主题 class UserDao implements Dao { @Override public void save() { System.out.println("保存"); } } //代理 class UserDaoProxy implements Dao{ private UserDao userDao; @Override public void save() { if(userDao == null) userDao = new UserDao(); System.out.println("保存前进行的事务"); // userDao.save(); System.out.println("保存后进行的事务"); } }
动态代理(接口代理)
解决了静态代理的缺点
使用JDK提供的api动态的在内存重生成代理对象(又叫jdk代理,接口代理)
代理对象类型为实现接口的类型(不能强转为实现类类型)
//抽象主题 public interface Dao { void save(); } //真实主题 class UserDao implements Dao { @Override public void save() { System.out.println("保存"); } } //动态代理工厂 public class ProxyFactory{ //通过构造函数传入目标对象 private Object target; public ProxyFactory(Object target) { this.target = target; } //生成代理对象的方法 public Object getProxyInstance(){ return Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), (Object proxy, Method method, Object[] args) ->{ Object value = null; if("save".equals(method.getName())) { //只对save方法进行代理 System.out.println("开启事务"); value = method.invoke(target, args); System.out.println("事务结束"); } else value = method.invoke(target,args); return value; } ); } }
cglib代理(子类代理)
需要引入jar包(spring3.2以上core包中已经集成)
在内存重构建一个子类对象,从而实现对目标对象的扩展
代理类需要实现MethodInterceptor接口
需要代理的类不能为final或static(会报错),同时方法不能final(此时不报错,但是不能拦截该方法)
//代理工厂 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) //设置回调函数 //回调函数作用: 执行目标对象的方法会触发执行重写的intercept的方法 return en.create(); //创建子类并返回 } //重写的intercept方法 @Override public Object intercept(Object obj,Method method,object[] args, MethodProxy proxy){ System.out.println(“开始事务”); Object value = method.invoke(target,args); //执行目标对象的方法 System.out.println(“提交事务”); return value; } }