Java动态代理类使用
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:?被代理類實例.getClass().getInterfaces()?
- 參數3:?invocationHandler處理接口, 一般采用匿名內部類實現。?
- 提供invoke方法,代理類的每一個方法執行時, 都將調用一次invoke方法
- Object invoke(Object obj,Method method,Object[] args)?
- 參數1:?proxy?: 代理對象
- 參數2:?method: 代理對象當前執行的方法的描述對象(反射)?
- 獲取方法名:?method.getName()
- 執行方法:?method.invoke(對象, 實際參數)
- 參數3:?args?: 方法實際參數
使用步驟
被代理對象.getClass().getClassLoader()
被代理對象.getClass().getInterfaces()
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
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的Java动态代理类使用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Tomcat容器入门介绍
- 下一篇: BeanUtils入门