java 反射和動態(tài)代理詳解及實例代碼
一、java中的反射
1.通過反射加載類的屬性和方法實例代碼:
/**
* java.lang.Class 是反射的源頭
* 我們創(chuàng)建了一個類,通過編譯(javac.exe)生成對應(yīng)的class文件,之后我們通過java.exe加載(jvm的類加載器加載)此class文件
* 此class文件加載到內(nèi)存后,就是一個運行時類,存在緩存區(qū),這個運行時類本事就是一個Class的實例
* 每一個運行時類只加載一次,
*/
Class<StudentExam> clazz = StudentExam.class;
StudentExam studentExam = clazz.newInstance();
System.err.println(studentExam);
System.out.println(clazz);
// Field field = clazz.getField("id"); // 通過屬性調(diào)用運行時類的指定屬性:屬性是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);// 獲取字段屬性的數(shù)據(jù)類型
System.out.println(type);
}
field.setAccessible(true);
field.set(studentExam, 11);
System.err.println(studentExam.getId());
// 通過反射調(diào)用運行時類的指定方法
Method method = clazz.getMethod("setId", Integer.class);
method.invoke(studentExam, 123); // 調(diào)用運行時類的指定方法
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文件,并讀取數(shù)據(jù)
* @param
* @author xiazhongwei
* @data 2016年9月29日:下午5:32:56
* @return
*/
public void classLoader() throws IOException {
//方法一、從當(dāng)前工程下加載
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)代理:代理類和目標(biāo)對象的類型都是在編譯期間確定下來,不利于程序的擴(kuò)展。同時每個代理類只能為一個接口服務(wù),這樣一來程序開發(fā)中必然產(chǎn)生過多的代理。
動態(tài)代理:客戶通過代理類來調(diào)用其他對象的方法,并且是在程序運行時,根據(jù)需要動態(tài)創(chuàng)建目標(biāo)類的代理對象。
代理設(shè)計模式的原理:
使用一個代理將對象包裝起來,然后用該代理對象取代原始對象,任何對原始對象的調(diào)用都要通過代理,代理對象決定的那個是否以及何時將方法調(diào)用
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;// 實現(xiàn)了接口的被代理類的對象的聲明
/**
* 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);
}
/**
* 當(dāng)通過代理類的對象發(fā)起對被重寫的方法的調(diào)用時,都會轉(zhuǎn)化為對如下的invok方法的調(diào)用
*/
@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;
// 代理對象有哪一個類加載器負(fù)責(zé)加載
ClassLoader loader = target.getClass().getClassLoader();
// 代理對象的類型,即其中有哪些方法
Class [] interfaces = new Class[]{ArithmeticCalculator.class};
// 當(dāng)調(diào)用代理對象的其中方法時,執(zhí)行下面的代碼
InvocationHandler h = new InvocationHandler() {
/**
* proxy: 代理對象。 一般不使用該對象
* method: 正在被調(diào)用的方法
* args: 調(diào)用方法傳入的參數(shù)
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// 在方法內(nèi)部不會直接調(diào)用proxy對象的某個方法,proxy.toString()會造成死循環(huán)調(diào)用invoke方法
String methodName = method.getName();
//打印日志
System.out.println("[before] The method " + methodName + " begins with " + Arrays.asList(args));
//調(diào)用目標(biāo)方法
Object result = null;
try {
//前置通知
result = method.invoke(target, args);
//返回通知, 可以訪問到方法的返回值
} catch (NullPointerException e) {
e.printStackTrace();
//異常通知, 可以訪問到方法出現(xiàn)的異常
}
//后置通知. 因為方法可以能會出異常, 所以訪問不到方法的返回值
//打印日志
System.out.println("[after] The method ends with " + result);
return result;
}
};
/**
* loader: 代理對象使用的類加載器。
* interfaces: 指定代理對象的類型. 即代理代理對象中可以有哪些方法.
* h: 當(dāng)具體調(diào)用代理對象的方法時, 應(yīng)該如何進(jìn)行響應(yīng), 實際上就是調(diào)用 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;// 實現(xiàn)了接口的被代理類的對象的聲明
/**
* 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);
}
/**
* 當(dāng)通過代理類的對象發(fā)起對被重寫的方法的調(diào)用時,都會轉(zhuǎn)化為對如下的invok方法的調(diào)用
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object returnObject = method.invoke(object, args);
return returnObject;
}
}
感謝閱讀此文,希望能幫助到大家,謝謝大家對本站的支持!
相關(guān)文章
Netty網(wǎng)絡(luò)編程零基礎(chǔ)入門
Netty是一個異步的、基于事件驅(qū)動的網(wǎng)絡(luò)應(yīng)用框架,用于快速開發(fā)可維護(hù)、高性能的網(wǎng)絡(luò)服務(wù)器和客戶端,如果你還不了解它的使用,就趕快繼續(xù)往下看吧2022-08-08
intellij idea如何配置網(wǎng)絡(luò)代理
intellij idea所在的這臺電腦本身上不了網(wǎng),要通過代理上網(wǎng),那么intellij idea怎么設(shè)置代理上網(wǎng)呢?今天通過本文給大家分享intellij idea如何配置網(wǎng)絡(luò)代理,感興趣的朋友一起看看吧2023-10-10

