如要轉載請標明作者zjrodger和出處:http://blog.csdn.net/zjrodger/,謝謝。
筆記目錄
· 分析JVM動態生成的類
(·) 讓JVM先創建動態類,再創建其實例對象的一般方法:
1. 創建一個實現了Collection接口的動態代理類(並不創建其實例對象)。
2. 實現Collection接口,創建一個動態代理類,並且創建該動態類的對象。
(·) 讓JVM創建動態類及其實例對象的快速簡便方法
(·) 總結讓JVM創建動態代理類及其實例對象
(·) 分析InvocationHandler對象的運行原理和動態代理的運行原理
1. 猜想分析動態生成的類的內部代碼
2. 動態代理類的工作原理圖
3. 實際開發中的動態代理類的實現(重要)
|
package com.zjrodger.day3;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Collection;
import java.util.Properties;
/**
* 程序功能:
* 1. 通過實現某個接口,比如java.util.Collection,創建一個動態的代理類。
* 2. 該接口可以由config.properties配置文件指定。
* **/
public class ProxyTest{
private static String interfaceName = null;
//在靜態初始化塊兒中讀取配置文件config.properties中的類名。
static{
InputStream inStream = null;
Properties prop = new Properties();
try {
inStream = ProxyTest.class.getClassLoader().getResourceAsStream("com/zjrodger/day3/config.properties");
prop.load(inStream);
ProxyTest.interfaceName = prop.getProperty("keyName01");
} catch (IOException e) {
e.printStackTrace();
System.out.println("讀取配置文件config.properties失敗!!");
} finally{
try {
inStream.close();
} catch (IOException e) {
e.printStackTrace();
System.out.println("關閉配置文件config.properties失敗!!");
}
inStream = null;
}
}
public static void main(String[] args){
Class<?> clazzInterface = null;
try {
clazzInterface = Class.forName(ProxyTest.interfaceName);
} catch (ClassNotFoundException e) {
e.printStackTrace();
System.out.println("加載ProxyTest.interfaceName失敗!!");
}
System.out.println(clazzInterface.getName());
// 通過實現Collection接口,創建一個動態的代理類。
Class<?> clazzMyProxyName01 = Proxy.getProxyClass(clazzInterface.getClassLoader(), clazzInterface);
System.out.println("-----------------動態代理類的構造方法列表-------------");
//預期目標: $Proxy0(java.lang.reflect.InvocationHandler)
Constructor[] constructors = clazzMyProxyName01.getConstructors();
for(Constructor oneConstructor: constructors){
StringBuilder sBuilder = new StringBuilder(oneConstructor.getName()+'(');
Class[] parameterTyes = oneConstructor.getParameterTypes();
for(Class oneParamType: parameterTyes){
sBuilder.append(oneParamType.getName());
sBuilder.append(',');
}
if(parameterTyes != null && parameterTyes.length != 0){
sBuilder.deleteCharAt(sBuilder.length()-1);
}
sBuilder.append(')');
System.out.println(sBuilder.toString());
}
System.out.println("\n");
System.out.println("-----------------動態代理類的普通方法列表-------------");
Method[] methods = clazzMyProxyName01.getMethods();
for(Method oneMethod: methods){
StringBuilder sBuilder = new StringBuilder(oneMethod.getName()+'(');
Class[] parameterTyes = oneMethod.getParameterTypes();
for(Class oneParamType: parameterTyes){
sBuilder.append(oneParamType.getName());
sBuilder.append(',');
}
if(parameterTyes != null && parameterTyes.length != 0){
sBuilder.deleteCharAt(sBuilder.length()-1);
}
sBuilder.append(')');
System.out.println(sBuilder.toString());
}
}
}
【運行結果】
java.util.Collection
-----------------動態代理類的構造方法列表-------------
$Proxy0(java.lang.reflect.InvocationHandler)
-----------------動態代理類的普通方法列表-------------
add(java.lang.Object)
hashCode()
clear()
equals(java.lang.Object)
toString()
contains(java.lang.Object)
isEmpty()
addAll(java.util.Collection)
iterator()
size()
toArray([Ljava.lang.Object;)
toArray()
remove(java.lang.Object)
containsAll(java.util.Collection)
removeAll(java.util.Collection)
retainAll(java.util.Collection)
isProxyClass(java.lang.Class)
getProxyClass(java.lang.ClassLoader,[Ljava.lang.Class;)
getInvocationHandler(java.lang.Object)
newProxyInstance(java.lang.ClassLoader,[Ljava.lang.Class;,java.lang.reflect.InvocationHandler)
wait()
wait(long,int)
wait(long)
getClass()
notify()
notifyAll()
|
package com.zjrodger.day3;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Properties;
/**
* 程序功能:
* 1. 通過實現某個接口,比如java.util.Collection,創建一個動態的代理類。
* 2. 該接口可以由config.properties配置文件指定。
* **/
public class ProxyTest{
private static String interfaceName = null;
//在靜態初始化塊兒中讀取配置文件config.properties中的類名。
static{
InputStream inStream = null;
Properties prop = new Properties();
try {
inStream = ProxyTest.class.getClassLoader().getResourceAsStream("com/zjrodger/day3/config.properties");
prop.load(inStream);
ProxyTest.interfaceName = prop.getProperty("keyName01");
} catch (IOException e) {
e.printStackTrace();
System.out.println("讀取配置文件config.properties失敗!!");
} finally{
try {
inStream.close();
} catch (IOException e) {
e.printStackTrace();
System.out.println("關閉配置文件config.properties失敗!!");
}
inStream = null;
}
}
public static void main(String[] args){
Class<?> clazzInterface = null;
try {
clazzInterface = Class.forName(ProxyTest.interfaceName);
} catch (ClassNotFoundException e) {
e.printStackTrace();
System.out.println("加載ProxyTest.interfaceName失敗!!");
}
System.out.println(clazzInterface.getName());
// 通過實現Collection接口,創建一個動態的代理類。
Class<?> clazzMyProxyClassName01 = Proxy.getProxyClass(clazzInterface.getClassLoader(), clazzInterface);
/**
* 創建該動態代理類的實例對象。
* **/
try {
//方式一:創建一個內部類,該內部類實現了InvocationHandler接口。
class MyInvocationHandler implements InvocationHandler{
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
return null;
}
}
Constructor constructor = clazzMyProxyClassName01.getConstructor(InvocationHandler.class);
//創建動態代理類的實例對象。
Collection proxyInstance01 = (Collection)constructor.newInstance(new MyInvocationHandler());
System.out.println(proxyInstance01.toString());
proxyInstance01.clear();
//方式二:通過匿名內部類來創建動態代理類的實例對象。
Collection proxyInstance02 = (Collection)constructor.newInstance(new InvocationHandler(){
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return null;
}
});
System.out.println("The size is "+proxyInstance02.size());
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
Foo f = (Foo) Proxy.newProxyInstance( Foo.class.getClassLoader(),new Class[] { Foo.class },handler);
package com.zjrodger.day3;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Properties;
/**
* 程序功能:
* 1. 通過實現某個接口,比如java.util.Collection,創建一個動態的代理類。
* 2. 該接口可以由config.properties配置文件指定。
* **/
public class ProxyTest{
private static String interfaceName = null;
//在靜態初始化塊兒中讀取配置文件config.properties中的類名。
static{
InputStream inStream = null;
Properties prop = new Properties();
try {
inStream = ProxyTest.class.getClassLoader().getResourceAsStream("com/zjrodger/day3/config.properties");
prop.load(inStream);
ProxyTest.interfaceName = prop.getProperty("keyName01");
} catch (IOException e) {
e.printStackTrace();
System.out.println("讀取配置文件config.properties失敗!!");
} finally{
try {
inStream.close();
} catch (IOException e) {
e.printStackTrace();
System.out.println("關閉配置文件config.properties失敗!!");
}
inStream = null;
}
}
public static void main(String[] args){
Class<?> clazzInterface = null;
try {
clazzInterface = Class.forName(ProxyTest.interfaceName);
} catch (ClassNotFoundException e) {
e.printStackTrace();
System.out.println("加載ProxyTest.interfaceName失敗!!");
}
System.out.println(clazzInterface.getName());
// 通過實現Collection接口,創建一個動態的代理類。
Class<?> clazzMyProxyClassName01 = Proxy.getProxyClass(clazzInterface.getClassLoader(), clazzInterface);
/**
* 創建該動態代理類的實例對象。
* **/
try {
//方式三:讓JVM創建動態類及其實例對象的快速簡便方法。
Collection proxyInstance03 = (Collection) Proxy.newProxyInstance(
ProxyTest.class.getClassLoader(),
new Class[]{java.util.Collection.class},
new InvocationHandler(){
//定義一個目標類,注意區別它和Proxy代理類的關係;
//另外,目標類和Proxy代理類都實現了相同的接口。
ArrayList target = new ArrayList();
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
long beginTime = System.currentTimeMillis();
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
Object returnedValue = method.invoke(target, args);
long endTime = System.currentTimeMillis();
System.out.println("代理類實例的代理方法"+method.getName()+"()執行的時間跨度爲: "+(endTime - beginTime));
return returnedValue;
}
}
);
proxyInstance03.add("zjrodger01");
proxyInstance03.add("Coffee");
proxyInstance03.add("Zhuxinyue");
System.out.println("The size is "+proxyInstance03.size());
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
Class Proxy${
add(Object object){
return handler.invoke(Object proxy, Method method, Object[] args);
}
}
package com.zjrodger.aopframework02;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class DynamicProxy {
/**
* 1.根據傳入的targe對象和advice對象,生成相應的Proxy對象。
* 2.代碼改造:
* 也可以將targe對象和advice對象定義爲DynamicProxy類的靜態類屬性,這樣,在創建Proxy對象之前,
* 可以通過靜態的setter()和getter()方法設置target對象和advice對象,這樣,
* 當調用myNewProxyInstance()方法時,就不用將target對象和advice對象作爲參數傳入到方法中了。
* **/
public static Object myNewProxyInstance(final Object target, final Advice advice){
Object oneProxyInstance = Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler(){
public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable {
advice.beforeMethod(); //系統輔助功能的切面代碼01
//核心業務代碼
Object returnedValue = method.invoke(target, args);
System.out.println("核心方法\""+method.getName()+"()\"執行完畢,其返回值:"+returnedValue);
Thread.sleep(1500);
advice.afterMethod(); //系統輔助功能的切面代碼02
return returnedValue;
}
}
);
return oneProxyInstance;
}
}
②Advice接口
package com.zjrodger.aopframework02;
public interface Advice {
public void beforeMethod();
public void afterMethod();
}
③Advice接口的實現類MyAdvice類
package com.zjrodger.aopframework02;
import java.text.DateFormat;
import java.util.Date;
public class MyAdvice implements Advice {
private DateFormat df = DateFormat.getTimeInstance(DateFormat.MEDIUM);
public void afterMethod() {
System.out.println("執行核心代碼之後,執行切面代碼02,時間爲:"+df.format(new Date()));
System.out.println("\n");
}
public void beforeMethod() {
System.out.println("執行核心代碼之前,執行切面代碼01,時間爲:"+df.format(new Date()));
}
}
④程序啓動入口類
package com.zjrodger.aopframework02;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class DynamicProxyTestLauncher {
public static void main(String[] args) {
//定義一個taget類
ArrayList target = new ArrayList();
//定義一個advice類
MyAdvice advice = new MyAdvice();
//生成動態代理對象。
Collection proxyObj = (Collection)DynamicProxy.myNewProxyInstance(target,advice);
//調用新創建動態代理對象的方法。
proxyObj.add("zjrodger");
proxyObj.add("Lilin");
System.out.println("Proxy對象的size屬性爲: "+proxyObj.size());
//遍歷新建的Proxy對象中存放的元素。
for(Iterator it = proxyObj.iterator(); it.hasNext();){
System.out.println(it.next());
}
}
}
【結果演示】
執行核心代碼之前,執行切面代碼01,時間爲:14:37:59 核心方法"add()"執行完畢,其返回值:true 執行核心代碼之後,執行切面代碼02,時間爲:14:38:00 執行核心代碼之前,執行切面代碼01,時間爲:14:38:00 核心方法"add()"執行完畢,其返回值:true 執行核心代碼之後,執行切面代碼02,時間爲:14:38:02 執行核心代碼之前,執行切面代碼01,時間爲:14:38:02 核心方法"size()"執行完畢,其返回值:2 執行核心代碼之後,執行切面代碼02,時間爲:14:38:03 Proxy對象的size屬性爲: 2 執行核心代碼之前,執行切面代碼01,時間爲:14:38:03 核心方法"iterator()"執行完畢,其返回值:java.util.AbstractList$Itr@1dff3a2 執行核心代碼之後,執行切面代碼02,時間爲:14:38:05 zjrodger Lilin |