/* * Copyright 2004-2015 the Seasar Foundation and the Others. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. See the License for the specific language * governing permissions and limitations under the License. */ package org.seasar.framework.aop.proxy; import java.io.Serializable; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.math.BigDecimal; import java.util.Date; import java.util.Iterator; import junit.framework.TestCase; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; import org.seasar.framework.aop.Aspect; import org.seasar.framework.aop.Pointcut; import org.seasar.framework.aop.impl.AspectImpl; import org.seasar.framework.aop.impl.PointcutImpl; import org.seasar.framework.aop.interceptors.TraceInterceptor; import org.seasar.framework.util.ClassUtil; import org.seasar.framework.util.MethodUtil; import org.seasar.framework.util.SerializeUtil; /** * @author higa * */ public class AopProxyTest extends TestCase { /** * @throws Exception */ public void testIntercept() throws Exception { TestInvocation invocation = new TestInvocation(); Pointcut pointcut = new PointcutImpl(new String[] { "getTime" }); Aspect aspect = new AspectImpl(invocation, pointcut); AopProxy aopProxy = new AopProxy(Date.class, new Aspect[] { aspect }); Date proxy = (Date) aopProxy.create(); System.out.println(proxy.getTime()); assertEquals("2", true, invocation.invoked_); } /** * @throws Exception */ public void testInterface() throws Exception { Pointcut pointcut = new PointcutImpl(new String[] { "greeting" }); Aspect aspect = new AspectImpl(new HelloInterceptor(), pointcut); AopProxy aopProxy = new AopProxy(Hello.class, new Aspect[] { aspect }); Hello proxy = (Hello) aopProxy.create(); assertEquals("1", "Hello", proxy.greeting()); } /** * @throws Exception */ public void testCreateForArgs() throws Exception { Aspect aspect = new AspectImpl(new TraceInterceptor()); AopProxy aopProxy = new AopProxy(HelloImpl.class, new Aspect[] { aspect }); Hello proxy = (Hello) aopProxy.create(new Class[] { String.class }, new Object[] { "Hello" }); assertEquals("1", "Hello", proxy.greeting()); System.out.println(proxy.hashCode()); } /** * @throws Exception */ public void testEquals() throws Exception { Pointcut pointcut = new PointcutImpl(new String[] { "greeting" }); Aspect aspect = new AspectImpl(new HelloInterceptor(), pointcut); AopProxy aopProxy = new AopProxy(Hello.class, new Aspect[] { aspect }); Hello proxy = (Hello) aopProxy.create(); assertEquals("1", true, proxy.equals(proxy)); assertEquals("2", false, proxy.equals(null)); assertEquals("3", false, proxy.equals("hoge")); } /** * */ public void testEqualsByValue() { Pointcut pointcut = new PointcutImpl(new String[] { "toString" }); Aspect aspect = new AspectImpl(new HelloInterceptor(), pointcut); AopProxy aopProxy = new AopProxy(BigDecimal.class, new Aspect[] { aspect }); BigDecimal proxy = (BigDecimal) aopProxy.create( new Class[] { String.class }, new Object[] { "10" }); assertTrue("1", proxy.equals(proxy)); assertTrue("2", proxy.equals(new BigDecimal("10"))); assertFalse("3", proxy.equals(null)); assertFalse("3", proxy.equals(new BigDecimal("100"))); assertFalse("3", proxy.equals("Hoge")); } /** * @throws Exception */ public void testFinalMethod() throws Exception { Pointcut pointcut = new PointcutImpl(new String[] { "greeting" }); Aspect aspect = new AspectImpl(new HelloInterceptor(), pointcut); AopProxy aopProxy = new AopProxy(HelloImpl3.class, new Aspect[] { aspect }); Hello proxy = (Hello) aopProxy.create(); assertEquals("1", "hoge", proxy.greeting()); } /** * Java8で追加されたデフォルトメソッドに対するインターセプタのテスト * * @throws Exception */ public void testDefaultMethod() throws Exception { if (!MethodUtil.isDefaultMethod(ClassUtil.getMethod(Iterator.class, "remove", null))) { // Java7以前はスキップ return; } System.out.println("before default test"); try { Aspect aspect = new AspectImpl(new TraceInterceptor()); AopProxy aopProxy = new AopProxy(Iterator.class, new Aspect[] { aspect }); Iterator proxy = (Iterator) aopProxy.create(); proxy.remove(); } catch (UnsupportedOperationException expected) { } catch (Throwable e) { e.printStackTrace(); } } /** * @throws Exception */ public void testSerialize() throws Exception { Aspect aspect = new AspectImpl(new TraceInterceptor()); AopProxy aopProxy = new AopProxy(HelloImpl.class, new Aspect[] { aspect }); Hello proxy = (Hello) aopProxy.create(new Class[] { String.class }, new Object[] { "Hello" }); Hello copy = (Hello) SerializeUtil.serialize(proxy); assertEquals("1", "Hello", copy.greeting()); } /** * @throws Exception */ public void testPerformance() throws Exception { Date target = new Date(); Pointcut pointcut = new PointcutImpl(new String[] { "compareTo" }); Aspect aspect = new AspectImpl(new TestInvocation(), pointcut); AopProxy aopProxy = new AopProxy(Date.class, new Aspect[] { aspect }); Date proxy = (Date) aopProxy.create(); MyInvocationHandler handler = new MyInvocationHandler(target); Comparable proxy2 = (Comparable) Proxy.newProxyInstance(Date.class .getClassLoader(), new Class[] { Comparable.class }, handler); final int num = 2000000; long start = System.currentTimeMillis(); for (int i = 0; i < num; ++i) { // target.hashCode(); target.compareTo(target); } System.out.println("target:" + (System.currentTimeMillis() - start)); start = System.currentTimeMillis(); for (int i = 0; i < num; ++i) { // proxy.hashCode(); proxy.compareTo(target); } System.out.println("AOP proxy:" + (System.currentTimeMillis() - start)); start = System.currentTimeMillis(); for (int i = 0; i < num; ++i) { // proxy.hashCode(); proxy2.compareTo(target); } System.out.println("JDK proxy:" + (System.currentTimeMillis() - start)); } /** * */ public class TestInvocation implements MethodInterceptor { private boolean invoked_ = false; public Object invoke(MethodInvocation invocation) throws Throwable { invoked_ = true; return invocation.proceed(); } } /** * */ public class MyInvocation implements MethodInterceptor { public Object invoke(MethodInvocation invocation) throws Throwable { return invocation.proceed(); } } /** * */ public interface Hello extends Serializable { /** * @return */ public String greeting(); } /** * */ public static class HelloImpl implements Hello { private static final long serialVersionUID = -6888891433122734807L; private String str_; /** * @param str */ public HelloImpl(String str) { str_ = str; } public String greeting() { return str_; } } /** * */ public static class Hello2Impl implements Hello { private static final long serialVersionUID = -7275896388662514561L; public String greeting() { return "Hello2"; } } /** * */ public static class HelloImpl3 implements Hello { private static final long serialVersionUID = 5992242320294594184L; public final String greeting() { return "hoge"; } } /** * */ public class HelloInterceptor implements MethodInterceptor { public Object invoke(MethodInvocation invocation) throws Throwable { return "Hello"; } } /** * */ public static class MyInvocationHandler implements InvocationHandler { private Object target; /** * @param target */ public MyInvocationHandler(Object target) { this.target = target; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { return method.invoke(target, args); } } }