当自学struts2的拦截器时,发现跟aop的功能很像,所以想把两个放在一起看看会发生什么。望大哥大姐多多指点哈
第一种情况使用struts2的AbstractInterceptor 拦截器
1. 使用Spring 代理 Struts2 的Action类,advice使用MethodBeforeAdvice
2. 在Action中使用一个继承自AbstractInterceptor的拦截器。
3. 当访问Action时,我认为因为Spring的代理对象在加载时已经被代理,所以它应该运行完Action的Interceptor再执行Spring的advice。结果和我想的一样,首先打印AbstractInterceptorMethodBeforeAdvice的信息,接着再打印MethodBeforeAdvice的内容,最后执行Action。
第二种情况使用struts2的Annotation拦截器
1. Spring 的配置和上面一样
2. 在Action中使用@Before标注一个非execute方法。
3. 当访问Action时,并未像第一种情况那样打印而是只打印了Spring的MethodBeforeAdvice的信息
为什么会这样呢?从陈英华的博文http://chenyinghua.iteye.com/blog/234814中我们了解到其实AbstractInterceptor和MethodBeforeAdvice的底层实现都是依靠的JDK的代理,在他的博文的基础上我加了Annotation,来看看为什么会发生第二种情况。(以下代码大多是借鉴陈英华的博文,在着表示感谢)
步骤1: 定义接口DynamicProxyFactory
步骤2: 定义接口Interceptor (本例暂不使用)
步骤3: 实现接口DynamicProxyFactory
步骤4: 实现调用处理器
步骤5:声明一个Annotation接口
所以准备工作做好现在该测试了。
测试
步骤1: 首先,给需要代理的类定义一个接口Service
步骤2: 实现这个接口,并使用Annotation,编写类ServiceImpl
步骤3: 实现拦截器接口Interceptor,编写类InterceptorImpl(该步骤暂不使用)
步骤4:编写测试类TestDynamicProxy
测试结果为:
method name is sayHello
java say: Hello, daniel
------打印service的Annotation:---------
方法 sayHello 的Annotation标注为 @com.interceptor.Before()
------打印 proxy 的Annotation:-----------
>>>>>>>>>>>TestDynamicProxy end
从结果我们可以看出service经过proxy后Annotation已经不存在了。
打开proxy.java的源码从getProxyClass(ClassLoader loader, Class<?>... interfaces)方法中的
代码知道,ProxyGenerator.generateProxyClass方法产生了一个字节数组,反编译ProxyGenerator从一下的两个重要方法
其中并没有发现对Annotation的处理,看来是把Annotation给忽略吧。
第一种情况使用struts2的AbstractInterceptor 拦截器
1. 使用Spring 代理 Struts2 的Action类,advice使用MethodBeforeAdvice
2. 在Action中使用一个继承自AbstractInterceptor的拦截器。
3. 当访问Action时,我认为因为Spring的代理对象在加载时已经被代理,所以它应该运行完Action的Interceptor再执行Spring的advice。结果和我想的一样,首先打印AbstractInterceptorMethodBeforeAdvice的信息,接着再打印MethodBeforeAdvice的内容,最后执行Action。
第二种情况使用struts2的Annotation拦截器
1. Spring 的配置和上面一样
2. 在Action中使用@Before标注一个非execute方法。
3. 当访问Action时,并未像第一种情况那样打印而是只打印了Spring的MethodBeforeAdvice的信息
为什么会这样呢?从陈英华的博文http://chenyinghua.iteye.com/blog/234814中我们了解到其实AbstractInterceptor和MethodBeforeAdvice的底层实现都是依靠的JDK的代理,在他的博文的基础上我加了Annotation,来看看为什么会发生第二种情况。(以下代码大多是借鉴陈英华的博文,在着表示感谢)
步骤1: 定义接口DynamicProxyFactory
package com.interceptor; public interface DynamicProxyFactory { /** * 生成动态代理,并且在调用代理执行函数的时候使用拦截器 * * @param clazz * 需要实现的接口 * @param target * 实现此接口的类 * @param interceptor * 拦截器 * @return */ public <T> T createProxy(T target, Interceptor interceptor); }
步骤2: 定义接口Interceptor (本例暂不使用)
package com.interceptor; import java.lang.reflect.Method; public interface Interceptor { public void before(Method method, Object[] args); public void after(Method method, Object[] args); public void afterThrowing(Method method, Object[] args, Throwable throwable); public void afterFinally(Method method, Object[] args); }
步骤3: 实现接口DynamicProxyFactory
package com.interceptor; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; public class DynamicProxyFactoryImpl implements DynamicProxyFactory { /** * 生成动态代理,并且在调用代理执行函数的时候使用拦截器 * * @param target * 需要代理的实例 * @param interceptor * 拦截器实现,就是我们希望代理类执行函数的前后, 抛出异常,finally的时候去做写什么 */ @SuppressWarnings("unchecked") public <T> T createProxy(T target, Interceptor interceptor) { // 当前对象的类加载器 ClassLoader classLoader = target.getClass().getClassLoader(); // 获取此对象实现的所有接口 Class<?>[] interfaces = target.getClass().getInterfaces(); // 利用DynamicProxyInvocationHandler类来实现InvocationHandler InvocationHandler handler = new DynamicProxyInvocationHandler(target, interceptor); return (T) Proxy.newProxyInstance(classLoader, interfaces, handler); } }
步骤4: 实现调用处理器
package com.interceptor; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; /** * 动态代理的调用处理器 * * @author chen.yinghua */ public class DynamicProxyInvocationHandler implements InvocationHandler { private Object target; private Interceptor interceptor; /** * @param target * 需要代理的实例 * @param interceptor * 拦截器 */ public DynamicProxyInvocationHandler(Object target, Interceptor interceptor) { this.target = target; this.interceptor = interceptor; } /** * @param proxy * 所生成的代理对象 * @param method * 调用的方法示例 * @args args 参数数组 * @Override */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object result = null; Method methodBefore=null; Class clazz = target.getClass(); Method methods[] = clazz.getMethods(); for(Method method0:methods){ if(method0.isAnnotationPresent(Before.class)){/*取得被Annotation标注的方法*/ methodBefore = method0; System.out.println("method name is "+method0.getName()); } } if(null != methodBefore){ methodBefore.invoke(this.target); result = method.invoke(this.target, args); } return result; } }
步骤5:声明一个Annotation接口
package com.interceptor; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Before { }
所以准备工作做好现在该测试了。
测试
步骤1: 首先,给需要代理的类定义一个接口Service
package com.interceptor; public interface Service { public String greet(String name); }
步骤2: 实现这个接口,并使用Annotation,编写类ServiceImpl
package com.interceptor; public class ServiceImpl implements Service { @Before public void sayHello(){ System.out.print("java say: Hello,"); } public String greet(String name) { String result = name; System.out.println(result); return result; } }
步骤3: 实现拦截器接口Interceptor,编写类InterceptorImpl(该步骤暂不使用)
步骤4:编写测试类TestDynamicProxy
package com.interceptor; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.util.HashSet; import java.util.Set; import com.opensymphony.xwork2.interceptor.annotations.Before; public class TestDynamicProxy { public TestDynamicProxy() { DynamicProxyFactory dynamicProxyFactory = new DynamicProxyFactoryImpl(); Service service = new ServiceImpl(); Interceptor interceptor = null;//Interceptor暂不使用 Service proxy = dynamicProxyFactory.createProxy(service, interceptor); proxy.greet(" daniel"); System.out.println("\n------打印service的Annotation:---------"); printAnnotation(service); System.out.println("\n------打印 proxy 的Annotation:-----------"); printAnnotation(proxy); System.out.println(">>>>>>>>>>>TestDynamicProxy end"); } public void printAnnotation(Object object){ Class interfaces = object.getClass(); Method[] method = interfaces.getMethods(); Set<Method> set = new HashSet<Method>(); for (int i = 0; i < method.length; i++) { Annotation an[] = method[i].getAnnotations(); for(Annotation a:an){ System.out.println("方法 "+method[i].getName()+" 的Annotation标注为 "+a.toString()); } } } public static void main(String[] args) { new TestDynamicProxy(); } }
测试结果为:
method name is sayHello
java say: Hello, daniel
------打印service的Annotation:---------
方法 sayHello 的Annotation标注为 @com.interceptor.Before()
------打印 proxy 的Annotation:-----------
>>>>>>>>>>>TestDynamicProxy end
从结果我们可以看出service经过proxy后Annotation已经不存在了。
打开proxy.java的源码从getProxyClass(ClassLoader loader, Class<?>... interfaces)方法中的
byte[] proxyClassFile = ProxyGenerator.generateProxyClass( proxyName, interfaces); try { proxyClass = defineClass0(loader, proxyName, proxyClassFile, 0, proxyClassFile.length); } catch (ClassFormatError e) {
代码知道,ProxyGenerator.generateProxyClass方法产生了一个字节数组,反编译ProxyGenerator从一下的两个重要方法
private byte[] generateClassFile() { addProxyMethod(hashCodeMethod, java/lang/Object); addProxyMethod(equalsMethod, java/lang/Object); addProxyMethod(toStringMethod, java/lang/Object); for(int i = 0; i < interfaces.length; i++) { Method amethod[] = interfaces[i].getMethods(); for(int k = 0; k < amethod.length; k++) addProxyMethod(amethod[k], interfaces[i]); } List list; for(Iterator iterator = proxyMethods.values().iterator(); iterator.hasNext(); checkReturnTypes(list)) list = (List)iterator.next(); try { methods.add(generateConstructor()); for(Iterator iterator1 = proxyMethods.values().iterator(); iterator1.hasNext();) { List list1 = (List)iterator1.next(); Iterator iterator2 = list1.iterator(); while(iterator2.hasNext()) { ProxyMethod proxymethod = (ProxyMethod)iterator2.next(); fields.add(new FieldInfo(proxymethod.methodFieldName, "Ljava/lang/reflect/Method;", 10)); methods.add(proxymethod.generateMethod()); } } methods.add(generateStaticInitializer()); } catch(IOException ioexception) { throw new InternalError("unexpected I/O Exception"); } if(methods.size() > 65535) throw new IllegalArgumentException("method limit exceeded"); if(fields.size() > 65535) throw new IllegalArgumentException("field limit exceeded"); cp.getClass(dotToSlash(className)); cp.getClass("java/lang/reflect/Proxy"); for(int j = 0; j < interfaces.length; j++) cp.getClass(dotToSlash(interfaces[j].getName())); cp.setReadOnly(); ByteArrayOutputStream bytearrayoutputstream = new ByteArrayOutputStream(); DataOutputStream dataoutputstream = new DataOutputStream(bytearrayoutputstream); try { dataoutputstream.writeInt(0xcafebabe); dataoutputstream.writeShort(0); dataoutputstream.writeShort(49); cp.write(dataoutputstream); dataoutputstream.writeShort(49); dataoutputstream.writeShort(cp.getClass(dotToSlash(className))); dataoutputstream.writeShort(cp.getClass("java/lang/reflect/Proxy")); dataoutputstream.writeShort(interfaces.length); for(int l = 0; l < interfaces.length; l++) dataoutputstream.writeShort(cp.getClass(dotToSlash(interfaces[l].getName()))); dataoutputstream.writeShort(fields.size()); FieldInfo fieldinfo; for(Iterator iterator3 = fields.iterator(); iterator3.hasNext(); fieldinfo.write(dataoutputstream)) fieldinfo = (FieldInfo)iterator3.next(); dataoutputstream.writeShort(methods.size()); MethodInfo methodinfo; for(Iterator iterator4 = methods.iterator(); iterator4.hasNext(); methodinfo.write(dataoutputstream)) methodinfo = (MethodInfo)iterator4.next(); dataoutputstream.writeShort(0); } catch(IOException ioexception1) { throw new InternalError("unexpected I/O Exception"); } return bytearrayoutputstream.toByteArray(); } private void addProxyMethod(Method method, Class class1) { String s; Class aclass[]; Class class2; Class aclass1[]; Object obj; label0: { s = method.getName(); aclass = method.getParameterTypes(); class2 = method.getReturnType(); aclass1 = method.getExceptionTypes(); String s1 = (new StringBuilder()).append(s).append(getParameterDescriptors(aclass)).toString(); obj = (List)proxyMethods.get(s1); if(obj != null) { Iterator iterator = ((List) (obj)).iterator(); ProxyMethod proxymethod; do { if(!iterator.hasNext()) break label0; proxymethod = (ProxyMethod)iterator.next(); } while(class2 != proxymethod.returnType); ArrayList arraylist = new ArrayList(); collectCompatibleTypes(aclass1, proxymethod.exceptionTypes, arraylist); collectCompatibleTypes(proxymethod.exceptionTypes, aclass1, arraylist); proxymethod.exceptionTypes = new Class[arraylist.size()]; proxymethod.exceptionTypes = (Class[])arraylist.toArray(proxymethod.exceptionTypes); return; } obj = new ArrayList(3); proxyMethods.put(s1, obj); } ((List) (obj)).add(new ProxyMethod(s, aclass, class2, aclass1, class1)); }
其中并没有发现对Annotation的处理,看来是把Annotation给忽略吧。
相关推荐
它通过Action类处理业务逻辑,使用拦截器(Interceptor)来实现如日志、权限验证等功能,并将结果转发到JSP或其他视图组件。 Hibernate3则是一个对象关系映射(ORM)框架,用于处理数据库操作。它简化了Java应用与...
本文将详细解析"Struts2+Spring2+Hibernate3 Annotation的整合"这一主题,主要涵盖以下几个方面: 1. **Struts2框架**:Struts2是一个基于MVC设计模式的Web应用框架,用于简化Java Web应用程序的开发。它的主要功能...
同时,Struts2的拦截器(Interceptor)可以与Spring的AOP相结合,增强Action执行前后的逻辑处理。 Hibernate作为ORM(对象关系映射)框架,负责数据库的CRUD操作。在整合Spring后,SessionFactory和Session可以通过...
- **Struts 2的特性**:Struts 2具有丰富的拦截器库,强大的OGNL表达式语言,强大的国际化和异常处理机制,以及灵活的模板引擎。 - **与Spring的配合**:通过Spring插件,Struts 2可以利用Spring的依赖注入来创建...
### Struts2+Spring2+Hibernate3+Annotation所需JAR包详解 在Java Web开发领域,Struts2、Spring2和Hibernate3是三个非常重要的框架,它们分别负责Web层、业务逻辑层和服务持久化层的功能实现。为了更好地整合这三...
4. **Struts2配置**:配置struts.xml文件,定义Action和结果视图,可能还需要配置拦截器。 5. **Hibernate配置**:配置hibernate.cfg.xml,包括数据库连接信息,以及启用注解实体扫描。 6. **实体类和DAO**:使用...
Struts2提供了一种可扩展的拦截器机制,使得开发者可以通过配置或注解来处理请求,实现灵活的控制流。此外,它还集成了Freemarker和JSP作为视图技术,增强了模板渲染能力。 **Spring** 框架则是一个全面的企业级...
总结起来,"Struts2+Hibernate3.5+Spring3.0(Annotation)"的组合为Java Web开发提供了一个强大的基础架构,尤其在权限管理方面。通过合理的配置和使用注解,可以实现高效、灵活且易于维护的权限控制系统。这不仅...
Struts2提供了丰富的拦截器(Interceptor)机制,能够方便地实现AOP(面向切面编程),如日志记录、权限验证等。此外,Struts2支持OGNL(Object-Graph Navigation Language)表达式,使得视图层与模型层的交互更加...
在IT行业中,Spring和Struts2是两个非常重要的Java Web框架。它们的整合可以构建出高效、可维护的Web应用程序。下面将详细讲解Spring与Struts2整合的关键知识点。 首先,Spring是一个轻量级的全面应用程序框架,它...
此外,Struts 2的拦截器(Interceptor)机制配合Spring的AOP可以实现更灵活的业务逻辑控制。 DWR(Direct Web Remoting)3 是一个JavaScript到Java的远程调用库,使得前端JavaScript能够直接调用后端Java方法,实现...
在这个2.1.8版本中,Struts 2提供了丰富的拦截器和插件机制,支持动态方法调用,增强了表单验证和国际化处理,使得视图与控制逻辑分离,提高了代码的可维护性。 3. **Hibernate 3**: Hibernate是一个对象关系映射...
Struts2.18是该框架的一个稳定版本,它提供了强大的表单处理、拦截器机制、国际化支持和丰富的动作与结果类型。Struts2通过Action类处理请求,将业务逻辑与视图分离,增强了可维护性和可扩展性。 **Hibernate** 是...
在IT行业中,Web应用程序开发是核心领域之一,而Spring、Struts2和Direct Web Remoting (DWR) 是其中常见的三大框架。它们分别扮演着不同的角色,以提高开发效率和提供更好的用户体验。本文将深入探讨如何将这三者...
Struts2的核心是拦截器,通过配置拦截器栈,可以实现各种业务逻辑,如表单验证、文件上传下载等。在这个示例中,Struts2负责处理HTTP请求,转发到相应的Action,执行业务逻辑,并将结果返回给用户界面。 **Spring**...
2. **配置Struts2**:在struts2的核心配置文件`struts.xml`中定义Action及其对应的Result,设置Struts2拦截器,比如Spring插件的拦截器,使得Struts2能够与Spring集成。 3. **配置Spring**:创建Spring的配置文件,...