- 浏览: 296889 次
- 性别:
- 来自: 上海
文章分类
最新评论
-
wangweiying123:
import com.sse.monitor.bean.Mes ...
一个项目看java TCP/IP Socket编程(1.3版) -
daxiaoli123:
求源码 448485223@qq.com
一个项目看java TCP/IP Socket编程(1.3版) -
jeromexf:
楼主,求源码,万分感谢(jeromexf@gmail.com) ...
一个项目看java TCP/IP Socket编程(1.3版) -
cuishen:
注意: 网上有人说IE8以下不支持Max-Age, 上面的代码 ...
Response Header Set-Cookie difference in cross browser -
zhunengfei:
刚接触socket,不是太明白,楼主的例子里面工具给的不是很全 ...
一个项目看java TCP/IP Socket编程(1.3版)
一提到jdk中的java.lang.reflect.Proxy,用过spring,hibernate等框架的人应该都有所了解,对!就是动态代理。AOP - 面向切面编程 - 就是基于动态代理实现的。
平日里项目中用spring aop框架进行日志拦截和声明式事务处理确实很方便好用,从另一种角度将代码解耦,极大的提高了代码的灵活性和可扩展性,在获益的同时我们不得不惊叹aop框架的神奇,但是静下心来想一想:它的核心 - 动态代理 - 其实是依靠运行时动态在内存中实现要代理的接口,并在所有接口的方法实现中反射java.lang.reflect.InvocationHandler的invoke方法;所以要用动态代理就必须先实现自己的InvocationHandler;返回给用户的是代理对象本身,而非接口的原有实现。
想明白了代理的本质,实现它就很容易了,我们可以借助开源的动态生成字节码/类的项目,如:
Byte Code Engineering Library (BCEL) - 在实际的JVM 指令层次上进行操作,提供在运行时在内存中动态生成类的支持
Javassist - 提供类似BCEL的功能,不过它更强调源代码级别的工作,对于程序员来说更加容易上手
好了,废话不多说了,现在看看我用Javassist实现的动态代理,提供接近java.lang.reflect.Proxy的功能
我也提供了类似于java.lang.reflect.InvocationHandler的接口,我暂且称其为拦截器接口,要用我的代理,就得先实现它
平日里项目中用spring aop框架进行日志拦截和声明式事务处理确实很方便好用,从另一种角度将代码解耦,极大的提高了代码的灵活性和可扩展性,在获益的同时我们不得不惊叹aop框架的神奇,但是静下心来想一想:它的核心 - 动态代理 - 其实是依靠运行时动态在内存中实现要代理的接口,并在所有接口的方法实现中反射java.lang.reflect.InvocationHandler的invoke方法;所以要用动态代理就必须先实现自己的InvocationHandler;返回给用户的是代理对象本身,而非接口的原有实现。
想明白了代理的本质,实现它就很容易了,我们可以借助开源的动态生成字节码/类的项目,如:
Byte Code Engineering Library (BCEL) - 在实际的JVM 指令层次上进行操作,提供在运行时在内存中动态生成类的支持
Javassist - 提供类似BCEL的功能,不过它更强调源代码级别的工作,对于程序员来说更加容易上手
好了,废话不多说了,现在看看我用Javassist实现的动态代理,提供接近java.lang.reflect.Proxy的功能
package com.cuishen.myAop; import java.lang.reflect.Method; import javassist.CannotCompileException; import javassist.ClassPool; import javassist.CtClass; import javassist.NotFoundException; import javassist.CtMethod; import javassist.CtNewMethod; /** * 基于javassist实现的动态代理类,即在运行时在内存中动态生成要代理的接口的实现,并在接口的方法实现中反射 * com.cuishen.myAop.InterceptorHandler(拦截器接口)的invoke方法,所以在使用本代理之前请先实现 * 拦截器接口。本代理提供接近java.lang.reflect.Proxy的功能 * @author cuishen * @version 1.0 * @see com.cuishen.myAop.InterceptorHandler * @see java.lang.reflect.Proxy */ public class MyProxyImpl { /** 动态代理类的类名后缀 */ private final static String PROXY_CLASS_NAME_SUFFIX = "$MyProxy_"; /** 拦截器接口 */ private final static String INTERCEPTOR_HANDLER_INTERFACE = "com.cuishen.myAop.InterceptorHandler"; /** 动态代理类的类名索引,防止类名重复 */ private static int proxyClassIndex = 1; /** * 暴露给用户的动态代理接口,返回某个接口的动态代理对象,注意本代理实现需和com.cuishen.myAop.InterceptorHandler拦截器配合 * 使用,即用户要使用本动态代理,需先实现com.cuishen.myAop.InterceptorHandler拦截器接口 * <br> * 使用方法如下: * <br> * <code> * StudentInfoService studentInfo = (StudentInfoService)MyProxyImpl.newProxyInstance(String, String, String); * <br>studentInfo.方法调用; * </code> * @param interfaceClassName String 要动态代理的接口类名, e.g test.StudentInfoService * @param classToProxy String 要动态代理的接口的实现类的类名, e.g test.StudentInfoServiceImpl * @param interceptorHandlerImplClassName String 用户提供的拦截器接口的实现类的类名 * @return Object 返回某个接口的动态代理对象 * @throws InstantiationException * @throws IllegalAccessException * @throws NotFoundException * @throws CannotCompileException * @throws ClassNotFoundException * @see com.cuishen.myAop.InterceptorHandler */ public static Object newProxyInstance(String interfaceClassName, String classToProxy, String interceptorHandlerImplClassName) throws InstantiationException, IllegalAccessException, NotFoundException, CannotCompileException, ClassNotFoundException { Class interfaceClass = Class.forName(interfaceClassName); Class interceptorHandlerImplClass = Class.forName(interceptorHandlerImplClassName); return dynamicImplementsInterface(classToProxy, interfaceClass, interceptorHandlerImplClass); } /** * 动态实现要代理的接口 * @param classToProxy String 要动态代理的接口的实现类的类名, e.g test.StudentInfoServiceImpl * @param interfaceClass Class 要动态代理的接口类, e.g test.StudentInfoService * @param interceptorHandlerImplClass Class 用户提供的拦截器接口的实现类 * @return Object 返回某个接口的动态代理对象 * @throws NotFoundException * @throws CannotCompileException * @throws InstantiationException * @throws IllegalAccessException */ private static Object dynamicImplementsInterface(String classToProxy, Class interfaceClass, Class interceptorHandlerImplClass) throws NotFoundException, CannotCompileException, InstantiationException, IllegalAccessException { ClassPool cp = ClassPool.getDefault(); String interfaceName = interfaceClass.getName(); //动态指定代理类的类名 String proxyClassName = interfaceName + PROXY_CLASS_NAME_SUFFIX + proxyClassIndex++; //要实现的接口的包名+接口名 String interfaceNamePath = interfaceName; CtClass ctInterface = cp.getCtClass(interfaceNamePath); CtClass cc = cp.makeClass(proxyClassName); cc.addInterface(ctInterface); Method [] methods = interfaceClass.getMethods(); for(int i = 0; i < methods.length; i++) { Method method = methods[i]; dynamicImplementsMethodsFromInterface(classToProxy, cc, method, interceptorHandlerImplClass, i); } return (Object)cc.toClass().newInstance(); } /** * 动态实现接口里的方法 * @param classToProxy String 要动态代理的接口的实现类的类名, e.g test.StudentInfoServiceImpl * @param implementer CtClass 动态代理类的包装 * @param methodToImpl Method 动态代理类里面要实现的接口方法的包装 * @param interceptorClass Class 用户提供的拦截器实现类 * @param methodIndex int 要实现的方法的索引 * @throws CannotCompileException */ private static void dynamicImplementsMethodsFromInterface(String classToProxy, CtClass implementer, Method methodToImpl, Class interceptorClass, int methodIndex) throws CannotCompileException { String methodCode = generateMethodCode(classToProxy, methodToImpl, interceptorClass, methodIndex); CtMethod cm = CtNewMethod.make(methodCode, implementer); implementer.addMethod(cm); } /** * 动态组装方法体,当然代理里面的方法实现并不是简单的方法拷贝,而是反射调用了拦截器里的invoke方法,并将接收到的参数进行传递 * @param classToProxy String 要动态代理的接口的实现类的类名, e.g test.StudentInfoServiceImpl * @param methodToImpl Method 动态代理类里面要实现的接口方法的包装 * @param interceptorClass Class 用户提供的拦截器实现类 * @param methodIndex int 要实现的方法的索引 * @return String 动态组装的方法的字符串 */ private static String generateMethodCode(String classToProxy, Method methodToImpl, Class interceptorClass, int methodIndex) { String methodName = methodToImpl.getName(); String methodReturnType = methodToImpl.getReturnType().getName(); Class []parameters = methodToImpl.getParameterTypes(); Class []exceptionTypes = methodToImpl.getExceptionTypes(); StringBuffer exceptionBuffer = new StringBuffer(); //组装方法的Exception声明 if(exceptionTypes.length > 0) exceptionBuffer.append(" throws "); for(int i = 0; i < exceptionTypes.length; i++) { if(i != exceptionTypes.length - 1) exceptionBuffer.append(exceptionTypes[i].getName()).append(","); else exceptionBuffer.append(exceptionTypes[i].getName()); } StringBuffer parameterBuffer = new StringBuffer(); //组装方法的参数列表 for(int i = 0; i < parameters.length; i++) { Class parameter = parameters[i]; String parameterType = parameter.getName(); //动态指定方法参数的变量名 String refName = "a" + i; if(i != parameters.length - 1) parameterBuffer.append(parameterType).append(" " + refName).append(","); else parameterBuffer.append(parameterType).append(" " + refName); } StringBuffer methodDeclare = new StringBuffer(); //方法声明,由于是实现接口的方法,所以是public methodDeclare.append("public ").append(methodReturnType).append(" ").append(methodName).append("(").append(parameterBuffer).append(")").append(exceptionBuffer).append(" {\n"); String interceptorImplName = interceptorClass.getName(); //方法体 methodDeclare.append(INTERCEPTOR_HANDLER_INTERFACE).append(" interceptor = new ").append(interceptorImplName).append("();\n"); //反射调用用户的拦截器接口 methodDeclare.append("Object returnObj = interceptor.invoke(Class.forName(\"" + classToProxy + "\").newInstance(), Class.forName(\"" + classToProxy + "\").getMethods()[" + methodIndex + "], "); //传递方法里的参数 if(parameters.length > 0) methodDeclare.append("new Object[]{"); for(int i = 0; i < parameters.length; i++) { //($w) converts from a primitive type to the corresponding wrapper type: e.g. //Integer i = ($w)5; if(i != parameters.length - 1) methodDeclare.append("($w)a" + i + ","); else methodDeclare.append("($w)a" + i); } if(parameters.length > 0) methodDeclare.append("});\n"); else methodDeclare.append("null);\n"); //对调用拦截器的返回值进行包装 if(methodToImpl.getReturnType().isPrimitive()) { if(methodToImpl.getReturnType().equals(Boolean.TYPE)) methodDeclare.append("return ((Boolean)returnObj).booleanValue();\n"); else if(methodToImpl.getReturnType().equals(Integer.TYPE)) methodDeclare.append("return ((Integer)returnObj).intValue();\n"); else if(methodToImpl.getReturnType().equals(Long.TYPE)) methodDeclare.append("return ((Long)returnObj).longValue();\n"); else if(methodToImpl.getReturnType().equals(Float.TYPE)) methodDeclare.append("return ((Float)returnObj).floatValue();\n"); else if(methodToImpl.getReturnType().equals(Double.TYPE)) methodDeclare.append("return ((Double)returnObj).doubleValue();\n"); else if(methodToImpl.getReturnType().equals(Character.TYPE)) methodDeclare.append("return ((Character)returnObj).charValue();\n"); else if(methodToImpl.getReturnType().equals(Byte.TYPE)) methodDeclare.append("return ((Byte)returnObj).byteValue();\n"); else if(methodToImpl.getReturnType().equals(Short.TYPE)) methodDeclare.append("return ((Short)returnObj).shortValue();\n"); } else { methodDeclare.append("return (" + methodReturnType + ")returnObj;\n"); } methodDeclare.append("}"); System.out.println(methodDeclare.toString()); return methodDeclare.toString(); } }
我也提供了类似于java.lang.reflect.InvocationHandler的接口,我暂且称其为拦截器接口,要用我的代理,就得先实现它
package com.cuishen.myAop; import java.lang.reflect.Method; /** * 拦截器接口,用户使用com.cuishen.myAop.MyProxyImpl动态代理前,请先实现本接口, * 在执行动态代理对象的方法时会自动反射到invoke方法,被代理的对象、方法和参数将做为 * 参数传递给invoke方法 * @author cuishen * @version 1.0 * @see com.cuishen.myAop.MyProxyImpl */ public interface InterceptorHandler { /** * 调用动态代理对象的方法将反射本方法,可在本方法实现中添加类似AOP的事前事后操作,只有在本方法体中加入如下代码 * <br> * <code> * Object returnObj = method.invoke(obj, args); * <br> * ... * <br> * return returnObj; * </code> * <br> * 被代理的方法才会被执行,返回值将返回给代理最后返回给程序 * @param obj Object 被代理的对象 * @param method Method 被代理对象的方法 * @param args Object[] 被代理对象的方法的参数 * @return Object 被代理对象的方法执行后的返回值 * @throws Throwable */ public Object invoke(Object obj, Method method, Object[] args) throws Throwable; }
- aop.rar (570.7 KB)
- 下载次数: 313
发表评论
-
设计模式---观察者模式(Observer Pattern with java)
2013-08-22 12:26 1735java中的 Listener - Event 是应用了设计模 ... -
java单线程实现队列模型
2013-04-23 17:51 8927以下是我整理的用java单线程实现队列Queue的代码模型。 ... -
Java线程安全隐患
2012-02-10 15:16 1802最近一直在考虑java线程 ... -
java代码调优笔记(一)
2011-10-28 13:30 1530(1). 用Boolean.valueOf(boolean ... -
浅析java callback 回调模式
2009-08-03 11:36 12532看过spring、hibernate源码的朋友对callbac ... -
java程序性能优化之找出内存溢出元凶
2009-06-08 08:47 7466我曾经在刚入行的时候 ... -
一个项目看java TCP/IP Socket编程(1.3版)
2008-09-16 17:50 23321前一段时间刚做了个java程序和网络上多台机器的c程序通讯的项 ... -
Log4J使用完全手册(转)
2007-11-20 15:04 5255Log4J是Apache的一个开放 ... -
神奇的java反射机制
2007-07-28 22:44 4215最近在开发一个小型的j2ee项目,沿用以前公司成熟的strut ... -
解决dom4j无法解析xml命名空间的问题
2006-11-26 19:29 5980困扰我几周的dom4j无法 ... -
dom4j中处理XML命名空间的问题,哪位指点下,谢谢!!!
2006-11-23 21:57 2681要用dom4j解析的带命名空间的xml文档如下: ---my ... -
关于dom4j无法读取xml文件的问题,已经困扰我几个礼拜了,哪位指点迷津!
2006-11-21 20:22 3239要读取的xml文件1----myXML.xml,放在c盘根目录 ...
相关推荐
在Struts2中,Javassist用于类的动态代理,以便实现AOP(面向切面编程)和拦截器功能。 5. **ognl-3.0.jar**:Object-Graph Navigation Language(OGNL)是一种强大的表达式语言,用于获取和设置Java对象的属性。在...
在Struts2中,它用于动态生成代理类,实现如AOP(面向切面编程)等高级功能。 6. **sqljdbc4.jar**:这是Microsoft提供的JDBC驱动,用于与SQL Server数据库进行连接,执行SQL语句,实现数据的增删改查操作。 7. **...
20. **hibernate-search.jar**:提供全文搜索功能,基于Lucene或其他搜索引擎。 21. **jboss-transaction-api_1.2_spec.jar**:JTA 1.2规范的实现。 22. **javassist-3.20.0-GA.jar**:另一个版本的javassist库,...
5. **.javassist.jar**:Javaassist库用于动态地修改类结构,Struts2使用它来处理Action类的动态代理,实现拦截器的功能。 6. **.commons-logging.jar**:这是一个通用的日志接口,提供日志抽象层,使得Struts2可以...
在Hibernate中,Javassist用于动态生成代理类以实现懒加载和其他特性。 8. **commons-collections-3.1.jar**:Apache Commons Collections是Apache软件基金会提供的一个工具包,提供了大量的集合类和算法,扩展了...
10. **cglib-2.2.jar**:Code Generation Library,用于生成子类以实现对目标类的动态代理或方法拦截,是 Spring AOP(面向切面编程)框架的重要组成部分,也可能在 Activiti 中用于动态代理或扩展。 综上所述,...
在Struts2中,它用于动态代理,实现如AOP(面向切面编程)的拦截器功能。 5. `commons-lang3-3.1.jar`:Apache Commons Lang是一个包含许多实用工具类的库,提供了字符串处理、日期/时间操作、数学计算等大量功能,...
使用Hibernate,开发者无需编写大量的SQL语句,就能实现对数据库的CRUD操作。为了使用Hibernate,你需要以下架包: - `hibernate-core.jar`:Hibernate的核心库,提供了ORM的所有基本功能。 - `hibernate-...
在Hibernate中,Javassist用于动态生成代理类,支持延迟加载(Lazy Loading)等特性。 6. Commons Collections:`commons-collections-3.1.jar`是Apache Commons项目的一部分,提供了一系列实用的集合类和算法,...
6. **javassist-3.9.0.GA.jar**:这是一个Java字节码操作和分析库,常被Hibernate和其他框架用来自动生成或修改类的字节码,以实现动态代理或运行时增强。 7. **commons-collections-3.1.jar**:Apache Commons ...
- **javassist-3.9.0.GA.jar**:动态字节码操作库,被Hibernate用来生成代理类。 - **cglib-2.2.jar**:用于创建动态代理,也是Hibernate依赖的库之一。 - **hibernate-commons-annotations.jar**:Hibernate使用的...
`javassist-3.20.0-GA.jar`是Java编程辅助工具,用于运行时动态修改类和类加载器,Struts 2使用它来实现动态代理。 `commons-lang3-3.6.jar`是Apache Commons Lang库,提供了一些高级语言功能,如字符串操作、日期...
`javassist-3.12.0.GA.jar`是Hibernate使用的字节码处理库,用于动态生成代理类,实现懒加载和缓存机制。 此外,该集合中还包括了其他一些辅助库: - `log4j`是一个日志记录框架,`...
5. **javassist.jar**:这是一个代码生成库,Struts2使用它来实现运行时动态代理,以实现拦截器的AOP(面向切面编程)功能。 6. **struts2-plugins.jar**:这通常包含了一些预定义的插件,例如struts2-convention-...
Hibernate通过`hibernate-jpa-2.0-api.jar`与JPA 2.0规范对接,同时`javassist.jar`负责运行时字节码操作,以实现动态代理和类增强。`jta.jar`则是Java Transaction API,用于管理事务,确保数据的一致性。 3. **...
- `javassist-3.9.0.GA.jar`:MyBatis使用javassist动态生成代理类,以实现SQL执行的动态绑定。 - `spring.jar`:可能包含Spring的部分或全部组件,如AOP、DI等。 整合这三个框架,通常步骤包括: 1. 配置Struts...
`javassist-3.11.0.GA.jar`是一个动态类库,用于在运行时修改类和接口。Struts2使用它来实现动态代理和AOP(面向切面编程),这使得在不修改原有代码的情况下,可以方便地添加新的功能或拦截器。 `ognl-3.0.6.jar`...
5. **javassist-x.x.x.jar**:Javaassist是一个库,允许在运行时动态修改类和接口,Struts2用它来实现AOP和动态代理。 6. **struts2-convention-plugin-x.x.x.jar**:这是一个插件,提供了基于约定优于配置的特性,...
在Struts2中,它可能用于动态代理和拦截器的实现。 6. **struts2-embeddedjsp-plugin-2.5.10.1.jar**:这是一个插件,使得Struts2能够内嵌JSP视图,使开发者可以直接在Action类中使用JSP标签,简化视图层的开发。 ...
8. **javassist.jar**:这是一个代码生成库,Struts2使用它来实现运行时动态代理,创建拦截器。 9. **slf4j-api.jar** 和 **log4j.jar**:日志框架接口和实现,Struts2使用它们进行日志记录,方便调试和问题定位。 ...