一、代理模式

如图:由于某些原因我们希望对该实现类进行访问控制、功能增强等,那么加入一层代理层,用代理层来调用实现类是一个很好的方式来解决这个问题,我们可以在调用实现类功能前后进行校验或者加入一些功能来达到控制、增强等效果。

你可以将代理模式简单理解为:不直接面向实现类,而是面向代理类,通过代理类调用实现类这一中间过程达到控制和增强的目的。

二、JDK动态代理

JDK提供了动态的代理实例创建的方法,你会用到:

在java.lang.reflect包下:

1)InvocationHandler代理处理程序接口

2)Proxy代理创建类

你需要使用步骤如下:

1)创建接口

2)创建接口实现类

3)实现代理处理程序InvocationHandler

4)Proxy创建代理

1、创建接口

/**
* 接口
*/
interface Person {
void say();
}

2、创建接口实现类

/**
* 实现类
*/
class Lay implements Person { @Override
public void say() {
System.out.println("the weather is very nice");
} }

3、创建代理处理程序

/**
* 代理处理实现
*/
class InvokeHandlerImpl implements InvocationHandler { private Object subject; public InvokeHandlerImpl(Object subject) {
this.subject = subject;
} @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("前置处理");
Object result = method.invoke(subject, args);
System.out.println("后置处理");
return result;
} }

注意:

1)InvokeHanlderImpl(Object subject); 构造方法传入了需要被代理的实现类实例对象;

2)proxy是代理实例对象;

3)method是被调用的方法;

4)args是method的参数;

4、创建代理

public class ProxyTest {

    public static void main(String[] args) {
Person lay = new Lay();
Person person = (Person) Proxy.newProxyInstance(lay.getClass().getClassLoader(), lay.getClass().getInterfaces(), new InvokeHandlerImpl(lay));
person.say();
} }

注意:

1)Proxy.newProxyInstance(...)方法创建了lay实例对象的代理;

2)第一个参数是类加载器;

3)第二个参数是相应声明的接口;

4)第三个参数是之前的代理处理程序;

控制台打印如下:

前置处理
the weather is very nice
后置处理

上面这个示例展示了JDK动态代理如何使用的,那么我们可以回想一下Spring框架中AOP、拦截器、事务等是不是也是一样的处理逻辑呢?所以Spring其实利用代理来做了很多事情。

三、为什么JDK动态代理基于接口

在上面的示例中,我们可能会疑惑,为什么一定要写一个Person接口,为什么在创建代理的时候需要传入接口呢?

打开newProxyInstance(...)源码你会看到(省略了代码):

...
Class<?> cl = getProxyClass0(loader, intfs);
...
final Constructor<?> cons = cl.getConstructor(constructorParams);
...
return cons.newInstance(new Object[]{h});

getProxyClass0方法通过加载器和接口获取了一个新类,这个类是接口的的实现类,而后通过构造方法创建了一个实例对象,这个实例对象就是代理对象。

我们可以这么理解代理对象和实现类之间的关系:

所以,代理对象和实现类的对象是两个对象,因此你可以知道如果你把代理对象强转成实现类是会报错的,因而你需要向上转型为接口。

Java API 之 动态代理的更多相关文章

  1. 使用Java中的动态代理实现数据库连接池

    2002 年 12 月 05 日 作者通过使用JAVA中的动态代理实现数据库连接池,使使用者可以以普通的jdbc连接的使用习惯来使用连接池. 数据库连接池在编写应用服务是经常需要用到的模块,太过频繁的 ...

  2. Java 反射 设计模式 动态代理机制详解 [ 转载 ]

    Java 反射 设计模式 动态代理机制详解 [ 转载 ] @author 亦山 原文链接:http://blog.csdn.net/luanlouis/article/details/24589193 ...

  3. 杨晓峰-Java核心技术-6 动态代理 反射 MD

    目录 第6讲 | 动态代理是基于什么原理? 典型回答 考点分析 知识扩展 反射机制及其演进 动态代理 精选留言 Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAnd ...

  4. 深入分析Java反射(四)-动态代理

    动态代理的简介 Java动态代理机制的出现,使得Java开发人员不用手工编写代理类,只要简单地指定一组接口及委托类对象,便能动态地获得代理类.代理类会负责将所有的方法调用分派到委托对象上反射执行,在分 ...

  5. java 笔记(3) —— 动态代理,静态代理,cglib代理

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

  6. java中的动态代理机制

    java中的动态代理机制 在java的动态代理机制中,有两个重要的类或接口,一个是 InvocationHandler(Interface).另一个则是 Proxy(Class),这一个类和接口是实现 ...

  7. Java反射和动态代理

    Java反射 反射机制 RTTI 编译器在编译时打开和检查*.class文件 反射机制 运行时打开和检查*.class文件 Java反射常见的方法 java反射的应用 setAccessible(bo ...

  8. Java学习笔记--动态代理

    动态代理 1.JDK动态代理 JDK1.3之后,Java提供了动态代理的技术,允许开发者在运行期创建接口的代理实例.JDK的动态代理主要涉及到java.lang.reflect包中的两个类:Proxy ...

  9. 十分钟理解Java中的动态代理

    十分钟理解 Java 中的动态代理   一.概述 1. 什么是代理 我们大家都知道微商代理,简单地说就是代替厂家卖商品,厂家“委托”代理为其销售商品.关于微商代理,首先我们从他们那里买东西时通常不知道 ...

随机推荐

  1. dataframe初始化

  2. HDU6400-2018ACM暑假多校联合训练1004-Parentheses Matrix-构造

    Parentheses Matrix Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Oth ...

  3. Logstash使用grok解析IIS日志

    Logstash使用grok解析IIS日志 1. 安装配置 安装Logstash前请确认Elasticsearch已经安装正确,参见RedHat6.4安装Elasticsearch5.2.0. 下载链 ...

  4. myeclipse关于svn更新报错:OPTIONS of '/svn/Xxx': 403 Forbidden

    这个问题出现原因是其他人修改了我原本写作的代码位置,把两个类转移到了别的文件夹,我更新之后只显示除了他增加的文件夹而没有里面的类,同时爆出错误: 问题原因:svn版本号不匹配,即跳版本. 解决如下:r ...

  5. leetcode-137-Single Number II-第一种解法

    题目描述: Given an array of integers, every element appears three times except for one, which appears ex ...

  6. python简介和环境搭建

    简介: python 是一种解释型.面向对象编程语言   由 Guido van Rossum 于1989年底发明, 第一个公开发行版发行于1991年, 最初被设计用于编写自动化脚本(shell)  ...

  7. SyntaxError: Non-UTF-8 code starting with '\xb6' in file XX.py

    导致出错的根源就是编码问题. 解决方案是: 在程序最上面加上: # coding=gbk

  8. python高级(三)—— 字典和集合(泛映射类型)

    本文主要内容 可散列类型 泛映射类型 字典 (1)字典推导式 (2)处理不存在的键 (3)字典的变种 集合 映射的再讨论 python高级——目录 文中代码均放在github上:https://git ...

  9. netsh命令操作ipsec

    IPsec就是IP安全筛选,本可以在本地安全策略中的窗口上进行操作添加,那么netsh也可以支持命令行操作这部分的内容. 我们的示例是禁止IP地址为192.168.1.10访问财务部某机3389端口 ...

  10. JavaSwing概述

    GUI(Graphic User Interface)为程序提供图形界面,它最初的设计目的是构建一个通用的GUI,使其能在所有平台上运行.在Java1.0中基础类AWT(Abstract Window ...