`
daniel_ic
  • 浏览: 2507 次
  • 性别: Icon_minigender_1
  • 来自: 成都
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

关于Spring Aop 覆盖struts2 的Annotation 拦截器

阅读更多
当自学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
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给忽略吧。
分享到:
评论

相关推荐

    struts2 hibernate3 spring2.5 annotation 整合

    它通过Action类处理业务逻辑,使用拦截器(Interceptor)来实现如日志、权限验证等功能,并将结果转发到JSP或其他视图组件。 Hibernate3则是一个对象关系映射(ORM)框架,用于处理数据库操作。它简化了Java应用与...

    struts2+spring2+hibernate3 Annotation的整合

    本文将详细解析"Struts2+Spring2+Hibernate3 Annotation的整合"这一主题,主要涵盖以下几个方面: 1. **Struts2框架**:Struts2是一个基于MVC设计模式的Web应用框架,用于简化Java Web应用程序的开发。它的主要功能...

    Struts2 Spring Hibernate 框架整合 Annotation Maven project.zip

    同时,Struts2的拦截器(Interceptor)可以与Spring的AOP相结合,增强Action执行前后的逻辑处理。 Hibernate作为ORM(对象关系映射)框架,负责数据库的CRUD操作。在整合Spring后,SessionFactory和Session可以通过...

    mybatis3+spring4+struts2.3整合jar

    - **Struts 2的特性**:Struts 2具有丰富的拦截器库,强大的OGNL表达式语言,强大的国际化和异常处理机制,以及灵活的模板引擎。 - **与Spring的配合**:通过Spring插件,Struts 2可以利用Spring的依赖注入来创建...

    Struts2+Spring2+Hibernate3+Annotation所需JAR包

    ### Struts2+Spring2+Hibernate3+Annotation所需JAR包详解 在Java Web开发领域,Struts2、Spring2和Hibernate3是三个非常重要的框架,它们分别负责Web层、业务逻辑层和服务持久化层的功能实现。为了更好地整合这三...

    Struts2+Spring2.5+Hibernate3+annotation 整合程序

    4. **Struts2配置**:配置struts.xml文件,定义Action和结果视图,可能还需要配置拦截器。 5. **Hibernate配置**:配置hibernate.cfg.xml,包括数据库连接信息,以及启用注解实体扫描。 6. **实体类和DAO**:使用...

    Struts2 Spring Hibernate 框架整合 Annotation Maven project

    Struts2提供了一种可扩展的拦截器机制,使得开发者可以通过配置或注解来处理请求,实现灵活的控制流。此外,它还集成了Freemarker和JSP作为视图技术,增强了模板渲染能力。 **Spring** 框架则是一个全面的企业级...

    权限管理 struts2 hiberante3.5 spring3.0 annotation

    总结起来,"Struts2+Hibernate3.5+Spring3.0(Annotation)"的组合为Java Web开发提供了一个强大的基础架构,尤其在权限管理方面。通过合理的配置和使用注解,可以实现高效、灵活且易于维护的权限控制系统。这不仅...

    Struts2+Spring+Mybaits3框架整合实例

    Struts2提供了丰富的拦截器(Interceptor)机制,能够方便地实现AOP(面向切面编程),如日志记录、权限验证等。此外,Struts2支持OGNL(Object-Graph Navigation Language)表达式,使得视图层与模型层的交互更加...

    Spring/Struts2整合项目

    在IT行业中,Spring和Struts2是两个非常重要的Java Web框架。它们的整合可以构建出高效、可维护的Web应用程序。下面将详细讲解Spring与Struts2整合的关键知识点。 首先,Spring是一个轻量级的全面应用程序框架,它...

    spring2.5 ibatis2.3 struts2.1 dwr3 annotation集成配置

    此外,Struts 2的拦截器(Interceptor)机制配合Spring的AOP可以实现更灵活的业务逻辑控制。 DWR(Direct Web Remoting)3 是一个JavaScript到Java的远程调用库,使得前端JavaScript能够直接调用后端Java方法,实现...

    spring3.2+struts2+hiber3框架配置

    在这个2.1.8版本中,Struts 2提供了丰富的拦截器和插件机制,支持动态方法调用,增强了表单验证和国际化处理,使得视图与控制逻辑分离,提高了代码的可维护性。 3. **Hibernate 3**: Hibernate是一个对象关系映射...

    struts2+hibernate+annotation+spring整合的jar包

    Struts2.18是该框架的一个稳定版本,它提供了强大的表单处理、拦截器机制、国际化支持和丰富的动作与结果类型。Struts2通过Action类处理请求,将业务逻辑与视图分离,增强了可维护性和可扩展性。 **Hibernate** 是...

    dwr和spring和struts2整合

    在IT行业中,Web应用程序开发是核心领域之一,而Spring、Struts2和Direct Web Remoting (DWR) 是其中常见的三大框架。它们分别扮演着不同的角色,以提高开发效率和提供更好的用户体验。本文将深入探讨如何将这三者...

    struts2+spring+hibernate示例

    Struts2的核心是拦截器,通过配置拦截器栈,可以实现各种业务逻辑,如表单验证、文件上传下载等。在这个示例中,Struts2负责处理HTTP请求,转发到相应的Action,执行业务逻辑,并将结果返回给用户界面。 **Spring**...

    整合struts2-spring-MyBatis

    2. **配置Struts2**:在struts2的核心配置文件`struts.xml`中定义Action及其对应的Result,设置Struts2拦截器,比如Spring插件的拦截器,使得Struts2能够与Spring集成。 3. **配置Spring**:创建Spring的配置文件,...

Global site tag (gtag.js) - Google Analytics