Java动态代理类使用

Java动态代理类位于Java.lang.reflect包下,一般主要涉及到以下两个类:

一、Interface InvocationHandler:该接口中仅定义了一个方法Object invoke(Object obj,Method method,Object[] args)。在实际使用时,第一个参数obj一般是指代理类,method是被代理的方法,args为该方法的参数数组。这个抽象方法在代理类中动态实现。

二、Proxy:该类即为动态代理类,其中主要包含以下内容:

Protected Proxy(InvocationHandler h):构造函数,用于给内部的h赋值。

static Class getProxyClass (ClassLoader loader,Class[] interfaces):获得一个代理类,其中loader是类装载器,interfaces是真实类所拥有的全部接口的数组。

static Object newProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler h):返回代理类的一个实例,返回后的代理类可以当作被代理类使用(可使用被代理类的在Subject接口中声明过的方法)。

所谓Dynamic Proxy是这样一种class:它是在运行时生成的class,在生成它时你必须提供一组interface给它,然后该class就宣称它实现了这些 interface。你当然可以把该class的实例当作这些interface中的任何一个来用。当然啦,这个Dynamic Proxy其实就是一个Proxy,它不会替你作实质性的工作,在生成它的实例时你必须提供一个handler,由它接管实际的工作。在使用动态代理类时,我们必须实现InvocationHandler接口.

代理机制及特点

通过实现 InvocationHandler 接口创建自己的调用处理器;

通过为 Proxy 类指定 ClassLoader 对象和一组 interface 来创建动态代理类;

通过反射机制获得动态代理类的构造函数,其唯一参数类型是调用处理器接口类型;

通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数被传入。

——参考《百度百科》

Proxy类

一般使用Proxy.newProxylnstance(ClassLoader loader,Class[] interfaces,InvocationHandler invocationHandler)来创建代理对象

  • 参数1: loader , 类加载器, 动态代理类运行时创建, 任何类都需要类加载器将其加载到内存。

    • 一般情况: 被代理类.class.getClassLoader()或者被代理类实例.getClass().getClassLoader()
  • 参数2: interfaces代理类需要实现的所有接口。 
    • 方式1: 被代理类实例.getClass().getInterfaces()

      • 注意: 只能获得自己接口, 不能获得父元素接口
    • 方式2: new Class[]{ 被代理类.class } 
      • 例如:jdbc驱动 –> DriverManager 获得接口 Connection
  • 参数3: invocationHandler处理接口, 一般采用匿名内部类实现。 
    • 提供invoke方法,代理类的每一个方法执行时, 都将调用一次invoke方法
    • Object invoke(Object obj,Method method,Object[] args) 
      • 参数1: proxy : 代理对象
      • 参数2: method: 代理对象当前执行的方法的描述对象(反射) 
        • 获取方法名: method.getName()
        • 执行方法: method.invoke(对象, 实际参数)
      • 参数3: args : 方法实际参数

使用步骤

  1. 创建 被增强对象【被代理对象】
  2. 创建 增强对象 【代理对象】 
    1. 通过被代理对象获取类加载器 
      被代理对象.getClass().getClassLoader()
    2. 通过被代理对象获取其所有的接口 
      被代理对象.getClass().getInterfaces()
    3. 创建一个处理类 【专门用来增强方法】

PS:动态代理技术实现的是接口中方法的代理,如果接口中没有的方法,动态代理是没法增强的!

案例:编码问题动态代理解决

index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html><head><meta charset="UTF-8"><title>首页</title></head><body><h1>get请求</h1><form action="${pageContext.request.contextPath}/EncodingServlet" method="get"><input type="text" name="username" /><br/><input type="submit" value="提交"/></form><br/><h1>post请求</h1><form action="${pageContext.request.contextPath}/EncodingServlet" method="post"><input type="text" name="username" /><br/><input type="submit" value="提交"/></form></body>
</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

EncodingFilter.java

