Java动态代理

1.概念

代理:

有时我们并不想直接访问对象A,或者不能直接访问对象A。而是通过访问一个中间对象B,让中间对象B去访问A。这种方式就称为代理

这里的对象A所属的类就为委托类,或者被代理类。

对象B所属的类就是代理类。

使用代理访问的优点

1.隐藏了被代理类的实现代码。

2.解耦,不改变被代理类的代码的情况下做一些额外的处理。(强调的是不改变被代理类的代码)。

比如调用SP的时候总是要获取sp,最后还要commit()。或者数据库操作等。在增删改查的前后总有一些相同的冗余代码。

根据程序运行前代理类是否已经存在,可以把代理分成静态代理和动态代理

静态代理

代理类在成勋运行前就已经存在的代理方式称为静态代理。(由开发人员编写或者编译器生成代理类的方式都属于静态代理

静态代理实例:

//被代理的类
class TobeProxyed {
public void m1(); public void m2(); public void m3(); } //代理类
class Proxy() {
//被代理类的对象
public class TobeProxyed proxyed; public Proxy(TobeProxyed proxyed) {
this.proxyed = proxyed;
} //代理类直接调用被代理类的方法。并且屏蔽了被代理类的//m3方法
public void proxyMethod1() {
proxyed.m1();
} public void proxyMethod2() {
proxyed.m2();
} }

静态代理中代理类和被代理类经常继承同一个父类或者实现同一个接口。

动态代理

代理类在程序运行前不存在,运行时由程序动态生成的代理方式称为动态代理

静态代理没有什么意思。动态代理的方式更灵活多变也是更需要理解的代理方式。

Java提供了动态代理的实现。可以在运行时动态的生成代理类。这样做代理就有一个非常大的好处————可以方便对代理类的函数做统一或者特殊的处理。如记录所有函数执行时间,所有函数执行前添加验证判断,对某个特殊函数进行特殊操作。不用像静态代理那样修改所有的方法。用静态代理只需要改一处invoke方法。

动态代理的实例:

实现动态代理包括三步:

1.要有被代理类的实例

2.写一个实现InvocationHandler接口的类(这个类是连接代理类和被代理类的中间类必须实现的接口)

3.调用Proxy.newProxyInstance()方法创建代理类对象

现在加入我们想要实现统计某个类所有函数的执行时间。传统的静态代理方式是在类的每个函数前后调用统计方法。

假如有100个方法的话,就要把相同的代码写100次。这时候静态代理的方式就很麻烦。

此时如果使用动态代理的方式就会很简单。只需要写一遍统计代码就OK了。

动态代理实例:

被代理类和被代理类接口

//这是被代理类的接口
public interface ProxyedInterface {
public void proxyedM1(); public void proxyedM2(); public void proxyedM3(); } //这是被代理类
public class ProxyedClassImpl implements ProxyedInterface {
@Override
public void proxyedM1() {
System.out.println("proxyedM1 invoked");
} public void proxyedM2() {
System.out.println("proxyedM2 invoked");
} public void proxyedM3() {
System.out.println("proxyedM3 invoked");
}
}

中间类实现InvocationHandler接口

有了要被代理的类。下面写一个中间类实现InvocationHandler接口的invoke方法。

//中间代理类
public class MiddleProxyClass implements InvocationHandler { //被代理类的对象
private Object proxyedClassImpl
public MiddleProxyClass(Object proxyedClassImpl) {
this.proxyedClassImpl = proxyedClassImpl;
} //调用被代理累的相应方法都会到调用这个方法内,在这里可以在方
//法的前后做相应的处理,但是无法改变被代理类的方法的内部逻辑
@Override
public Object (Object proxy, Method method, Object[] args) throws Throwable {
long start = System.currentTimeMillis(); Object o = method.invoke(proxyedClassImpl, args)//调用被代理累proxyedClassImpl的指定方法
System.out.println(method.getName() + " cost time : " + (System.currentTimeMillis()-start))
return o;
}
}

通过 Proxy 类静态函数生成代理对象

public class Main {
public static void main(String[] args) {
// create proxy instance
MiddleProxyClass middleProxyClass = new MiddleProxyClass(new ProxyedClassImpl()); //在这里动态生成实际的代理类对象 proxyedInterface
ProxyedInterface proxyedInterface = (ProxyedInterface)(Proxy.newProxyInstance(ProxyedInterface.class.getClassLoader(), new Class[] {ProxyedInterface.class},
middleProxyClass)); // call method of proxy instance
proxyedInterface.proxyedM1();
System.out.println();
proxyedInterface.proxyedM2();
System.out.println();
proxyedInterface.proxyedM3();
}
}

每次调用Proxy.newProxyInstance生成的代理类对象的方法,都会调用到中间类对象middleProxyClass的invoke方法。而invoke方法实现中会调用被代理类的指定方法。

生成代理类的静态方法: Proxy.newProxyInstance(…)

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)

loader表示类加载器

