浏览 6888 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2009-02-19
第一种情况使用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给忽略吧。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |