所谓的代理模式就是为其它类或对象提供一个代理以控制对这个对象的访问。那么常见的代理有远程代理,虚拟代理,保护代理,智能代理。

1. 远程代理:为一个不同地址空间的对象提供一个本地代理对象。

2. 虚拟代理:根据需要创建一个开销很大的对象。

3. 保护代理:控制原始对象的访问。

4. 智能代理:取代简单的指针,它在访问对象时执行一些附件操作

实现代理的有两种方式

1. 静态代理:就是代理和被代理的对象在代理之前是确定的,他们可以通过继承抽象类或者实现相同的接口来实现。

下面使用代理模式来模拟实现我一天的生活。

<1>. 首先先通过继承方式来实现代理模式, 创建被代理的接口和实现类

package com.dcz.proxy;

public interface IWork {

	/**
* 工作
*/
public void working();
}
package com.dcz.proxy;

public class Work implements IWork {

	@Override
public void working() { System.out.println("开始一天的工作....");
} }

<2>. 通过使用继承的方法来实现对工作类的代理,代码如下

package com.dcz.proxy;

public class InheritProxy extends Work {

	@Override
public void working() { System.out.println("出家门,驾车去公司...");
super.working();
System.out.println("出公司门,驾车回家...");
} }

<3>. 通过使用聚合的方法来实现对工作类的代理,代码如下

package com.dcz.proxy;

public class AggregationProxy implements IWork {

	private IWork work;

	public AggregationProxy(IWork work) {
super();
this.work = work;
} @Override
public void working() { System.out.println("出家门,驾车去公司...");
work.working();
System.out.println("出公司门,驾车回家...");
} }

那么既然有两种方法可以实现代理模式,那么毕竟会 有一种比较优越的方法,哪会是哪一种 呢。那好,思考一个问题,假如我们有多层代理去代理一个目标方法,如果使用继承的话就会一类依赖一个类,并且有很多层继承。聚合就不同了,他们不管要实现多少层代理,都是统一实现一个接口。这样具有灵活性,并且类的设计原则告诉我们要少用继承多用聚合。

下面使用代码来模拟我一天的工作内容。

<1>. 还是针对上面的Work接口和类,创建代理类1

package com.dcz.proxy;

public class WorkProxy1 implements IWork {

	private IWork work;

	public WorkProxy1(IWork work) {
super();
this.work = work;
} @Override
public void working() { System.out.println("出家门,驾车去公司...");
work.working();
System.out.println("出公司门,驾车回家...");
} }

<2>. 创建代理类2

package com.dcz.proxy;

public class WorkProxy2 implements IWork {

	private IWork work;

	public WorkProxy2(IWork work) {
super();
this.work = work;
} @Override
public void working() { System.out.println("吃早饭...");
work.working();
System.out.println("吃晚饭...");
} }

<3>. 创建代理类3

package com.dcz.proxy;

public class WorkProxy3 implements IWork {

	private IWork work;

	public WorkProxy3(IWork work) {
super();
this.work = work;
} @Override
public void working() { System.out.println("早锻炼...");
work.working();
System.out.println("晚散步");
} }

<4>. 测试

package com.dcz.proxy;

public class ProxyTest2 {

	public static void main(String[] args) {

		IWork work = new Work();
// 代理1
WorkProxy1 workProxy1 = new WorkProxy1(work);
// 代理2
WorkProxy2 workProxy2 = new WorkProxy2(workProxy1);
// 调用
workProxy2.working(); } }

<5> . 输出

吃早饭...
出家门,驾车去公司...
开始一天的工作....
出公司门,驾车回家...
吃晚饭...

假如你要将代理类1和代理类2调换一下,这将很容易做到。这就是静态代理模式,但是这也将使用具有一定的范围,思考一个问题,我们做代理的时候是知道代理和被代理对象,假如我们想为我们项目中的某些类方法实现代理,而现在我们不知道具体是哪些类方法,那么该如何做呢——动态代理。

2. 动态代理

动态代理有两种实现的方式,一种是jdk原生支持的动态代理,一种是第三方的实现cglib动态代理,两者有一定的区别,下面分别使用代码实现。

