代理模式
来源:互联网 发布:苹果7为什么4g网络很慢 编辑:程序博客网 时间:2024/06/05 18:55
代理设计模式(Proxy Pattern),为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
代理模式中涉及的角色:
抽象角色:通过接口或抽象类声明真实角色实现的业务方法。
代理角色:实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作。
真实角色:实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用。
宏观而言,代理模式分为两种类型,动态代理和静态代理。
静态代理:代理和被代理对象在代理之前是确定的,他们都实现相同的接口或继承了相同的抽象类。
这里以计算动物的奔跑时间为例,
继承的方式实现静态代理:
/** * @author BeautifulSoup * 定义全局接口,用于奔跑 */public interface Run { void run();}/** * @author BeautifulSoup * 定义真实对象完成真实操作. */public class Animal implements Run { public void run() { System.out.println("动物在奔跑"); try { Thread.sleep(new Random().nextInt(1000));//模拟动物奔跑 } catch (InterruptedException e) { e.printStackTrace(); } }}/** * @author BeautifulSoup * 得到代理对象,为满足实际需求而进行某方面的增强 */public class AnimalProxy extends Animal { @Override public void run() { long startTime=System.currentTimeMillis(); super.run(); long endTime=System.currentTimeMillis(); System.out.println("动物奔跑的时间为:"+(endTime-startTime)); }}/** * @author BeautifulSoup * 实际开发只需要调用代理对象就能完成指定的操作 */public class TestProxy { public static void main(String[] args) { AnimalProxy proxy=new AnimalProxy(); proxy.run(); }}
基于聚合的方式实现代理(该方式更加适合存在多种含有执行顺序的操作的代理中):
//接口和真实对象的代码不变/** * @author BeautifulSoup * 得到代理对象,为满足实际需求而进行某方面的增强 */public class AnimalProxy implements Run { private Run run; public AnimalProxy(Run run) { super(); this.run = run; } public void run() { long startTime=System.currentTimeMillis(); run.run(); long endTime=System.currentTimeMillis(); System.out.println("动物奔跑花费的时间为:"+(endTime-startTime)); }}/** * @author BeautifulSoup * 实际开发只需要调用代理对象就能完成指定的操作 */public class TestProxy { public static void main(String[] args) { Animal animal=new Animal(); AnimalProxy proxy=new AnimalProxy(animal); proxy.run(); }}
动态代理: Java中目前实现动态代理的方式有2中,分别是Jdk的动态代理和CGLib的动态代理,Jdk的动态代理是基于接口的动态代理,也就是说代理类和被代理类对象都应该实现相同的接口;而基于CGLib的动态代理是以类及策划你给的方式来实现的。基于CGLib的动态代理在Spring等框架中应用的比较多。这里仅介绍基于JDK的动态代理,在以后介绍Spring的AOP中会介绍基于类级别的代理方式。
这里还是以记录日志的例子来说明JDK的动态代理的使用。
在实际的开发中,往往都是面向接口编程的,对于持久层的代码,先新建接口后实现。
/** * @author BeautifulSoup * Dao层的接口 */ public interface UserDao { public void add(); public void update();}/** * @author BeautifulSoup * Dao层的实现类 */public class UserDaoImpl implements UserDao{ public void add() { System.out.println("add..."); } public void update() { System.out.println("update..."); }}/** * @author BeautifulSoup * 现在要为Dao层记录日志 */ public class UserDaoProxy { private UserDao userDao; public UserDaoProxy(UserDao userDao) { super(); this.userDao=userDao; } public UserDao createProxy(){ UserDao proxy=(UserDao) Proxy.newProxyInstance(userDao.getClass().getClassLoader(),userDao.getClass().getInterfaces(), new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if("update".equals(method.getName())){ System.out.println("日志记录开始......."); Object result=method.invoke(userDao, args); System.out.println("日志记录结束"); return result; } return method.invoke(userDao, args); } }); return proxy; }}
客户端测试的代码:
public class Test01 { @Test public void test01(){ UserDao userDao=new UserDaoImpl(); userDao.add(); userDao.update(); } @Test public void test02(){ UserDao userDao=new UserDaoImpl(); UserDao proxy=new UserDaoProxy(userDao).createProxy(); proxy.add(); proxy.update(); }}
JDK的动态代理是通过Proxy这个类来实现的,其中newInstance方法前两个参数都是固定的,传递接口和类的Class对象(这里也可以知道原理是反射实现的动态代理),第三个参数是InvocationHandler,一般使用匿名内部类的方式来实现参数的传递。其中的抽象方法中的三个参数分别代表被代理类、要被代理的方法和方法中的参数。
- 代理模式--动态代理
- 代理模式-静态代理
- 代理模式-静态代理
- 代理模式 & 动态代理
- 代理模式--静态代理
- 代理模式--动态代理
- 代理模式(动态代理)
- 代理模式-动态代理
- 代理模式-动态代理
- 代理模式动态代理
- 代理模式-静态代理
- 代理模式-动态代理
- 代理模式 -动态代理
- 代理模式---动态代理
- 代理模式-动态代理
- 代理模式--静态代理
- 代理模式!
- 代理模式
- HDU 1176 免费馅饼 (动态规划)
- javascript字符串
- SQL连接查询2 外连接(左右联接查询)
- 策略模式 Java
- java的几种对象(PO,VO,DAO,BO,POJO)解释
- 代理模式
- springboot @import @importResource 注解使用方式
- 颠覆你的思维,探寻人类发展史
- 自动化邮件报告平台-邮件发送highchart图表
- 《C和指针》练习题~6.18-2 del_substr()
- LeetCode 145. Binary Tree Postorder Traversal java solution
- stm32f103的11个定时器详解
- [mysql] Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'lo
- 协议栈