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
- 方式1:
- 参数3:
invocationHandler
处理接口, 一般采用匿名内部类实现。
- 提供
invoke
方法,代理类的每一个方法执行时, 都将调用一次invoke
方法 Object invoke(Object obj,Method method,Object[] args)
- 参数1:
proxy
: 代理对象 - 参数2:
method
: 代理对象当前执行的方法的描述对象(反射)
- 获取方法名:
method.getName()
- 执行方法:
method.invoke(对象, 实际参数)
- 获取方法名:
- 参数3:
args
: 方法实际参数
- 参数1:
- 提供
使用步骤
- 创建 被增强对象【被代理对象】
- 创建 增强对象 【代理对象】
- 通过被代理对象获取类加载器
被代理对象.getClass().getClassLoader()
- 通过被代理对象获取其所有的接口
被代理对象.getClass().getInterfaces()
- 创建一个处理类 【专门用来增强方法】
- 通过被代理对象获取类加载器
PS:动态代理技术实现的是接口中方法的代理,如果接口中没有的方法,动态代理是没法增强的!
案例:编码问题动态代理解决
index.jsp
- 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
- 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
- 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.youkuaiyun.com/q547550831/article/details/52924724