Proxy是一种结构设计模型,主要解决对象直接访问带来的问题,代理又分为静态代理和动态代理(JDK代理、CGLIB代理。

静态代理:又程序创建的代理类,或者特定的工具类,在平时开发中经常用到这种代理模式,这种一般在程序运行前就已经生成对应的class文件;

动态代理:在程序运行时通过反射机制动态创建。

下面通过一个场景实现以下三种代理方式

  • 步骤一:定义商店接口(Subject)
  • 步骤二:个人店家运营(RealSubject)
  • 步骤三:平台运营(proxy)
  • 步骤四:个体消费(client)

几种代理方式都会用到Subject、RealSubject,现在这里定义

Store.java(Subject):定义两个接口operate(运营),business(交易)。

public interface Store {
/**
* 店铺运营
*/
public void operate(); /**
* 店铺交易
*/
public void business();
}

PersonStore.java(RealSubject) 单个用户运营

public class PersonStore implements Store {
@Override
public void operate() {
System.out.println("个人商店运营");
} @Override
public void business() {
System.out.println("个人商店交易");
}
}

静态代理

静态代理的实现比较简单,代理类通过实现与目标对象相同的接口,并在类中维护一个代理对象,这种场景用于个体商家比较少的情况,如果多的话代理类十分繁多、不易维护

创建静态代理类

ProxyStroe.java(proxy):在代理平台运营是收取管理费用100,这个代理类需要实现Store接口,并制定目标类target(PersonStore)。

public class ProxyStroe implements Store{

    private Store personStore = new PersonStore();

    @Override
public void operate() {
System.out.println("收取管理费用100元");
personStore.operate();
} @Override
public void business() {
personStore.business();
}
}

静态代理调用

StaticConsumer.java(client):通过创建ProxyStroe去代理PersonStore,并进行操作。

public class StaticConsumer {

    public static void main(String[] args) {
ProxyStroe store = new ProxyStroe();
store.operate();
store.business();
}
}

动态代理

JDK代理

动态代理类是通过接口实现的,利用拦截器(拦截器必须实现InvocationHanlder)加上反射机制生成一个实现代理接口的匿名类,

在调用具体方法前调用InvokeHandler来处理。

创建jdk代理类

JDKStoreHandler.java(proxy):通过实现InvocationHandler接口的invoke方法,在里面进行反射调用,newProxyInstanse通过目标对象创建真是对象。

public class JDKStoreHandler implements InvocationHandler {

    /**
* 目标对象
*/
private Object targetObject; @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if("operate".equals(method.getName())){
System.out.println("收取管理费用100元");
}
return method.invoke(targetObject, args);
} /**
*
* @param targetObject
* @return
*/
public Object newProxyInstanse(Object targetObject){
this.targetObject = targetObject;
return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),targetObject.getClass().getInterfaces(),this);
}
}

JDK代理对象调用

JDKDynamicConsumer.java(proxy):通过JDKStoreHandler的newProxyInstanse创建真实目标对象,并调用接口的方法

public class JDKDynamicConsumer {

    public static void main(String[] args) {
Store store = (Store)new JDKStoreHandler().newProxyInstanse(new PersonStore());
store.operate();
store.business();
}
}

CGLIB代理

cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。

创建cglib代理对象

CglibProxy.java(proxy):需要实现MethodInterceptor的intercept方法,并进行反射调用。通过createProxyObject创建真实对象,这里是根据目标对象直接生成对象。

public class CglibProxy implements MethodInterceptor{

    /**
* CGlib需要代理的目标对象
*/
private Object targetObject; public Object createProxyObject(Object targetObject){
this.targetObject = targetObject;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(targetObject.getClass());
enhancer.setCallback(this);
Object proxyObj = enhancer.create();
return proxyObj;
} @Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
if("operate".equals(method.getName())){
System.out.println("收取管理费用100元");
}
return method.invoke(targetObject, objects);
}
}

CGLib代理对象调用

CglibDynamicConsumer.java(client):通过CglibProxy的createProxyObject创建真实目标对象,对进行方法调用

public class CglibDynamicConsumer {

    public static void main(String[] args) {
Store store = (Store)new CglibProxy().createProxyObject(new PersonStore());
store.operate();
store.business();
}
}

源码已上传:https://github.com/itrickzhang/proxy-demo

