一、代理模式

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

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

二、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. CharSequence与String的区别

    CharSequence与String都能用于定义字符串,但CharSequence的值是可读可写序列,而String的值是只读序列. 原文: http://blog.csdn.net/joy_zha ...

  2. Spring整合JPA时,为实体类添加@Entity注解时提示The type MultipartEntity is deprecated

    这个情况是由于导入错了Entity包所导致的. 按住Alt+T时,会有两个关于@Entity的提示 org.hibernate.annotations.Entity 和 javax.persisten ...

  3. maven 引入外部jar包

    方式1:dependency 本地jar包 <dependency> <groupId>com.hope.cloud</groupId> <!--自定义--& ...

  4. Logstash IIS日志采集

    Logstash IIS 日志采集,跟Linux上运行差不多,都需要java运行环境,装个jdk就好了,对于IIS日志暂时未处理X-forward-for,纠结怎么弄当中,貌似要装个插件,慢慢研究. ...

  5. P5038 [SCOI2012]奇怪的游戏 二分+网络流

    $ \color{#0066ff}{ 题目描述 }$ Blinker最近喜欢上一个奇怪的游戏. 这个游戏在一个 \(N \times M\) 的棋盘上玩,每个格子有一个数.每次\(Blinker\)会 ...

  6. c语言-汉诺塔递归调用

    #include<stdio.h> int main() { void hano_tower(int n,char one,char two,char three); int m=0; p ...

  7. js控制输入框只能输入数字不能输入其他字符

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. Django上传文件的那些参数

    # ################## 默认文件上传配置 ######################## from django.core.files.uploadhandler import M ...

  9. MUI 滚动插件使用

    在Vue中 使用MUI滚动插件 官方文档地址:http://dev.dcloud.net.cn/mui/ui/#scroll 示例:初始化scroll控件: mui('.mui-scroll-wrap ...

  10. [Alpha]Scrum Meeting#3

    github 本次会议项目由PM召开,时间为4月3日晚上10点30分 时长15分钟 任务表格 人员 昨日工作 下一步工作 木鬼 撰写团队贡献分配计划(issue#39) 调整&分配工作 SiM ...