1 /* 2 * Copyright 2002-2007 the original author or authors. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package org.springframework.aop.framework; 18 19 import static org.easymock.EasyMock.createMock; 20 import static org.easymock.EasyMock.expect; 21 import static org.easymock.EasyMock.replay; 22 import static org.easymock.EasyMock.verify; 23 import static org.junit.Assert.*; 24 25 import java.io.Serializable; 26 27 import org.aopalliance.intercept.MethodInterceptor; 28 import org.aopalliance.intercept.MethodInvocation; 29 30 import org.springframework.aop.interceptor.ExposeInvocationInterceptor; 31 import org.springframework.aop.support.AopUtils; 32 import org.springframework.beans.IOther; 33 import org.springframework.beans.ITestBean; 34 import org.springframework.beans.TestBean; 35 36 /** 37 * @since 13.03.2003 38 * @author Rod Johnson 39 * @author Juergen Hoeller 40 * @author Chris Beams 41 */ 42 @SuppressWarnings("serial") 43 public final class JdkDynamicProxyTests extends AbstractAopProxyTests implements Serializable { 44 createProxy(ProxyCreatorSupport as)45 protected Object createProxy(ProxyCreatorSupport as) { 46 assertFalse("Not forcible CGLIB", as.isProxyTargetClass()); 47 Object proxy = as.createAopProxy().getProxy(); 48 assertTrue("Should be a JDK proxy: " + proxy.getClass(), AopUtils.isJdkDynamicProxy(proxy)); 49 return proxy; 50 } 51 createAopProxy(AdvisedSupport as)52 protected AopProxy createAopProxy(AdvisedSupport as) { 53 return new JdkDynamicAopProxy(as); 54 } 55 testNullConfig()56 public void testNullConfig() { 57 try { 58 new JdkDynamicAopProxy(null); 59 fail("Shouldn't allow null interceptors"); 60 } 61 catch (IllegalArgumentException ex) { 62 // Ok 63 } 64 } 65 testProxyIsJustInterface()66 public void testProxyIsJustInterface() throws Throwable { 67 TestBean raw = new TestBean(); 68 raw.setAge(32); 69 AdvisedSupport pc = new AdvisedSupport(new Class[] {ITestBean.class}); 70 pc.setTarget(raw); 71 JdkDynamicAopProxy aop = new JdkDynamicAopProxy(pc); 72 73 Object proxy = aop.getProxy(); 74 assertTrue(proxy instanceof ITestBean); 75 assertTrue(!(proxy instanceof TestBean)); 76 } 77 testInterceptorIsInvokedWithNoTarget()78 public void testInterceptorIsInvokedWithNoTarget() throws Throwable { 79 // Test return value 80 int age = 25; 81 MethodInterceptor mi = createMock(MethodInterceptor.class); 82 83 AdvisedSupport pc = new AdvisedSupport(new Class[] { ITestBean.class }); 84 pc.addAdvice(mi); 85 AopProxy aop = createAopProxy(pc); 86 87 expect(mi.invoke(null)).andReturn(age); 88 replay(mi); 89 90 ITestBean tb = (ITestBean) aop.getProxy(); 91 assertTrue("correct return value", tb.getAge() == age); 92 verify(mi); 93 } 94 testTargetCanGetInvocationWithPrivateClass()95 public void testTargetCanGetInvocationWithPrivateClass() throws Throwable { 96 final ExposedInvocationTestBean expectedTarget = new ExposedInvocationTestBean() { 97 protected void assertions(MethodInvocation invocation) { 98 assertTrue(invocation.getThis() == this); 99 assertTrue("Invocation should be on ITestBean: " + invocation.getMethod(), 100 invocation.getMethod().getDeclaringClass() == ITestBean.class); 101 } 102 }; 103 104 AdvisedSupport pc = new AdvisedSupport(new Class[] { ITestBean.class, IOther.class }); 105 pc.addAdvice(ExposeInvocationInterceptor.INSTANCE); 106 TrapTargetInterceptor tii = new TrapTargetInterceptor() { 107 public Object invoke(MethodInvocation invocation) throws Throwable { 108 // Assert that target matches BEFORE invocation returns 109 assertEquals("Target is correct", expectedTarget, invocation.getThis()); 110 return super.invoke(invocation); 111 } 112 }; 113 pc.addAdvice(tii); 114 pc.setTarget(expectedTarget); 115 AopProxy aop = createAopProxy(pc); 116 117 ITestBean tb = (ITestBean) aop.getProxy(); 118 tb.getName(); 119 // Not safe to trap invocation 120 //assertTrue(tii.invocation == target.invocation); 121 122 //assertTrue(target.invocation.getProxy() == tb); 123 124 // ((IOther) tb).absquatulate(); 125 //MethodInvocation minv = tii.invocation; 126 //assertTrue("invoked on iother, not " + minv.getMethod().getDeclaringClass(), minv.getMethod().getDeclaringClass() == IOther.class); 127 //assertTrue(target.invocation == tii.invocation); 128 } 129 testProxyNotWrappedIfIncompatible()130 public void testProxyNotWrappedIfIncompatible() { 131 FooBar bean = new FooBar(); 132 ProxyCreatorSupport as = new ProxyCreatorSupport(); 133 as.setInterfaces(new Class[] {Foo.class}); 134 as.setTarget(bean); 135 136 Foo proxy = (Foo) createProxy(as); 137 assertSame("Target should be returned when return types are incompatible", bean, proxy.getBarThis()); 138 assertSame("Proxy should be returned when return types are compatible", proxy, proxy.getFooThis()); 139 140 } 141 testEqualsAndHashCodeDefined()142 public void testEqualsAndHashCodeDefined() throws Exception { 143 AdvisedSupport as = new AdvisedSupport(new Class[]{Named.class}); 144 as.setTarget(new Person()); 145 JdkDynamicAopProxy aopProxy = new JdkDynamicAopProxy(as); 146 Named proxy = (Named) aopProxy.getProxy(); 147 Named named = new Person(); 148 assertEquals("equals() returned false", proxy, named); 149 assertEquals("hashCode() not equal", proxy.hashCode(), named.hashCode()); 150 } 151 152 153 public static interface Foo { 154 getBarThis()155 Bar getBarThis(); 156 getFooThis()157 Foo getFooThis(); 158 } 159 160 161 public static interface Bar { 162 163 } 164 165 166 public static class FooBar implements Foo, Bar { 167 getBarThis()168 public Bar getBarThis() { 169 return this; 170 } 171 getFooThis()172 public Foo getFooThis() { 173 return this; 174 } 175 } 176 177 178 public static interface Named { 179 getName()180 String getName(); 181 equals(Object other)182 boolean equals(Object other); 183 hashCode()184 int hashCode(); 185 } 186 187 188 public static class Person implements Named { 189 190 private final String name = "Rob Harrop"; 191 getName()192 public String getName() { 193 return this.name; 194 } 195 equals(Object o)196 public boolean equals(Object o) { 197 if (this == o) return true; 198 if (o == null || getClass() != o.getClass()) return false; 199 200 final Person person = (Person) o; 201 202 if (!name.equals(person.name)) return false; 203 204 return true; 205 } 206 hashCode()207 public int hashCode() { 208 return name.hashCode(); 209 } 210 } 211 212 } 213