一個(gè)簡單JDK版動(dòng)態(tài)代理
本文實(shí)例為大家分享了手動(dòng)實(shí)現(xiàn)的一個(gè)簡單JDK版動(dòng)態(tài)代理,供大家參考,具體內(nèi)容如下
一.實(shí)現(xiàn)步驟
1.根據(jù)目標(biāo)類的接口類型生成代理類的java文件。
2.編譯代理類java文件為.class字節(jié)碼文件。
3.將編譯好的字節(jié)碼文件加載到j(luò)vm中。
4.生成代理類對(duì)象并返回。
二.代碼實(shí)現(xiàn)
1.Proxy類
public class CLProxy {
private static final String ENTER= "\r\n";
private static final String PAKAGE=CLProxy.class.getPackage().toString()+";";
private static final String CLASS_NAME="$Proxy";
private static final AtomicInteger NUMBER= new AtomicInteger(0);
public static Object newProxyInstance(CLClassLoader classLoader, Class<?>[] interfaces,CLInvocationHandler h) throws Exception{
String className =CLASS_NAME+NUMBER.getAndIncrement();
//遍歷所有的接口生成java 文件
String javaString = createJavaString(interfaces, className);
String parentPath = CLProxy.class.getResource("").getPath();
File file =new File(parentPath,className+".java" );
FileWriter writer = new FileWriter(file);
writer.write(javaString);
writer.flush();
writer.close();
//System.out.println(file);
//編譯
JavaCompiler systemJavaCompiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager standardFileManager = systemJavaCompiler.getStandardFileManager(null, null, null);
Iterable<? extends JavaFileObject> javaFileObjects = standardFileManager.getJavaFileObjects(file);
JavaCompiler.CompilationTask task = systemJavaCompiler.getTask(null, standardFileManager, null, null, null, javaFileObjects);
task.call();
standardFileManager.close();
//創(chuàng)建實(shí)例
Class<?> aClass = classLoader.findClass(className);
Constructor<?> constructor = aClass.getConstructor(CLInvocationHandler.class);
Object instance = constructor.newInstance(h);
//file.delete();
return instance;
}
/**
* 生成java 文件
* @param interfaces
* @return
*/
private static String createJavaString(Class<?>[] interfaces , String className ){
StringBuffer buffer = new StringBuffer();
buffer.append(PAKAGE+ENTER);
buffer.append("import java.lang.reflect.Method;"+ ENTER);
StringBuffer interfaceString= new StringBuffer();
int length= interfaces.length;
for (int i = 0; i<length ; ++i){
interfaceString.append(interfaces[i].getName());
if (i!=length-1){
interfaceString.append(",");
}
}
buffer.append("public final class ");
buffer.append(className);
buffer.append(" implements ");
buffer.append(interfaceString);
buffer.append(" {"+ENTER);
buffer.append("private CLInvocationHandler handler;"+ENTER);
buffer.append("public "+className+"(CLInvocationHandler handler) {"+ENTER);
buffer.append(" this.handler= handler;"+ENTER);
buffer.append("}"+ENTER);
for (int i =0 ;i<length;++i){
Class<?> clazz= interfaces[i];
Method[] methods = clazz.getMethods();
for (Method method : methods){
String returnTypeString = method.getReturnType().getName();
Class<?>[] parameterTypes = method.getParameterTypes();
StringBuffer paramTypeString = new StringBuffer();
StringBuffer methodParamString = new StringBuffer();
StringBuffer invokeParamString = new StringBuffer();
paramTypeString.append("new Class[]{");
int paramLength= parameterTypes.length;
for (int j =0 ; j<paramLength ;++j){
Class<?> paramClazz= parameterTypes[j];
paramTypeString.append(paramClazz.getName()+".class");
String paramFieldName = "var"+j;
methodParamString.append(paramClazz.getName() +" "+paramFieldName);
invokeParamString.append(paramFieldName);
if (j!= paramLength-1){
paramTypeString.append(",");
methodParamString.append(",");
invokeParamString.append(",");
}
}
paramTypeString.append("}");
int modifiers = method.getModifiers();
if (Modifier.isPublic(modifiers)){
buffer.append("public");
}else if (Modifier.isPrivate(modifiers)){
buffer.append("private");
}else if (Modifier.isProtected(modifiers)){
buffer.append("protected");
}
buffer.append(" final "+returnTypeString+" "+ method.getName()+"("+methodParamString+"){"+ ENTER);
buffer.append("try{"+ENTER);
buffer.append("Method method = "+clazz.getName()+".class.getMethod(\""+method.getName()+"\","+paramTypeString+" );"+ENTER);
if (!"void".equals(returnTypeString)){
buffer.append("return ("+returnTypeString+")");
}
if (invokeParamString.toString().length()==0){
invokeParamString.append("null");
}else{
invokeParamString = new StringBuffer("new Object[]{"+invokeParamString.toString()+"}");
}
buffer.append("this.handler.invoke(this,method,"+invokeParamString+");"+ENTER);
buffer.append("}catch(Throwable e){"+ENTER);
buffer.append("e.printStackTrace();"+ENTER);
buffer.append("}"+ENTER);
if (!"void".equals(returnTypeString)){
buffer.append("return null;"+ENTER);
}
buffer.append("}"+ENTER);
}
}
buffer.append("}");
return buffer.toString();
}
public static void main(String[] args) throws Exception {
Person person = (Person)CLProxy.newProxyInstance(new CLClassLoader(), XiaoMing.class.getInterfaces(), new CLInvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before");
Object result= method.invoke(new XiaoMing(), args);
System.out.println("after");
return result;
}
});
String laoxu = person.call("laoxu");
System.out.println(laoxu);
/* person.eat();
Class<?>[] interfaces = person.getClass().getInterfaces();
for (Class<?> in:interfaces){
System.out.println(in.getName());
}
*/
Person person2= (Person)CLProxy.newProxyInstance(new CLClassLoader(), XiaoMing.class.getInterfaces(), new CLInvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before");
Object result= method.invoke(new XiaoMing(), args);
System.out.println("after");
return result;
}
});
System.out.println(person2.getClass());
}
}
2.InvocationHandler接口
public interface CLInvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
}
3.ClassLoader類加載器
public class CLClassLoader extends ClassLoader {
private File classPathFile;
public CLClassLoader(){
String classPath = CLClassLoader.class.getResource("").getPath();
this.classPathFile= new File(classPath);
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
String className = CLClassLoader.class.getPackage().getName()+"."+name;
if (classPathFile!= null ){
File classFile = new File(classPathFile, name.replace("\\.", "/") + ".class");
if (classFile.exists()){
FileInputStream inputStream =null;
ByteArrayOutputStream outputStream = null;
try{
inputStream=new FileInputStream(classFile);
outputStream= new ByteArrayOutputStream();
byte[] bytes = new byte[1024];
int len;
while ((len=inputStream.read(bytes))!=-1){
outputStream.write(bytes,0,len);
}
return defineClass(className,outputStream.toByteArray(),0,outputStream.size());
}catch (Exception e){
e.printStackTrace();
}finally {
if (inputStream!= null){
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (outputStream!=null){
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
return super.findClass(name);
}
}
4.測(cè)試使用的接口與目標(biāo)類
//測(cè)試使用的接口
public interface Person {
void eat();
String call(String name);
}
//測(cè)試使用目標(biāo)類
public class XiaoMing implements Person {
@Override
public void eat() {
System.out.println("吃東西");
}
//@Override
public String call(String name) {
return name;
}
}
注意測(cè)試方法在CLProxy 的main 方法中。
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Spring AOP注解失效的坑及JDK動(dòng)態(tài)代理
- java動(dòng)態(tài)代理(jdk與cglib)詳細(xì)解析
- 詳解Spring的兩種代理方式:JDK動(dòng)態(tài)代理和CGLIB動(dòng)態(tài)代理
- 深入理解java動(dòng)態(tài)代理的兩種實(shí)現(xiàn)方式(JDK/Cglib)
- java jdk動(dòng)態(tài)代理詳解
- 淺談Java代理(jdk靜態(tài)代理、動(dòng)態(tài)代理和cglib動(dòng)態(tài)代理)
- jdk中動(dòng)態(tài)代理異常處理分析:UndeclaredThrowableException
- java代理 jdk動(dòng)態(tài)代理應(yīng)用案列
- Java JDK動(dòng)態(tài)代理(AOP)的實(shí)現(xiàn)原理與使用詳析
- Java JDK動(dòng)態(tài)代理的基本原理詳細(xì)介紹
相關(guān)文章
Java Kafka實(shí)現(xiàn)延遲隊(duì)列的示例代碼
kafka作為一個(gè)使用廣泛的消息隊(duì)列,很多人都不會(huì)陌生。本文將利用Kafka實(shí)現(xiàn)延遲隊(duì)列,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以嘗試一下2022-08-08
Java的字符讀寫類CharArrayReader和CharArrayWriter使用示例
這篇文章主要介紹了Java的字符讀寫類CharArrayReader和CharArrayWriter使用示例,兩個(gè)類分別繼承于Reader和Writer,需要的朋友可以參考下2016-06-06
Java實(shí)戰(zhàn)項(xiàng)目 圖書管理系統(tǒng)
這篇文章主要介紹了使用java SSM jsp mysql maven設(shè)計(jì)實(shí)現(xiàn)的精品圖書管理系統(tǒng),是一個(gè)很好的實(shí)例,對(duì)大家的學(xué)習(xí)和工作具有借鑒意義,建議收藏一下2021-09-09
Java多線程之scheduledThreadPool的方法解析
這篇文章主要介紹了Java多線程之scheduledThreadPool的方法解析,queue是DelayedWorkQueue,但通過后面的分析可以知道,最大線程數(shù)是不起作用的,最多會(huì)起核心線程數(shù)的數(shù)量,需要的朋友可以參考下2023-12-12
Java中的NumberFormatException異常原因以及解決方案詳解
這篇文章主要介紹了Java中的NumberFormatException異常原因以及解決方案詳解,NumberFormatException 是 Java 中的一個(gè)異常類,通常在字符串轉(zhuǎn)換為數(shù)字的過程中發(fā)生,它表示一個(gè)無效的數(shù)字格式,即字符串無法被正確解析為數(shù)字,需要的朋友可以參考下2024-02-02
springboot?@PostConstruct無效的解決
這篇文章主要介紹了springboot?@PostConstruct無效的解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11
JavaWeb實(shí)現(xiàn)多文件上傳及zip打包下載
這篇文章主要為大家詳細(xì)介紹了JavaWeb實(shí)現(xiàn)多文件上傳及zip打包下載,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-07-07

