仿照java的jdk动态代理实现go语言动态代理

通过学习java的jdk动态代理和Cglib动态代理,仿照jdk动态代理用go实现了一个简单的动态代理

结构型模式

代理模式

代理模式中分为静态代理和动态代理。静态代理需要在编译前就要写好,而动态代理需要在运行时通过反射来实现方法增强。

静态代理:

  1. 代理类实现和目标类相同的接口,每个类都单独编辑一个代理类。
  2. 我们需要在代理类中,将目标类中的所有方法都要重新实现,并且为每个方法都附加相似的代码逻辑。
  3. 如果要添加方法增强的类不止一个,我们需要对每个类都创建一个代理类。

动态代理:

  1. 不需要为每个目标类编辑代理类。
  2. 在程序运行时,系统会动态地创建代理类,然后用代理类替换掉原始类。
  3. 一般采用反射实现。

代理模式的优点:

  1. 代理模式能将代理对象与真实被调用目标对象分离。
  2. 在一定程度上降低了系统的耦合性,拓展性好。
  3. 可以起到保护目标对象的作用。
  4. 可以增强目标对象的功能。

动态代理实现

package proimport ("errors""fmt""reflect"
)//提供动态调用方法接口
type InvocationHandler interface {Invoke(proxy *Proxy, method *Method, args []interface{}) ([]interface{}, error)
}//代理,用来总管代理类的生成
type Proxy struct {target  interface{}        //目标类,后面的类型和java的Object一样methods map[string]*Method //map用来装载待增强的不同的方法handle  InvocationHandler  //用来暴露统一invoke接口,类似多态
}//创建新的代理
func NewProxy(target interface{}, h InvocationHandler) *Proxy {typ := reflect.TypeOf(target)          //用来显示目标类动态的真实类型value := reflect.ValueOf(target)       //获取目标类的值methods := make(map[string]*Method, 0) //初始化目标类的方法map//将目标类的方法逐个装载for i := 0; i < value.NumMethod(); i++ {method := value.Method(i)methods[typ.Method(i).Name] = &Method{value: method}}return &Proxy{target: target, methods: methods, handle: h}
}//代理调用代理方法
func (p *Proxy) InvokeMethod(name string, args ...interface{}) ([]interface{}, error) {return p.handle.Invoke(p, p.methods[name], args)
}//用来承载目标类的方法定位和调用
type Method struct {value reflect.Value //用来装载方法实例
}//这里相当于调用原方法,在该方法外可以做方法增强,需要调用者自己实现!!!
func (m *Method) Invoke(args ...interface{}) (res []interface{}, err error) {defer func() {//用来捕捉异常if p := recover(); p != nil {err = errors.New(fmt.Sprintf("%s", p))}}()//处理参数params := make([]reflect.Value, 0)if args != nil {for i := 0; i < len(args); i++ {params = append(params, reflect.ValueOf(args[i]))}}//调用方法call := m.value.Call(params)//接收返回值res = make([]interface{}, 0)if call != nil && len(call) > 0 {for i := 0; i < len(call); i++ {res = append(res, call[i].Interface())}}return
}

测试

package proimport ("fmt""testing""time"
)func TestName(t *testing.T) {//这里对活动时长做统计people := &People{}   //创建目标类h := new(PeopleProxy) //创建接口实现类proxy := NewProxy(people, h)//调用方法ret, err := proxy.InvokeMethod("Work", "敲代码", "学习")if err != nil {fmt.Println(err)}fmt.Println(ret)
}//目标类
type People struct {}func (p *People) Work(content string, next string) string {fmt.Println("活动内容是:" + content + ",接下来需要做:" + next)return "all right"
}//用户需要自己实现的增强内容,需要实现InvocationHandler接口
type PeopleProxy struct {}//在这里做方法增强
func (p *PeopleProxy) Invoke(proxy *Proxy, method *Method, args []interface{}) ([]interface{}, error) {start := time.Now()defer fmt.Printf("耗时:%v\n", time.Since(start))fmt.Println("before method")invoke, err := method.Invoke(args...)fmt.Println("after method")return invoke, err
}

输出

仿照java的jdk动态代理实现go语言动态代理相关推荐

  1. Java基础-JDK动态代理

    JDK的动态代理依靠接口实现  代理模式  代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等. ...

  2. 【java】JDK动态代理原理

    文章目录 1. 示例 2. 原理 3. 为什么必须要基于接口? 1. 示例 首先,定义一个接口: public interface Staff {void work(); } 然后,新增一个类并实现上 ...

  3. JDK动态代理和Cglib的动态代理

    2019独角兽企业重金招聘Python工程师标准>>> 最简单的是静态代理方法,即代理模式,这里就不多啰嗦了.. 重点说一下JDK的动态代理和Cglib的动态代理吧 先说JDK的,需 ...

  4. Java JDK代理、CGLIB、AspectJ代理分析比较

    前言 什么是代理,在Design patterns In java这个本书中是这样描述的,简单的说就是为某个对象提供一个代理,以控制对这个对象的访问.在不修改源代码的基础上做方法增强,代理是一种设计模 ...

  5. 利用代码分别实现jdk动态代理和cglib动态代理_面试之动态代理

    大家好!我是CSRobot,从今天开始,我将会发布一些技术文章,内容就是结合春招以来的面试所遇到的问题进行分享,首先会对知识点进行一个探讨和整理,在最后会给出一些面试题并作出解答,希望可以帮助到大家! ...

  6. Java中三种代理方式—— 静态代理与两种动态代理的实现机制

    个人博客请访问 http://www.x0100.top 1.代理模式 代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现 ...

  7. spring AOP原理分析:静态代理;JDK实现接口动态代理;Cglib继承父类代理;SpringAop的责任链模式调用

    普通静态代理 代理类和真实类都需要实现同一个接口 接口 package com.fchan.layui.represent.service; /*** 静态代理demo*/ public interf ...

  8. java动态代理_Java中的动态代理一

    方法newProxyInstance介绍 这篇开始学Java中的动态代理部分,刚开始,我们不去了解什么是动态代理相关的概念,除了动态代理,还有静态代理.我们学习动态代理直接从学习一个方法开始,这个方法 ...

  9. Java设计模式:(一)动态代理分析 (含静态代理)

    代理模式:为其他对象提供一种代理以控制某个对象的访问.用在:在某些情况下,一个客户不想或者不能直接访问另一个对象,而代理对象可以在客户端和目标对象之前起到中介的作用,代理对象还可以完成它附加的操作. ...

最新文章

  1. Dokku和Docker的完美配合
  2. gcc和g++是什么,有什么区别?
  3. 使用git命令行将某个指定文件回退到前几个版本
  4. Gradle Eclipse插件教程
  5. 原来 GitHub 网红是这么混出来的 如何以正确的姿势参与开源项目
  6. 表单标签<input>的介绍
  7. python判断闰年_python如何判断闰年
  8. xxl子任务_分布式任务调度平台XXL-JOB
  9. 音乐伴奏如何提取?不容错过的几款软件
  10. 阿里云培训-OSS(对象存储)
  11. 【NLP】5计数词向量底层代码编写和gensim word2vec库入门——斯坦福大学CS224n第一次课作业代码复现
  12. Java Jsp+Servlet+mysql实现的火车票查询预定系统(管理员/普通用户 功能:火车票查询、订票付款退票改签、火车票信息管理、线路管理、站点管理等)
  13. oracle 导出身份证号_ORACLE对身份证号码处理相关的SQL汇总
  14. iPhone开发实战 pdf电子书
  15. mysql 查询 一对多_Mybatis一对一、一对多、多对多查询。+MYSQL
  16. ace缓存扩展接口_Laravel框架中实现使用阿里云ACE缓存服务
  17. Android 项目更换头像(拍照和选择相册)
  18. 一个基于SpringBoot开发的RBAC系统,非常适合新手入门JavaWeb代码审计实战的系统,长文警告,要好好学习。
  19. 继电器是如何成为CPU的(2)
  20. 分布式光纤温度监测系统在通信机房大楼电缆竖井的应用

热门文章

  1. C++11 - std::chrono - 使用std::chrono::duration_cast进行时间转换
  2. linux系统可以写入光盘吗_基于linux的国产操作系统,是真国产吗?
  3. PTA帅到没朋友(Java语言)+测试点
  4. DDR扫盲—-关于Prefetch(预取)与Burst(突发)的深入讨论
  5. 如何利用快递单号查询全部的物流信息并导出
  6. 《三十而已》告诉我们:在职场,混得越好,小人越多
  7. cartographer保存地图
  8. SpringBoot的基本配置
  9. 硅晶片清洗-半导体制造过程中的一个基础和关键步骤
  10. 基于百度地图画出物流起始线路