interfaces表示委托类的接口,生成代理类时需要实现这些接口

h是InvocationHandler实现类对象,负责连接代理类和委托类的中间类

我们可以这样理解,如上的动态代理实现实际是双层的静态代理,开发者提供了委托类 B,程序动态生成了代理类 A。开发者还需要提供一个实现了InvocationHandler的子类 C,子类 C 连接代理类 A 和委托类 B,它是代理类 A 的委托类,委托类 B 的代理类。用户直接调用代理类 A 的对象,A 将调用转发给委托类 C,委托类 C 再将调用转发给它的委托类 B。

Java笔记--动态代理的更多相关文章

  1. 【设计模式】Java设计模式 - 动态代理

    [设计模式]Java设计模式 - 动态代理 不断学习才是王道 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 一个有梦有戏的人 @怒放吧德德 最近工作比较忙,没啥时间学习 目录 [设计模 ...

  2. java的动态代理机制详解

    在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的 ...

  3. java中动态代理实现机制

    前言: 代理模式是常用的java设计模式,它的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会存在关联关系 ...

  4. Java特性-动态代理

    代理在开发中无处不在: 我们完成一个接口开发A,接口下有很多个实现类,这些类有些共同要处理的部分,比如每一个类都定义了接口A中的方法getXX(String name).我现在想把每次调用某个实现类的 ...

  5. java --- 设计模式 --- 动态代理

    Java设计模式——动态代理 java提供了动态代理的对象,本文主要探究它的实现, 动态代理是AOP(面向切面编程, Aspect Oriented Programming)的基础实现方式, 动态代理 ...

  6. java的动态代理机制

    前几天看到java的动态代理机制,不知道是啥玩意,然后看了看.死活不知道 invoke(Object proxy, Method m, Object[] args)种的proxy是个什么东西,放在这里 ...

  7. java中动态代理

    一.在java中怎样实现动态代理 1.我们要有一个接口,还要有一个接口的实现类,而这个实现类呢就是我们要代理的对象 接口: package org.dynamicproxy.test; public ...

  8. Java的动态代理机制详解(转)

    在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的 ...

  9. (转)java的动态代理机制详解

    原文出自:http://www.cnblogs.com/xiaoluo501395377/p/3383130.html 在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一 ...

随机推荐

  1. Shell字符串截取处理文件路径

    在生信处理流程中,从最初的fastq文件,经过分析处理后,会生成一堆的后续文件,如何在流程中合理的命名呢? 通常在批处理模式中,我们会得到多个样本*.fastq(或*.fq.*.fastq.gz.*. ...

  2. LINQ中的陷阱--TakeWhile&SkipWhile

    在用TakeWhile,SkipWhile设置陷阱之前,我们先来看一看他们的兄弟Take和Skip: public static IEnumerable<T> Take<T>( ...

  3. Gulp的学习和使用

    Gulp是一种直观.自动化构建的工具. Gulp是基于Node和NPM,安装教程点这里. 什么是Gulp? Gulp使用了node.js的流控制系统,使其(Gulp)构建更快,因为它不需要将临时文件/ ...

  4. PHP中ob_start()函数的用法

    ob_start()函数用于打开缓冲区,比如header()函数之前如果就有输出,包括回车/空格/换行/都会有"Header had all ready send by"的错误,这 ...

  5. 【Qt官方例程学习笔记】Address Book Example(代理模型)

    地址簿示例展示了如何使用代理模型在单个模型的数据上显示不同的视图. 本例提供了一个地址簿,允许按字母顺序将联系人分组为9组:ABC.DEF.GHI.…,VW,…XYZ.这是通过在同一个模型上使用多个视 ...

  6. gitlab私服搭建

    1.什么是gitlab: gitlab 是一个用于仓库管理系统的开源项目,它以git为代码管理工具,因此代码可以管到它上边来.搭建私服gitlab可以方便我们有条不紊的管理我们的代码.闲话不说,上代码 ...

  7. Hadoop 对MapReduce的理解

    对MapReduce的理解 客户端启动一个作业 向JobTraker请求一个JobId 将资源文件复制到HDFS上,包括Jar文件,配置文件,输入划分信息等 接收作业后,进入作业队列,根据输入划分信息 ...

  8. java部分基础知识整理----百度脑图版

    近期发现,通过百度脑图可以很好的归纳总结和整理知识点,本着学习和复习的目的,梳理了一下java部分的知识点,不定期更新,若有不恰之处,请指正,谢谢! 脑图链接如下:java部分基础知识整理----百度 ...

  9. CacheManager 概述

    1. CacheManager 管理缓存,而缓存可以是基于内存的缓存,也可以是基于磁盘的缓存 2. CacheManager 需要通过 BlockMananger 来操作数据: 3. 当 Task 运 ...

  10. day01笔记

    linux基本命令的学习: 1.查看主机名 hostname 2.修改主机名 hostnamectl set-hostname s16ds 3.linux命令提示符 [root@s16ds ~]# # ...