Java Proxy動態代理
Spring主要有兩大思想,一個是IoC,另一個就是AOP.而AOP的原理就是java的動態代理機制.
二:概念
動態代理其實就是java.lang.reflect.Proxy類動態的根據您指定的所有介面生成一個class BYTE,該class會繼承Proxy類,並實現所有你指定的介面(您在引數中傳入的介面陣列);然後再利用您指定的classloader將 class BYTE載入進系統,最後生成這樣一個類的物件,並初始化該物件的一些值,如invocationHandler,以即所有的介面對應的Method成員。 初始化之後將物件返回給呼叫的客戶端
三:解析
在java的動態代理機制中,有兩個重要的類或介面,一個是 InvocationHandler(Interface)、另一個則是 Proxy(Class),這一個類和介面是實現我們動態代理所必須用到的。
InvocationHandler:
每一個動態代理類都必須要實現InvocationHandler這個介面,並且每個代理類的例項都關聯到了一個Handler,當我們透過代理物件呼叫一個方法的時候,這個方法的呼叫就會被轉發為由InvocationHandler這個介面的 invoke 方法來進行呼叫。我們來看看InvocationHandler這個介面的唯一一個方法 invoke 方法:
Object invoke(Object proxy, Method method, Object[] args) throws Throwable
我們看到這個方法一共接受三個引數,那麼這三個引數分別代表什麼呢?
proxy: 指代我們所代理的那個真實物件
method: 指代的是我們所要呼叫真實物件的某個方法的Method物件
args: 指代的是呼叫真實物件某個方法時接受的引數
Proxy:
Proxy這個類的作用就是用來動態建立一個代理物件的類,它提供了許多的方法,但是我們用的最多的就是 newProxyInstance 這個方法:
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
這個方法的作用就是得到一個動態的代理物件,其接收三個引數,我們來看看這三個引數所代表的含義:
loader: 一個ClassLoader物件,定義了由哪個ClassLoader物件來對生成的代理物件進行載入
interfaces: 一個Interface物件的陣列,表示的是我將要給我需要代理的物件提供一組什麼介面,如果我提供了一組介面給它,那麼這個代理物件就宣稱實現了該介面(多型),這樣我就能呼叫這組介面中的方法了
h: 一個InvocationHandler物件,表示的是當我這個動態代理物件在呼叫方法的時候,會關聯到哪一個InvocationHandler物件上
四:案例
業務介面:
點選(此處)摺疊或開啟
-
public interface BusinessProcessor {
-
public void processBusiness();
- }
點選(此處)摺疊或開啟
-
public class BusinessProcessorImpl implements BusinessProcessor{
-
-
/* (non-Javadoc)
-
* @see com.enjoylink.gmap.mongodb.demo.BusinessProcessor#processBusiness()
-
*/
-
@Override
-
public void processBusiness() {
-
-
System.out.println("===========處理業務============");
-
}
-
- }
點選(此處)摺疊或開啟
-
public class BusinessProcessorHandler implements InvocationHandler {
-
-
private Object target = null;
-
-
BusinessProcessorHandler(Object target) {
-
this.target = target;
-
}
-
-
/*
-
* (non-Javadoc)
-
*
-
* @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object,
-
* java.lang.reflect.Method, java.lang.Object[])
-
*/
-
@Override
-
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
-
-
System.out.println("=========業務處理------前的操作=========");
-
Object result=method.invoke(target, args);
-
System.out.println("=========業務處理------後的操作=========");
-
return result;
-
}
-
- }
點選(此處)摺疊或開啟
-
public class BusinessProcessorTest {
-
-
public static void main(String[] args) {
-
BusinessProcessorImpl bpImpl = new BusinessProcessorImpl();
-
BusinessProcessorHandler handler = new BusinessProcessorHandler(bpImpl);
-
-
BusinessProcessor bp = (BusinessProcessor) Proxy.newProxyInstance(bpImpl.getClass().getClassLoader(),
-
bpImpl.getClass().getInterfaces(), handler);
-
-
bp.processBusiness();
-
System.out.println(bp.getClass().getName());
-
-
Class clz = bp.getClass();
-
printClassDefinition(clz);
-
-
}
-
-
public static String getModifier(int modifier) {
-
String result = "";
-
switch (modifier) {
-
case Modifier.PRIVATE:
-
result = "private";
-
case Modifier.PUBLIC:
-
result = "public";
-
case Modifier.PROTECTED:
-
result = "protected";
-
case Modifier.ABSTRACT:
-
result = "abstract";
-
case Modifier.FINAL:
-
result = "final";
-
case Modifier.NATIVE:
-
result = "native";
-
case Modifier.STATIC:
-
result = "static";
-
case Modifier.SYNCHRONIZED:
-
result = "synchronized";
-
case Modifier.STRICT:
-
result = "strict";
-
case Modifier.TRANSIENT:
-
result = "transient";
-
case Modifier.VOLATILE:
-
result = "volatile";
-
case Modifier.INTERFACE:
-
result = "interface";
-
}
-
return result;
-
}
-
-
public static void printClassDefinition(Class clz) {
-
-
String clzModifier = getModifier(clz.getModifiers());
-
if (clzModifier != null && !clzModifier.equals("")) {
-
clzModifier = clzModifier + " ";
-
}
-
String superClz = clz.getSuperclass().getName();
-
if (superClz != null && !superClz.equals("")) {
-
superClz = "extends " + superClz;
-
}
-
-
Class[] interfaces = clz.getInterfaces();
-
-
String inters = "";
-
for (int i = 0; i < interfaces.length; i++) {
-
if (i == 0) {
-
inters += "implements ";
-
}
-
inters += interfaces[i].getName();
-
}
-
-
System.out.println(clzModifier + clz.getName() + " " + superClz + " " + inters);
-
System.out.println("{");
-
-
Field[] fields = clz.getDeclaredFields();
-
for (int i = 0; i < fields.length; i++) {
-
String modifier = getModifier(fields[i].getModifiers());
-
if (modifier != null && !modifier.equals("")) {
-
modifier = modifier + " ";
-
}
-
String fieldName = fields[i].getName();
-
String fieldType = fields[i].getType().getName();
-
System.out.println(" " + modifier + fieldType + " " + fieldName + ";");
-
}
-
-
System.out.println();
-
-
Method[] methods = clz.getDeclaredMethods();
-
for (int i = 0; i < methods.length; i++) {
-
Method method = methods[i];
-
-
String modifier = getModifier(method.getModifiers());
-
if (modifier != null && !modifier.equals("")) {
-
modifier = modifier + " ";
-
}
-
-
String methodName = method.getName();
-
-
Class returnClz = method.getReturnType();
-
String retrunType = returnClz.getName();
-
-
Class[] clzs = method.getParameterTypes();
-
String paraList = "(";
-
for (int j = 0; j < clzs.length; j++) {
-
paraList += clzs[j].getName();
-
if (j != clzs.length - 1) {
-
paraList += ", ";
-
}
-
}
-
paraList += ")";
-
-
clzs = method.getExceptionTypes();
-
String exceptions = "";
-
for (int j = 0; j < clzs.length; j++) {
-
if (j == 0) {
-
exceptions += "throws ";
-
}
-
-
exceptions += clzs[j].getName();
-
-
if (j != clzs.length - 1) {
-
exceptions += ", ";
-
}
-
}
-
-
exceptions += ";";
-
-
String methodPrototype = modifier + retrunType + " " + methodName + paraList + exceptions;
-
-
System.out.println(" " + methodPrototype);
-
-
}
-
System.out.println("}");
-
}
-
- }
點選(此處)摺疊或開啟
-
=========業務處理------前的操作=========
-
===========處理業務============
-
=========業務處理------後的操作=========
-
com.sun.proxy.$Proxy0
-
com.sun.proxy.$Proxy0 extends java.lang.reflect.Proxy implements com.enjoylink.gmap.mongodb.demo.BusinessProcessor
-
{
-
java.lang.reflect.Method m1;
-
java.lang.reflect.Method m2;
-
java.lang.reflect.Method m3;
-
java.lang.reflect.Method m0;
-
-
boolean equals(java.lang.Object);
-
java.lang.String toString();
-
int hashCode();
-
void processBusiness();
- }
Proxy.newProxyInstance方法會做如下幾件事:
1,根據傳入的第二個引數interfaces動態生成一個類,實現interfaces中的介面,該例中即BusinessProcessor介面的processBusiness方法。並且繼承了Proxy類,重寫了hashcode,toString,equals等三個方法。具體實現可參看 ProxyGenerator.generateProxyClass(...); 該例中生成了$Proxy0類
2,透過傳入的第一個引數classloder將剛生成的類載入到jvm中。即將$Proxy0類load
3,利用第三個引數,呼叫$Proxy0的$Proxy0(InvocationHandler)建構函式 建立$Proxy0的物件,並且用interfaces引數遍歷其所有介面的方法,並生成Method物件初始化物件的幾個Method成員變數
4,將$Proxy0的例項返回給客戶端。
我們再看客戶端怎麼調就清楚了。
1,客戶端拿到的是$Proxy0的例項物件,由於$Proxy0繼承了BusinessProcessor,因此轉化為BusinessProcessor沒任何問題。
BusinessProcessor bp = (BusinessProcessor)Proxy.newProxyInstance(....);
2,bp.processBusiness();
實際上呼叫的是$Proxy0.processBusiness();那麼$Proxy0.processBusiness()的實現就是透過InvocationHandler去呼叫invoke方法。
五:總結
代理模式最大的特點就是代理類和實際業務類實現同一個介面(或繼承同一父類),代理物件持有一個實際物件的引用,外部呼叫時操作的是代理物件,而在代理物件的內部實現中又會去呼叫實際物件的操作
Java動態代理其實內部也是透過Java反射機制來實現的,即已知的一個物件,然後在執行時動態呼叫其方法,這樣在呼叫前後作一些相應的處理.
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/28624388/viewspace-2129828/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Java進階 | Proxy動態代理機制詳解Java
- jdk proxy invocationhandler (jdk動態代理)JDK
- Java JDK Proxy和CGLib動態代理示例講解JavaJDKCGLib
- Java代理設計模式(Proxy)的四種具體實現:靜態代理和動態代理Java設計模式
- JAVA 靜態代理 & 動態代理Java
- java動態代理基本原理及proxy原始碼分析一Java原始碼
- Java代理(jdk靜態代理、動態代理和cglib動態代理)JavaJDKCGLib
- java動態代理——代理方法的假設和驗證及Proxy原始碼分析五Java原始碼
- java靜態代理和動態代理Java
- java動態代理Java
- 幾個動態代理Proxy工具效能比較
- Java提高班(六)反射和動態代理(JDK Proxy和Cglib)Java反射JDKCGLib
- 【JAVA】代理模式之Java動態代理Java模式
- 【Java基礎】代理 - ProxyJava
- java動態代理動態在哪裡?Java
- Java動態代理(AOP)Java
- java動態代理(1)Java
- java 的動態代理Java
- java動態代理原理Java
- 輕鬆理解 Java 靜態代理/動態代理Java
- Java中的靜態代理和動態代理Java
- Java動態程式設計---動態代理Java程式設計
- Java進階--Java動態代理Java
- 動態代理jdk的Proxy與spring的CGlibJDKSpringCGLib
- Java基礎系列-靜態代理和動態代理Java
- JAVA學習篇--靜態代理VS動態代理Java
- Java 動態代理newProxyInstanceJava
- 動態代理及java演示Java
- java動態代理如何使用Java
- java 反射和動態代理Java反射
- Java 動態代理深入解析Java
- Java Web之動態代理JavaWeb
- (轉)Java動態代理與CGLib代理JavaCGLib
- Java進階之 JDK動態代理與Cglib動態代理JavaJDKCGLib
- Java架構-Java JDK 動態代理Java架構JDK
- Java中的代理模式(Proxy Pattern)Java模式
- 讓我們打一場動態代理的官司–Java動態代理Java
- java | 什麼是動態代理?Java