Java代理设计模式(Proxy)的几种具体实现的更多相关文章

  1. Java代理设计模式(Proxy)的四种具体实现:静态代理和动态代理

    面试问题:Java里的代理设计模式(Proxy Design Pattern)一共有几种实现方式?这个题目很像孔乙己问"茴香豆的茴字有哪几种写法?" 所谓代理模式,是指客户端(Cl ...

  2. 巧用代理设计模式(Proxy Design Pattern)改善前端图片加载体验

    这篇文章介绍一种使用代理设计模式(Proxy Design Pattern)的方法来改善您的前端应用里图片加载的体验. 假设我们的应用里需要显示一张尺寸很大的图片,位于远端服务器.我们用一些前端框架的 ...

  3. java 代理设计模式

    首先代理(deleration)是什么,在日常生活中我们有很多这种的例子,比如你上个QQ,各种空间被什么代理刷屏,对的,代理不是生产产品的商家,也不是进购产品的卖家,他们只是帮别人卖东西,这就相当于一 ...

  4. Java代理类Proxy的用法

    代理(proxy) 利用代理可以在运行时创建一个实现了一组给定接口的新类.这种功能只有在编译时无法确定需要实现哪个接口时才有必要使用. 何时使用代理 假设有一个表示接口的Class对象(有可能只包含一 ...

  5. java 代理的三种实现方式

    Java 代理模式有如下几种实现方式: 1.静态代理. 2.JDK动态代理. 3.CGLIB动态代理. 示例,有一个打招呼的接口.分别有两个实现,说hello,和握手.代码如下. 接口: public ...

  6. Java基础-设计模式之-代理模式Proxy

    代理模式是对象的结构模式.代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用. 代理模式是常用的Java 设计模式,它的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理 ...

  7. Java设计模式—Proxy动态代理模式

    代理:设计模式 代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问.代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理. 图 1. 代 ...

  8. Java的三种代理模式(Proxy,CGLib)

    1.静态代理,这种不用说最不靠谱.每个类一个代理,代码量很大. 2.JDK代理.使用java.lang.reflect.Proxy进行代理,但是被代理的类必须要实现接口. 3.Cglib代理.不用实现 ...

  9. 《JAVA设计模式》之代理模式(Proxy)

    在阎宏博士的<JAVA与模式>一书中开头是这样描述代理(Proxy)模式的: 代理模式是对象的结构模式.代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用. 代理模式的结 ...

随机推荐

  1. Java内部类超详细总结(含代码示例)

    什么是内部类 什么是内部类? 顾名思义,就是将一个类的定义放在另一个类的内部. 概念很清楚,感觉很简单,其实关键在于这个内部类放置的位置,可以是一个类的作用域范围.一个方法的或是一个代码块的作用域范围 ...

  2. Apache 80端口可以访问,8080却不可访问

    RT, 记录一下,后面看是否有解决方案.

  3. python3学习-logging模块

    1.logging模块的使用非常简单,引入模块就可以使用. import logging logging.debug('This is debug message') logging.info('Th ...

  4. Simple Windows Service in C++

    本文是来自CodeProject中的一篇名为Simple Windows Service in C++的译文,原文地址为:https://www.codeproject.com/Articles/49 ...

  5. 5.MySQL数据库操作步骤

    第一步:登录到MySQL服务器 第二步:选择当前要操作的数据库 第三步:设置请求和返回数据的字符集 第四步:执行SQL语句 l 增加记录:INSERT INTO news(title,content) ...

  6. 帝国CMS(EmpireCMS) v7.5配置文件写入漏洞分析

    帝国CMS(EmpireCMS) v7.5配置文件写入漏洞分析 一.漏洞描述 该漏洞是由于安装程序时没有对用户的输入做严格过滤,导致用户输入的可控参数被写入配置文件,造成任意代码执行漏洞. 二.漏洞复 ...

  7. Windows Server 2008 R2服务器内存使用率过高,但与任务管理器中进程占用内存和不一致

    系统环境: Windows Server 2008 R2 + Sql Server 2008 R2   问题描述: Windows Server 2008 R2系统内存占用率过大,而在任务管理器中各进 ...

  8. shiro登录名的获取

    登录名的获取:通过的SecurityUtils的shiro import org.apache.shiro.SecurityUtils; //登录用户名 String loginAccount = S ...

  9. C#窗体--鼠标事件

    常见的鼠标事件: mouseclick,mousedown,mouseup,mousuenter,mouseleave.mousemove mouseDown按下鼠标事件: //鼠标按下后显示 pri ...

  10. mybatis 源码分析(六)StatementHandler 主体结构分析

    分析到这里的时候,mybatis 初始化.接口.事务.缓存等主要功能都已经讲完了,现在就还剩下 StatementHandler 这个真正干活的家伙没有分析了:所以接下来的博客内容主要和数据库的关系比 ...