java要实现代理可以通过继承和聚合来实现,个人不推荐用继承实现,用继承实现可能使继承层次很多,这样结构就不好看,也不符合设计模式中的建议(尽量使用聚合而代替使用继承)。 看看java的动态代理是怎么实现的: 下面通过模拟java的动态代理写一个例子:
public interface Sale {
public void sale();
}
package com.KingXt.proxy;
public class ComputerSales implements Sale{
@Override
public void sale() {
System.out.println("--------ComputerSales--------");
}
}
通过实现下面的接口,用户就可以自定义代理方式(例如:方法执行前后打印出当前时间)
package com.KingXt.proxy;
import java.lang.reflect.Method;
public interface InvocationHandler{
public void invoke(Object proxy, Method method);
}
简单写了一个类来测试按此类实现代理
package com.KingXt.proxy;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* 赠送代理
* @author KingXt
*
*/
public class PresentInvocationHandler implements InvocationHandler{
private Object object;
public PresentInvocationHandler(Object object) {
super();
this.object = object;
}
@Override
public void invoke(Object proxy, Method method){
System.out.println("赠送鼠标");
try {
method.invoke(object, new Object[]{});
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
这是代理生成类,通过动态生成java文件,调用jdk6带来的特性将文件编译成class,然后通过反射生成代理类
package com.KingXt.proxy;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import javax.tools.JavaCompiler;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import javax.tools.JavaCompiler.CompilationTask;
/**
* 代理类实现
* @author KingXt
*
*/
@SuppressWarnings("unchecked")
public class Proxy {
//得到项目根目录
public static final String baseDir = System.getProperty("user.dir");
public static Object newProxyInstance(Class intface, InvocationHandler h){
if (h == null) {
throw new NullPointerException();
}
String methodString = Proxy.getMethodString(intface);
String src = "package com.KingXt.proxy; " +
"import java.lang.reflect.Method; " +
"public class ProxyAny implements " + intface.getName()+ "{" +
"com.KingXt.proxy.InvocationHandler h;" +
"public ProxyAny(InvocationHandler ih){" +
"this.h = ih;" +
"}" +
methodString +
"}"+
"}";
String fileName = baseDir + "/src/com/KingXt/proxy/ProxyAny.java";
File file = new File(fileName);
//将字符串写入java文件
try {
FileWriter fw = new FileWriter(file);
fw.write(src);
fw.flush();
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
return getObjectWithFile(fileName, h);
}
/**
* 拼接一个类的方法字符串
* @param intface 接口
* @return 方法字符串
*/
private static String getMethodString(Class intface){
StringBuffer sb = new StringBuffer();
//得到接口中的所有方法
Method []ms = intface.getMethods();
for(Method m : ms){
sb.append("@Override ");
sb.append("public void "+ m.getName() +"(){ ");
sb.append("try { ");
sb.append("Method m = " + intface.getName() + ".class.getMethod(\"" + m.getName() + "\");");
sb.append("h.invoke(this, m);");
sb.append("}catch(Exception e){e.printStackTrace();}");
}
return sb.toString();
}
/**
* 首先将java文件动态编译,然后将编译后的class的文件load进内存,再通过反射机制生产java类
* @param filePath java文件的位置
* @param ih 要生产java类,通过调用构造函数构建,这就必须知道构造函数的参数
* @return 调用反射生成的类
*/
private static Object getObjectWithFile(String filePath, InvocationHandler ih){
Object o = null;
//得到java本地编译器
JavaCompiler jc = ToolProvider.getSystemJavaCompiler();
//通过java编译器得到文件管理器
StandardJavaFileManager javaFileManager = jc.getStandardFileManager(null, null, null);
Iterable files = javaFileManager.getJavaFileObjects(filePath);
CompilationTask ct = null;
//调用java编译器编译java文件
ct = jc.getTask(null, javaFileManager, null, null, null, files);
ct.call();
try {
javaFileManager.close();
} catch (IOException e) {
e.printStackTrace();
}
//通过URLClassLoader加载class文件
URL urls[] = null;
try {
/*
* 这里要重点注意:
* 如果file:/" + baseDir + "/src这个字符串最后没有"/", URLClassLoader加载的是jar文件
* 否则加载的是一个目录
*/
urls = new URL[]{new URL("file:/" + baseDir + "/src/")};
} catch (MalformedURLException e) {
e.printStackTrace();
}
URLClassLoader ul = new URLClassLoader(urls, Thread.currentThread().getContextClassLoader());
Class c = null;
try {
c = ul.loadClass("com.KingXt.proxy.ProxyAny");
Constructor constr = c.getConstructor(InvocationHandler.class);
o = constr.newInstance(ih);
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return o;
}
}
package com.KingXt.proxy;
public class Test {
public static void main(String[] args) {
//创一个电脑销售商
ComputerSales computerSales = new ComputerSales();
//给出销售前后可以处理的动作,例如:送鼠标
InvocationHandler ih = new PresentInvocationHandler(computerSales);
//创建代理
Sale sale = (Sale) Proxy.newProxyInstance(Sale.class, ih);
//根据代理产生的对象执行动作
sale.sale();
}
}
通过上面的代码,基本上模拟了java的动态代理。但是还有很多细节性东西没实现,比如invoke函数的返回值不应该是void、同步等等。要想知道jdk具体实现可以看看jdk的源代码。还有一点要强调的是URLClassLoader的使用,很容易产生ClassNotFoundException异常。
分享到:
相关推荐
本示例将带你深入理解Java动态代理的概念,并通过一个简单易懂的demo来演示其用法。 1. **Java动态代理概念** Java动态代理基于Java反射机制,可以在运行时动态地创建代理类和代理对象。与静态代理(即手动编写...
Java动态代理是Java语言提供的一种高级特性,它允许我们在运行时创建一个代理对象来代替某个接口或类的对象,这个代理对象能够对...分析和理解这个文件的内容,可以帮助我们深入理解Java动态代理的更多细节和应用场景。
### Java动态代理实现数据库连接池 #### 背景与挑战 在开发应用程序时,数据库连接池...这种实现方式灵活且易于扩展,对于希望深入理解Java动态代理机制以及数据库连接池实现原理的开发者来说,具有较高的参考价值。
通过深入理解Java动态代理机制,我们可以灵活地扩展已有代码的功能,而无需修改原始代码,这在维护性和可扩展性方面具有很大的优势。同时,`j-dynproxies-source`这样的开源项目可以帮助我们学习和借鉴其他开发者在...
在这个“狗星例子”中,我们将深入理解Java动态代理的工作原理,并通过具体的代码示例来阐述其核心概念。 首先,我们要知道Java动态代理主要依赖于`java.lang.reflect.Proxy`类和`java.lang.reflect....
Java动态代理是Java编程中一个重要...以上内容是对Java动态代理技术的概述,详细的学习和理解可以通过阅读给定的文档来深入探讨。在实践中,掌握动态代理能够帮助开发者编写更灵活、可扩展的代码,提高软件的可维护性。
刘意老师的2014版动态代理讲解视频是学习这一主题的宝贵资源,结合视频中的内存图,可以帮助我们深入理解Java动态代理的工作原理及其应用。 动态代理,简单来说,就是在运行时创建一个实现了特定接口的代理类,这个...
"示例来理解Java动态代理: ```java // 目标接口 public interface HelloWorld { void sayHello(); } // 目标实现 public class HelloWorldImpl implements HelloWorld { @Override public void sayHello() { ...
新的 UserService 实例 = new UserServiceImpl(); UserService proxyUserService = new UserServiceProxy(userServiceImpl);...了解和掌握动态代理技术对于深入理解 Java 并应用于实际项目开发有着重要的意义。
本文将深入讲解如何利用Java动态代理技术来实现AOP,以便于读者理解并实践。 #### 二、面向切面编程(AOP)简介 面向切面编程(Aspect-Oriented Programming,简称AOP)是一种编程范式,旨在通过将横切关注点与...
首先,让我们深入理解Java动态代理。动态代理基于Java的反射API实现,它允许我们在运行时创建一个实现了特定接口的代理类。这个代理类可以代理真实对象的方法调用,并在调用前后添加额外的操作。通常,我们通过`java...
通过阅读和理解这个例子,你可以更深入地掌握动态代理的实现细节。如果你对某个部分有疑问,或者想要了解更多相关知识,可以参考博客文章(http://520code.net/index.php/archives/19/)进行深入学习。
首先,让我们深入理解Java动态代理。动态代理是Java提供的一种机制,允许我们在运行时创建一个实现一组给定接口的类的代理实例。这个代理类可以在调用方法时执行额外的操作,如日志记录、性能监控或事务管理。动态...
在深入探讨Java动态代理的实现过程之前,我们首先需要理解动态代理的基本概念及其在Java中的应用价值。动态代理,顾名思义,是在运行时动态创建代理对象的一种机制,它无需在编译期就确定代理类的具体实现,而是通过...
在IT行业中,ORM(Object-Relational Mapping,对象关系映射)是一种常用的技术,它允许...虽然现有的ORM框架如Hibernate、MyBatis已经相当成熟,但对于学习和理解Java的高级特性,这样的实践不失为一种有益的尝试。
这里我们将深入探讨两个主要的Java动态代理实现:JDK动态代理和CGLIB动态代理。 **JDK动态代理**: JDK动态代理基于Java接口实现,适用于目标对象实现了至少一个接口的情况。它通过`java.lang.reflect.Proxy`类和`...
这种方式虽然相比现成的连接池库可能功能有限,但能帮助我们深入理解数据库连接池的工作原理,并且在某些定制化需求的场景下,提供了更大的灵活性。通过下载并运行提供的源码,我们可以更直观地学习这一实现方式。
这篇博客的文章链接虽然没有给出具体内容,但我们可以根据Java动态代理和Spring AOP的基本概念来深入探讨相关知识点。 首先,Java动态代理允许我们在运行时创建一个实现了特定接口的新类。这个新类会代理原始类,并...
通过阅读和理解这些代码,你可以更深入地了解Java动态代理的工作原理和实际应用。 Java动态代理广泛应用于AOP(面向切面编程),例如Spring AOP框架,日志记录,性能监控,事务管理等场景。通过动态代理,我们可以...