<1> jdk动态代理

实现步骤:

(1). 创建一个实现接口InvocationHandler的类,实现invoke方法。

(2). 创建代理类和接口

(3). 调用Proxy的静态方法,创建一个代理实例

(4). 通过代理调用目标方法

代码实现:

(1). 首先先定义代理类接口

package com.dcz.jdkproxy;

public interface IDoSomething {

	/**
* 做某事
*/
public void doSomething(); }

(2). 创建实现类

package com.dcz.jdkproxy;

import java.util.Random;

public class DoSomething implements IDoSomething {

	@Override
public void doSomething() { try {
Thread.sleep(new Random().nextInt(1000));
System.out.println("做事中....");
} catch (InterruptedException e) {
e.printStackTrace();
}
} }

(3).  代理实现

package com.dcz.jdkproxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method; public class TimeProxy implements InvocationHandler { private Object target; public TimeProxy(Object target) {
super();
this.target = target;
} @Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
long startTime = System.currentTimeMillis();
System.out.println("开始计时...");
method.invoke(target);
long endTime = System.currentTimeMillis();
System.out.println("计时结束... 用时:" + (endTime-startTime)+"毫秒");
return null;
} }

(4). 测试

package com.dcz.jdkproxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy; public class ProxyTest { public static void main(String[] args) { // JDK动态代理测试
IDoSomething doSomething = new DoSomething(); InvocationHandler timeProxy = new TimeProxy(doSomething); /**
* loader 类加载器
* interfaces 实现接口
* h
*/
IDoSomething ds = (IDoSomething)Proxy.newProxyInstance(doSomething.getClass().getClassLoader(),
doSomething.getClass().getInterfaces(),
timeProxy);
ds.doSomething(); } }

从上面代码可以看到,jdk内置实现的代理是需要代理类实现一个接口的,也就是说使用jdk动态代理要求代理类必须要实现一个接口。

2. cglib动态代理

代码实现:

(1). 创建代理类

package com.dcz.cglibproxy;

import java.util.Random;

public class DoSomething {

	public void doSomething() {

		try {
Thread.sleep(new Random().nextInt(1000));
System.out.println("做事中....");
} catch (InterruptedException e) {
e.printStackTrace();
}
} }

(2). 创建cglib代理

package com.dcz.cglibproxy;

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy; public class CglibProxy implements MethodInterceptor { private Enhancer enhance = new Enhancer(); public Object getProxy(Class<?> clazz){
// 设置创建子类的类
enhance.setSuperclass(clazz);
enhance.setCallback(this);
return enhance.create();
} /**
* 拦截所有目标类方法的调用
* object 目标类实例
* method 目标方法反射对象
* args 方法参数
* proxy 代理类实例
*/
@Override
public Object intercept(Object object, Method method, Object[] args,
MethodProxy proxy) throws Throwable { long startTime = System.currentTimeMillis();
System.out.println("计时开始...");
// 代理类调用父类的方法
proxy.invokeSuper(object, args);
long endTime = System.currentTimeMillis();
System.out.println("计时结束...用时:" + (endTime - startTime) + "毫秒");
return null;
} }

(3). 测试

package com.dcz.cglibproxy;

public class CglibProxyTest {

	public static void main(String[] args) {

		CglibProxy poxy = new CglibProxy();

		DoSomething doSomething = (DoSomething)poxy.getProxy(DoSomething.class);

		doSomething.doSomething();
} }

cglib动态代理可以为任何的类实现代理

