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. ANNOVAR工具

    annovar软件组件介绍之一——table_annovar.pl(译) 对于初学者,使用ANNOVAr的最简单方法是使用table_annovar.pl程序,该程序采用输入突变文件(例如,VCF文件 ...

  2. surging+EFCore 服务实现入门

    准备工作 本篇文章基于上篇基础上进行的,请先了解此篇  surging+CentOS7+docker+rancher2.0 菜鸟部署运行笔记 开发环境  Visual Studio 2017 15.5 ...

  3. CSS 框模型概述

    在 CSS 中,width 和 height 指的是内容区域的宽度和高度. 增加内边距.边框和外边距不会影响内容区域的尺寸,但是会增加元素框的总尺寸. 假设框的每个边上有 10 个像素的外边距和 5 ...

  4. [poj 1837] Balance dp

    Description Gigel has a strange "balance" and he wants to poise it. Actually, the device i ...

  5. [Xcode 实际操作]四、常用控件-(7)UIStepper控件的使用

    目录:[Swift]Xcode实际操作 本文将演示步进控件的基本用法.步进控件常用于小范围数值的调整. 在项目导航区,打开视图控制器的代码文件[ViewController.swift] import ...

  6. openstack RPC通信

    openstack RPC通信 OpenStack 的主要组件有 Nova.Cinder.Neutron.Glance 等,分别负责云平台的计算.存储.网络资源管理.openstack 各组件之间是通 ...

  7. C#正则表达式快速入门

    作者将自己在学习正则表达式中的心得和笔记作了个总结性文章,希望对初学C#正则表达式的读者有帮助. [内容] 什么是正则表达式 涉及的基本的类 正则表达式基础知识 构建表达式基本方法 编写一个检验程序 ...

  8. 我的省选 Day -5

    Day -5 时间载着我们,一天又一天,呼啸而过. 已经记不清今天是Day 负几了,总之还有不到一个星期就要去参加选拔赛了. 写一下今晚做NOI2009的心路历程. T1题意有点绕,但很快看出是个二分 ...

  9. 高斯消元法的C++简单实现

    高斯消元法 首先,我们导入几个概念. 定义1: 一个矩阵称为阶梯形(行阶梯形),若它有以下三个性质: 1.每一非零行在每一零行之上: 2.某一行的先导元素所在的列位于前一行先导元素的后面: 3.某一行 ...

  10. Could not find iPhone X simulator

    Could not find iPhone X simulator Error: Could not find iPhone X simulator at resolve (/Users/zhouen ...