java 反射和動態(tài)代理詳解及實例代碼
更新時間:2016年09月30日 14:19:18 作者:夏中偉
這篇文章主要介紹了java 反射和動態(tài)代理詳解及實例代碼的相關資料,需要的朋友可以參考下
一、java中的反射
1.通過反射加載類的屬性和方法實例代碼:
/**
* java.lang.Class 是反射的源頭
* 我們創(chuàng)建了一個類,通過編譯(javac.exe)生成對應的class文件,之后我們通過java.exe加載(jvm的類加載器加載)此class文件
* 此class文件加載到內存后,就是一個運行時類,存在緩存區(qū),這個運行時類本事就是一個Class的實例
* 每一個運行時類只加載一次,
*/
Class<StudentExam> clazz = StudentExam.class;
StudentExam studentExam = clazz.newInstance();
System.err.println(studentExam);
System.out.println(clazz);
// Field field = clazz.getField("id"); // 通過屬性調用運行時類的指定屬性:屬性是public類型
Field field = clazz.getDeclaredField("id"); // 屬性是非public 類型
Field[] fields = clazz.getDeclaredFields(); // 獲取運行時類本身(父類不行)所有聲明的屬性,父類使用clazz.getFields();
for (Field field2 : fields) {
int i = field2.getModifiers();
String type = Modifier.toString(i);// 獲取字段屬性的數據類型
System.out.println(type);
}
field.setAccessible(true);
field.set(studentExam, 11);
System.err.println(studentExam.getId());
// 通過反射調用運行時類的指定方法
Method method = clazz.getMethod("setId", Integer.class);
method.invoke(studentExam, 123); // 調用運行時類的指定方法
Method[] methods = clazz.getMethods(); // 獲取所有運行時類及其父類中所有聲明為public的方法
Method[] methods2 = clazz.getDeclaredMethods();// 獲取運行時類本身類中聲明的方法
for (Method method2 : methods) {
System.out.println(method2.getName());
}
// * 通過對象的getClass()方法獲取對象的運行時類,
Exam exam = new Exam();
Class clazzExam = exam.getClass();
2.類加載器ClassLoader
/**
* Description:類加載器,加載xx.properties文件,并讀取數據
* @param
* @author xiazhongwei
* @data 2016年9月29日:下午5:32:56
* @return
*/
public void classLoader() throws IOException {
//方法一、從當前工程下加載
ClassLoader loader = this.getClass().getClassLoader();
// 路徑是包下寫:com\\able\\onlineExam\\resources\\config.properties
InputStream inStream = loader.getResourceAsStream("config.properties");
// 方法二、從指定的路徑下加載文件
// FileInputStream fileInputStream = new FileInputStream(new File("config.properties"));
Properties properties = new Properties();
properties.load(inStream);
// properties.load(fileInputStream);
String prop = properties.getProperty("domain");
System.out.println(prop);
}
3.動態(tài)代理
靜態(tài)代理:代理類和目標對象的類型都是在編譯期間確定下來,不利于程序的擴展。同時每個代理類只能為一個接口服務,這樣一來程序開發(fā)中必然產生過多的代理。
動態(tài)代理:客戶通過代理類來調用其他對象的方法,并且是在程序運行時,根據需要動態(tài)創(chuàng)建目標類的代理對象。
代理設計模式的原理:
使用一個代理將對象包裝起來,然后用該代理對象取代原始對象,任何對原始對象的調用都要通過代理,代理對象決定的那個是否以及何時將方法調用
package com.test.junit;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyTest {
public static void main(String[] args) {
RealSubject realSubject = new RealSubject();
MyInvocationHandler myInvocationHandler = new MyInvocationHandler();
Object object = myInvocationHandler.bind(realSubject);
Subject subject = (Subject) object;
subject.action();
}
}
// 動態(tài)代理的使用
interface Subject{
void action();
}
// 被代理類
class RealSubject implements Subject{
@Override
public void action() {
System.out.println("我是被代理類,記得執(zhí)行我哦。。。。");
}
}
class MyInvocationHandler implements InvocationHandler{
Object object;// 實現了接口的被代理類的對象的聲明
/**
* Description:①給被代理的對象實例化 ②返回一個代理類對象
* @param
* @author xiazhongwei
* @data 2016年9月29日:下午4:13:43
* @return
*/
public Object bind(Object object){
this.object = object;
return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), this);
}
/**
* 當通過代理類的對象發(fā)起對被重寫的方法的調用時,都會轉化為對如下的invok方法的調用
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object returnObject = method.invoke(object, args);
return returnObject;
}
}
4.動態(tài)代理與AOP
示例一、
package com.atguigu.spring.aop;
public interface ArithmeticCalculator {
int add(int i, int j);
int sub(int i, int j);
int mul(int i, int j);
int div(int i, int j);
}
package com.atguigu.spring.aop;
import org.springframework.stereotype.Component;
@Component("arithmeticCalculator")
public class ArithmeticCalculatorImpl implements ArithmeticCalculator {
@Override
public int add(int i, int j) {
int result = i + j;
return result;
}
@Override
public int sub(int i, int j) {
int result = i - j;
return result;
}
@Override
public int mul(int i, int j) {
int result = i * j;
return result;
}
@Override
public int div(int i, int j) {
int result = i / j;
return result;
}
}
package com.atguigu.spring.aop;
public class ArithmeticCalculatorLoggingImpl implements ArithmeticCalculator {
@Override
public int add(int i, int j) {
System.out.println("The method add begins with [" + i + "," + j + "]");
int result = i + j;
System.out.println("The method add ends with " + result);
return result;
}
@Override
public int sub(int i, int j) {
System.out.println("The method sub begins with [" + i + "," + j + "]");
int result = i - j;
System.out.println("The method sub ends with " + result);
return result;
}
@Override
public int mul(int i, int j) {
System.out.println("The method mul begins with [" + i + "," + j + "]");
int result = i * j;
System.out.println("The method mul ends with " + result);
return result;
}
@Override
public int div(int i, int j) {
System.out.println("The method div begins with [" + i + "," + j + "]");
int result = i / j;
System.out.println("The method div ends with " + result);
return result;
}
}
package com.atguigu.spring.aop;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
public class ArithmeticCalculatorLoggingProxy {
//要代理的對象
private ArithmeticCalculator target;
public ArithmeticCalculatorLoggingProxy(ArithmeticCalculator target) {
super();
this.target = target;
}
//返回代理對象
public ArithmeticCalculator getLoggingProxy(){
ArithmeticCalculator proxy = null;
// 代理對象有哪一個類加載器負責加載
ClassLoader loader = target.getClass().getClassLoader();
// 代理對象的類型,即其中有哪些方法
Class [] interfaces = new Class[]{ArithmeticCalculator.class};
// 當調用代理對象的其中方法時,執(zhí)行下面的代碼
InvocationHandler h = new InvocationHandler() {
/**
* proxy: 代理對象。 一般不使用該對象
* method: 正在被調用的方法
* args: 調用方法傳入的參數
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// 在方法內部不會直接調用proxy對象的某個方法,proxy.toString()會造成死循環(huán)調用invoke方法
String methodName = method.getName();
//打印日志
System.out.println("[before] The method " + methodName + " begins with " + Arrays.asList(args));
//調用目標方法
Object result = null;
try {
//前置通知
result = method.invoke(target, args);
//返回通知, 可以訪問到方法的返回值
} catch (NullPointerException e) {
e.printStackTrace();
//異常通知, 可以訪問到方法出現的異常
}
//后置通知. 因為方法可以能會出異常, 所以訪問不到方法的返回值
//打印日志
System.out.println("[after] The method ends with " + result);
return result;
}
};
/**
* loader: 代理對象使用的類加載器。
* interfaces: 指定代理對象的類型. 即代理代理對象中可以有哪些方法.
* h: 當具體調用代理對象的方法時, 應該如何進行響應, 實際上就是調用 InvocationHandler 的 invoke 方法
*/
proxy = (ArithmeticCalculator) Proxy.newProxyInstance(loader, interfaces, h);
return proxy;
}
}
package com.atguigu.spring.aop;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
// ArithmeticCalculator arithmeticCalculator = new ArithmeticCalculatorImpl();
ArithmeticCalculator arithmeticCalculator = new ArithmeticCalculatorLoggingImpl();
arithmeticCalculator = new ArithmeticCalculatorLoggingProxy(arithmeticCalculator).getLoggingProxy();
int result = arithmeticCalculator.add(11, 12);
System.out.println("result:" + result);
result = arithmeticCalculator.div(21, 3);
System.out.println("result:" + result);
}
}
示例二、
package com.test.junit;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyTest {
public static void main(String[] args) {
RealSubject realSubject = new RealSubject();
MyInvocationHandler myInvocationHandler = new MyInvocationHandler();
Object object = myInvocationHandler.bind(realSubject);
Subject subject = (Subject) object;
subject.action();
}
}
// 動態(tài)代理的使用
interface Subject{
void action();
}
// 被代理類
class RealSubject implements Subject{
@Override
public void action() {
System.out.println("我是被代理類,記得執(zhí)行我哦。。。。");
}
}
class MyInvocationHandler implements InvocationHandler{
Object object;// 實現了接口的被代理類的對象的聲明
/**
* Description:①給被代理的對象實例化 ②返回一個代理類對象
* @param
* @author xiazhongwei
* @data 2016年9月29日:下午4:13:43
* @return
*/
public Object bind(Object object){
this.object = object;
return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), this);
}
/**
* 當通過代理類的對象發(fā)起對被重寫的方法的調用時,都會轉化為對如下的invok方法的調用
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object returnObject = method.invoke(object, args);
return returnObject;
}
}
感謝閱讀此文,希望能幫助到大家,謝謝大家對本站的支持!