package com.pc.web.filter;import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;import javax.servlet.Filter;
import javax.servlet.FilterChain;import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;/*** 编码过滤器,使用动态代理解决编码问题* * @author Switch* @data 2016年10月25日* @version V1.0*/
public class EncodingFilter implements Filter {public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {final HttpServletRequest req = (HttpServletRequest) request;HttpServletResponse res = (HttpServletResponse) response;// 处理POST乱码问题req.setCharacterEncoding("utf-8");// 处理GET乱码问题// 创建HttpServletRequest代理对象// 参数1:ClassLoader loader 该代理类的类加载器// 参数2:Class<?>[] interfaces 该代理类的接口// 参数3:InvocationHandler h 代理实例的调用处理程序 实现的接口HttpServletRequest reqProxyInstance = (HttpServletRequest) Proxy.newProxyInstance(req.getClass().getClassLoader(), req.getClass().getInterfaces(), new InvocationHandler() {// 参数1:Object proxy 代理实例// 参数2:Method method 某一方法// 参数3:Object[] args 参数列表@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 当当前方法是"getParameter"时,增强该方法if ("getParameter".equals(method.getName())) {// 反射获取"getParameter"方法的返回值String value = (String) method.invoke(req, args);// GET请求方式则处理乱码问题if ("GET".equalsIgnoreCase(req.getMethod())) {value = new String(value.getBytes("iso8859-1"), "utf-8");}// 返回该值return value;}// 返回其他方法的值,并没有进行处理(增强)return method.invoke(req, args);}});// 放行,使用动态代理对象chain.doFilter(reqProxyInstance, res);}public void init(FilterConfig fConfig) throws ServletException {}public void destroy() {}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73

EncodingServlet.java

package com.pc.web.servlet;import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;/*** 编码测试Servlet* * @author Switch* @data 2016年10月25日* @version V1.0*/
public class EncodingServlet extends HttpServlet {public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {response.setContentType("text/html;charset=utf-8");String username = request.getParameter("username");System.out.println(username);}public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {response.setContentType("text/html;charset=utf-8");String username = request.getParameter("username");System.out.println(username);}}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

PS:编码问题的装饰者解决:过滤器Filter

from: http://blog.csdn.net/q547550831/article/details/52924724

Java动态代理类使用相关推荐

  1. 初看Mybatis 源码 (二) Java动态代理类

    先抛出一个问题,用过Mybatis的都知道,我们只需要定义一个Dao的接口,在里面写上一些CRUD相关操作,然后配置一下sql映射文件,就可以达到调用接口中的方法,然后执行sql语句的效果,为什么呢? ...

  2. Java之动态代理类实现日志简单实例

    开心一笑 上课呢,同桌撕了一片纸放嘴里了咬了咬,又吐回了手里. 揉了揉,揉成个球状,然后又把这东西给放嘴里,咽下去了. 我问:你干嘛呢? 这二货幽幽地说:这两天有点感冒,捏个药丸吃. 视频教程 大家好 ...

  3. java动态代理上是否能再进行一层代理

    CGLIB动态代理类 import java.lang.reflect.Method;import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.p ...

  4. Java 动态代理机制分析及扩展--转

    http://www.ibm.com/developerworks/cn/java/j-lo-proxy1/#icomments http://www.ibm.com/developerworks/c ...

  5. Java 动态代理机制分析及扩展,第 1 部分

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

  6. Java 动态代理机制分析及扩展

    简介: 本文通过分析 Java 动态代理的机制和特点,解读动态代理类的源代码,并且模拟推演了动态代理类的可能实现,向读者阐述了一个完整的 Java 动态代理运作过程,希望能帮助读者加深对 Java 动 ...

  7. 【转】浅析动态代理类实现过程

    代理模式 代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问.在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用. 代理模式一般涉及到 ...

  8. java动态代理模式初解

    第一部分 1.代理模式的作用和定义: 为其他对象提供一种代理以控制对这个对象的访问.在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用.  2.代 ...

  9. Java动态代理实现(转载\整理)

    在深入解析MapReduce架构设计与实现原理一书中读到动态代理这个东东. 代理是一种常用的设计模式,其目的是为其他对象提供一种代理一控制对这个对象的访问.代理类负责为委托类进行预处理(如安全检查.权 ...

最新文章

  1. DB2更改数据文件路径
  2. 计算机硬件:内存条的基础知识笔记
  3. 《面向对象的思考过程(原书第4版)》一 导读
  4. 中国经济蓝皮书发布 该死的房价下降成定局
  5. 麒麟810怎么样_麒麟810+6G+128G+大电池,千元价格的手机上手体验
  6. MySQL心得1--数据库的基本概念
  7. Geodetector软件下载、地理探测器的应用实践与结果解读
  8. ps随机排列_[PS]圆点随机不重叠排列脚本
  9. Freeswitch的Proxy(代理转发)模式和Bypass(旁路)模式的正确配置
  10. 拼多多新店扶持期是多久?
  11. Hutool进行DES加解密
  12. Aria2 ,下载神器
  13. redis缓存穿透和缓存雪崩的浅析以及解决方案
  14. prometheus启动报错Unit prometheus.service entered failed state.
  15. 大数据——Redshift通过UDF函数实现金融业XIRR函数
  16. Windows 10下无法安装 CAD 2013/2014的解决方法
  17. ALS冰桶挑战案例详解
  18. 干选机的工作原理与维护
  19. (转)CSS3之pointer-events(屏蔽鼠标事件)属性说明
  20. 网页分段视频下载并将多个ts文件合并

热门文章

  1. redis的hash操作在集中式session中的应用
  2. MySQL——多表查询练习:电商数据查询
  3. 【数据工程】工具与思维结合,会爆发奇效
  4. 深度学习在推荐领域的应用
  5. Apache Kafka-通过concurrency实现并发消费
  6. Java学习笔记(七)--格式化字符串及格式输出
  7. Lock锁的基本使用
  8. python对象点方法_python对象方法、类方法、静态方法
  9. 银行java多线程例子_Java 多线程 之 银行ATM实例
  10. python内置排序算法_2021-01-05 排序算法(Python语言实现)