Java设计模式 之 代理模式的更多相关文章

  1. Java设计模式之代理模式(静态代理和JDK、CGLib动态代理)以及应用场景

    我做了个例子 ,需要可以下载源码:代理模式 1.前言: Spring 的AOP 面向切面编程,是通过动态代理实现的, 由两部分组成:(a) 如果有接口的话 通过 JDK 接口级别的代理 (b) 如果没 ...

  2. java设计模式6——代理模式

    java设计模式6--代理模式 1.代理模式介绍: 1.1.为什么要学习代理模式?因为这就是Spring Aop的底层!(SpringAop 和 SpringMvc) 1.2.代理模式的分类: 静态代 ...

  3. 夜话JAVA设计模式之代理模式(Proxy)

    代理模式定义:为另一个对象提供一个替身或者占位符以控制对这个对象的访问.---<Head First 设计模式> 代理模式换句话说就是给某一个对象创建一个代理对象,由这个代理对象控制对原对 ...

  4. Java设计模式:代理模式(转)

    代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能.这里使用到编程中的一 ...

  5. Java 设计模式_代理模式(2016-08-19)

    概念: 代理模式是对象的结构模式.代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用. 就是一个人或者机构代表另一个人或者机构采取行动.在一些情况下,一个客户不想或者不能够直接引用一 ...

  6. JAVA设计模式:代理模式&& 装饰模式区别

    在前面学习了代理模式和装饰模式后,发现对两者之间有时候会混淆,因此对两者进行了区别和理解: 装饰模式你可以这样理解,就像糖一样,卖的时候商家大多要在外面包一层糖纸,其实原本还是糖. public in ...

  7. Java设计模式:代理模式(二)

    承接上文 三.计数代理 计数代理的应用场景是:当客户程序需要在调用服务提供者对象的方法之前或之后执行日志或者计数等额外功能时,就可以用到技术代理模式.计数代理模式并不是把额外操作的代码直接添加到原服务 ...

  8. java设计模式之代理模式 ,以及和java 回调机制的区别

    java 代理模式就是: 将自己要做的事交给别人去做(这个别人就是代理者,自己就是被代理者),为什么自己能做的要交给别人去做了?假如一个小学生小明,现在要写作业,但是又想玩游戏,他更想玩游戏,并且不想 ...

  9. Java设计模式之代理模式(Proxy)

    前言: 最近在研究Retrofit开源框架的时候,其主要核心代码是通过注解标示参数,动态代理模式实现具体接口,反射机制进行参数解析,最终实现发送请求.其实之前在学习Xutils源码的时候,Xutils ...

随机推荐

  1. python requests

    快速上手http://docs.python-requests.org/zh_CN/latest/user/quickstart.html Requests 是使用 Apache2 Licensed ...

  2. JS-Array数组对象

    <!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>A ...

  3. canvas练习

    <!doctype html><html><head><meta charset="utf-8"><title>move ...

  4. Java数据结构——用双端链表实现队列

    //================================================= // File Name : LinkQueue_demo //---------------- ...

  5. Codeforces 719B Anatoly and Cockroaches(元素的交叉排列问题)

    题目链接:http://codeforces.com/problemset/problem/719/B 题目大意: 有一队蟑螂用字符串表示,有黑色 ‘b’ 和红色 'r' 两种颜色,你想使这队蟑螂颜色 ...

  6. FingerGestures for Unity3D

    FingerGestures http://fingergestures.fatalfrog.com

  7. 正则表达式分组()、不捕获(?:)和断言(?<=)详解

    分组 分组在正则中用()表示,根据小菜理解,分组的作用有两个: 1.将某些规律看成是一组,然后进行组级别的重复,可以得到意想不到的效果. 2.分组之后,可以通过后向引用简化表达式(\1 或者$1). ...

  8. springmvc 注解总结

    1.@RequestMapping@RequestMappingRequestMapping是一个用来处理请求地址映射的注解(将请求映射到对应的控制器方法中),可用于类或方法上.用于类上,表示类中的所 ...

  9. [js/jquery]移动端手势拖动,放大,缩小预览图片

    摘要 有这样的需求需要在手机端预览图片的时候,实现图片的手势拖动,放大缩小功能.最终通过touch.js这个插件实现了效果. touch.js Touch.js是移动设备上的手势识别与事件库, 由百度 ...

  10. [c#]获取exchange中的图片

    摘要 在exchange 2007或者2010中获取的邮件内容为html标签格式,也就是一个页面.如果里面含有img标签,你会发现img标签的src属性为cid:xxxxxxxxxxxx的一串字符串, ...