View Javadoc
1   /*
2    * Copyright 2002-2014 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.autoproxy;
18  
19  import java.io.Serializable;
20  import java.lang.reflect.Proxy;
21  
22  import org.aopalliance.intercept.MethodInterceptor;
23  import org.aopalliance.intercept.MethodInvocation;
24  import org.junit.Test;
25  
26  import org.springframework.aop.TargetSource;
27  import org.springframework.aop.support.AopUtils;
28  import org.springframework.beans.MutablePropertyValues;
29  import org.springframework.beans.factory.BeanFactory;
30  import org.springframework.beans.factory.BeanFactoryAware;
31  import org.springframework.beans.factory.DisposableBean;
32  import org.springframework.beans.factory.FactoryBean;
33  import org.springframework.beans.factory.InitializingBean;
34  import org.springframework.beans.factory.config.BeanDefinitionHolder;
35  import org.springframework.beans.factory.support.RootBeanDefinition;
36  import org.springframework.context.ApplicationContext;
37  import org.springframework.context.ApplicationContextAware;
38  import org.springframework.context.MessageSource;
39  import org.springframework.context.support.StaticApplicationContext;
40  import org.springframework.context.support.StaticMessageSource;
41  import org.springframework.tests.sample.beans.ITestBean;
42  import org.springframework.tests.sample.beans.IndexedTestBean;
43  import org.springframework.tests.sample.beans.TestBean;
44  import org.springframework.tests.sample.beans.factory.DummyFactory;
45  
46  import static org.junit.Assert.*;
47  
48  /**
49   * @author Juergen Hoeller
50   * @author Chris Beams
51   * @since 09.12.2003
52   */
53  @SuppressWarnings("resource")
54  public final class AutoProxyCreatorTests {
55  
56  	@Test
57  	public void testBeanNameAutoProxyCreator() {
58  		StaticApplicationContext sac = new StaticApplicationContext();
59  		sac.registerSingleton("testInterceptor", TestInterceptor.class);
60  
61  		RootBeanDefinition proxyCreator = new RootBeanDefinition(BeanNameAutoProxyCreator.class);
62  		proxyCreator.getPropertyValues().add("interceptorNames", "testInterceptor");
63  		proxyCreator.getPropertyValues().add("beanNames", "singletonToBeProxied,innerBean,singletonFactoryToBeProxied");
64  		sac.getDefaultListableBeanFactory().registerBeanDefinition("beanNameAutoProxyCreator", proxyCreator);
65  
66  		RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
67  		bd.setAutowireMode(RootBeanDefinition.AUTOWIRE_BY_TYPE);
68  		RootBeanDefinition innerBean = new RootBeanDefinition(TestBean.class);
69  		bd.getPropertyValues().add("spouse", new BeanDefinitionHolder(innerBean, "innerBean"));
70  		sac.getDefaultListableBeanFactory().registerBeanDefinition("singletonToBeProxied", bd);
71  
72  		sac.registerSingleton("singletonFactoryToBeProxied", DummyFactory.class);
73  		sac.registerSingleton("autowiredIndexedTestBean", IndexedTestBean.class);
74  
75  		sac.refresh();
76  
77  		MessageSource messageSource = (MessageSource) sac.getBean("messageSource");
78  		ITestBean singletonToBeProxied = (ITestBean) sac.getBean("singletonToBeProxied");
79  		assertFalse(Proxy.isProxyClass(messageSource.getClass()));
80  		assertTrue(Proxy.isProxyClass(singletonToBeProxied.getClass()));
81  		assertTrue(Proxy.isProxyClass(singletonToBeProxied.getSpouse().getClass()));
82  
83  		// test whether autowiring succeeded with auto proxy creation
84  		assertEquals(sac.getBean("autowiredIndexedTestBean"), singletonToBeProxied.getNestedIndexedBean());
85  
86  		TestInterceptor ti = (TestInterceptor) sac.getBean("testInterceptor");
87  		// already 2: getSpouse + getNestedIndexedBean calls above
88  		assertEquals(2, ti.nrOfInvocations);
89  		singletonToBeProxied.getName();
90  		singletonToBeProxied.getSpouse().getName();
91  		assertEquals(5, ti.nrOfInvocations);
92  
93  		ITestBean tb = (ITestBean) sac.getBean("singletonFactoryToBeProxied");
94  		assertTrue(AopUtils.isJdkDynamicProxy(tb));
95  		assertEquals(5, ti.nrOfInvocations);
96  		tb.getAge();
97  		assertEquals(6, ti.nrOfInvocations);
98  
99  		ITestBean tb2 = (ITestBean) sac.getBean("singletonFactoryToBeProxied");
100 		assertSame(tb, tb2);
101 		assertEquals(6, ti.nrOfInvocations);
102 		tb2.getAge();
103 		assertEquals(7, ti.nrOfInvocations);
104 	}
105 
106 	@Test
107 	public void testBeanNameAutoProxyCreatorWithFactoryBeanProxy() {
108 		StaticApplicationContext sac = new StaticApplicationContext();
109 		sac.registerSingleton("testInterceptor", TestInterceptor.class);
110 
111 		RootBeanDefinition proxyCreator = new RootBeanDefinition(BeanNameAutoProxyCreator.class);
112 		proxyCreator.getPropertyValues().add("interceptorNames", "testInterceptor");
113 		proxyCreator.getPropertyValues().add("beanNames", "singletonToBeProxied,&singletonFactoryToBeProxied");
114 		sac.getDefaultListableBeanFactory().registerBeanDefinition("beanNameAutoProxyCreator", proxyCreator);
115 
116 		RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
117 		sac.getDefaultListableBeanFactory().registerBeanDefinition("singletonToBeProxied", bd);
118 
119 		sac.registerSingleton("singletonFactoryToBeProxied", DummyFactory.class);
120 
121 		sac.refresh();
122 
123 		ITestBean singletonToBeProxied = (ITestBean) sac.getBean("singletonToBeProxied");
124 		assertTrue(Proxy.isProxyClass(singletonToBeProxied.getClass()));
125 
126 		TestInterceptor ti = (TestInterceptor) sac.getBean("testInterceptor");
127 		int initialNr = ti.nrOfInvocations;
128 		singletonToBeProxied.getName();
129 		assertEquals(initialNr + 1, ti.nrOfInvocations);
130 
131 		FactoryBean<?> factory = (FactoryBean<?>) sac.getBean("&singletonFactoryToBeProxied");
132 		assertTrue(Proxy.isProxyClass(factory.getClass()));
133 		TestBean tb = (TestBean) sac.getBean("singletonFactoryToBeProxied");
134 		assertFalse(AopUtils.isAopProxy(tb));
135 		assertEquals(initialNr + 3, ti.nrOfInvocations);
136 		tb.getAge();
137 		assertEquals(initialNr + 3, ti.nrOfInvocations);
138 	}
139 
140 	@Test
141 	public void testCustomAutoProxyCreator() {
142 		StaticApplicationContext sac = new StaticApplicationContext();
143 		sac.registerSingleton("testAutoProxyCreator", TestAutoProxyCreator.class);
144 		sac.registerSingleton("noInterfaces", NoInterfaces.class);
145 		sac.registerSingleton("containerCallbackInterfacesOnly", ContainerCallbackInterfacesOnly.class);
146 		sac.registerSingleton("singletonNoInterceptor", TestBean.class);
147 		sac.registerSingleton("singletonToBeProxied", TestBean.class);
148 		sac.registerPrototype("prototypeToBeProxied", TestBean.class);
149 		sac.refresh();
150 
151 		MessageSource messageSource = (MessageSource) sac.getBean("messageSource");
152 		NoInterfaces noInterfaces = (NoInterfaces) sac.getBean("noInterfaces");
153 		ContainerCallbackInterfacesOnly containerCallbackInterfacesOnly =
154 				(ContainerCallbackInterfacesOnly) sac.getBean("containerCallbackInterfacesOnly");
155 		ITestBean singletonNoInterceptor = (ITestBean) sac.getBean("singletonNoInterceptor");
156 		ITestBean singletonToBeProxied = (ITestBean) sac.getBean("singletonToBeProxied");
157 		ITestBean prototypeToBeProxied = (ITestBean) sac.getBean("prototypeToBeProxied");
158 		assertFalse(AopUtils.isCglibProxy(messageSource));
159 		assertTrue(AopUtils.isCglibProxy(noInterfaces));
160 		assertTrue(AopUtils.isCglibProxy(containerCallbackInterfacesOnly));
161 		assertTrue(AopUtils.isCglibProxy(singletonNoInterceptor));
162 		assertTrue(AopUtils.isCglibProxy(singletonToBeProxied));
163 		assertTrue(AopUtils.isCglibProxy(prototypeToBeProxied));
164 
165 		TestAutoProxyCreator tapc = (TestAutoProxyCreator) sac.getBean("testAutoProxyCreator");
166 		assertEquals(0, tapc.testInterceptor.nrOfInvocations);
167 		singletonNoInterceptor.getName();
168 		assertEquals(0, tapc.testInterceptor.nrOfInvocations);
169 		singletonToBeProxied.getAge();
170 		assertEquals(1, tapc.testInterceptor.nrOfInvocations);
171 		prototypeToBeProxied.getSpouse();
172 		assertEquals(2, tapc.testInterceptor.nrOfInvocations);
173 	}
174 
175 	@Test
176 	public void testAutoProxyCreatorWithFallbackToTargetClass() {
177 		StaticApplicationContext sac = new StaticApplicationContext();
178 		sac.registerSingleton("testAutoProxyCreator", FallbackTestAutoProxyCreator.class);
179 		sac.registerSingleton("noInterfaces", NoInterfaces.class);
180 		sac.registerSingleton("containerCallbackInterfacesOnly", ContainerCallbackInterfacesOnly.class);
181 		sac.registerSingleton("singletonNoInterceptor", TestBean.class);
182 		sac.registerSingleton("singletonToBeProxied", TestBean.class);
183 		sac.registerPrototype("prototypeToBeProxied", TestBean.class);
184 		sac.refresh();
185 
186 		MessageSource messageSource = (MessageSource) sac.getBean("messageSource");
187 		NoInterfaces noInterfaces = (NoInterfaces) sac.getBean("noInterfaces");
188 		ContainerCallbackInterfacesOnly containerCallbackInterfacesOnly =
189 				(ContainerCallbackInterfacesOnly) sac.getBean("containerCallbackInterfacesOnly");
190 		ITestBean singletonNoInterceptor = (ITestBean) sac.getBean("singletonNoInterceptor");
191 		ITestBean singletonToBeProxied = (ITestBean) sac.getBean("singletonToBeProxied");
192 		ITestBean prototypeToBeProxied = (ITestBean) sac.getBean("prototypeToBeProxied");
193 		assertFalse(AopUtils.isCglibProxy(messageSource));
194 		assertTrue(AopUtils.isCglibProxy(noInterfaces));
195 		assertTrue(AopUtils.isCglibProxy(containerCallbackInterfacesOnly));
196 		assertFalse(AopUtils.isCglibProxy(singletonNoInterceptor));
197 		assertFalse(AopUtils.isCglibProxy(singletonToBeProxied));
198 		assertFalse(AopUtils.isCglibProxy(prototypeToBeProxied));
199 
200 		TestAutoProxyCreator tapc = (TestAutoProxyCreator) sac.getBean("testAutoProxyCreator");
201 		assertEquals(0, tapc.testInterceptor.nrOfInvocations);
202 		singletonNoInterceptor.getName();
203 		assertEquals(0, tapc.testInterceptor.nrOfInvocations);
204 		singletonToBeProxied.getAge();
205 		assertEquals(1, tapc.testInterceptor.nrOfInvocations);
206 		prototypeToBeProxied.getSpouse();
207 		assertEquals(2, tapc.testInterceptor.nrOfInvocations);
208 	}
209 
210 	@Test
211 	public void testAutoProxyCreatorWithFactoryBean() {
212 		StaticApplicationContext sac = new StaticApplicationContext();
213 		sac.registerSingleton("testAutoProxyCreator", TestAutoProxyCreator.class);
214 		sac.registerSingleton("singletonFactoryToBeProxied", DummyFactory.class);
215 		sac.refresh();
216 
217 		TestAutoProxyCreator tapc = (TestAutoProxyCreator) sac.getBean("testAutoProxyCreator");
218 		tapc.testInterceptor.nrOfInvocations = 0;
219 
220 		FactoryBean<?> factory = (FactoryBean<?>) sac.getBean("&singletonFactoryToBeProxied");
221 		assertTrue(AopUtils.isCglibProxy(factory));
222 
223 		TestBean tb = (TestBean) sac.getBean("singletonFactoryToBeProxied");
224 		assertTrue(AopUtils.isCglibProxy(tb));
225 		assertEquals(2, tapc.testInterceptor.nrOfInvocations);
226 		tb.getAge();
227 		assertEquals(3, tapc.testInterceptor.nrOfInvocations);
228 	}
229 
230 	@Test
231 	public void testAutoProxyCreatorWithFactoryBeanAndPrototype() {
232 		StaticApplicationContext sac = new StaticApplicationContext();
233 		sac.registerSingleton("testAutoProxyCreator", TestAutoProxyCreator.class);
234 
235 		MutablePropertyValues pvs = new MutablePropertyValues();
236 		pvs.add("singleton", "false");
237 		sac.registerSingleton("prototypeFactoryToBeProxied", DummyFactory.class, pvs);
238 
239 		sac.refresh();
240 
241 		TestAutoProxyCreator tapc = (TestAutoProxyCreator) sac.getBean("testAutoProxyCreator");
242 		tapc.testInterceptor.nrOfInvocations = 0;
243 
244 		FactoryBean<?> prototypeFactory = (FactoryBean<?>) sac.getBean("&prototypeFactoryToBeProxied");
245 		assertTrue(AopUtils.isCglibProxy(prototypeFactory));
246 		TestBean tb = (TestBean) sac.getBean("prototypeFactoryToBeProxied");
247 		assertTrue(AopUtils.isCglibProxy(tb));
248 
249 		assertEquals(2, tapc.testInterceptor.nrOfInvocations);
250 		tb.getAge();
251 		assertEquals(3, tapc.testInterceptor.nrOfInvocations);
252 	}
253 
254 	@Test
255 	public void testAutoProxyCreatorWithFactoryBeanAndProxyObjectOnly() {
256 		StaticApplicationContext sac = new StaticApplicationContext();
257 
258 		MutablePropertyValues pvs = new MutablePropertyValues();
259 		pvs.add("proxyFactoryBean", "false");
260 		sac.registerSingleton("testAutoProxyCreator", TestAutoProxyCreator.class, pvs);
261 
262 		sac.registerSingleton("singletonFactoryToBeProxied", DummyFactory.class);
263 
264 		sac.refresh();
265 
266 		TestAutoProxyCreator tapc = (TestAutoProxyCreator) sac.getBean("testAutoProxyCreator");
267 		tapc.testInterceptor.nrOfInvocations = 0;
268 
269 		FactoryBean<?> factory = (FactoryBean<?>) sac.getBean("&singletonFactoryToBeProxied");
270 		assertFalse(AopUtils.isAopProxy(factory));
271 
272 		TestBean tb = (TestBean) sac.getBean("singletonFactoryToBeProxied");
273 		assertTrue(AopUtils.isCglibProxy(tb));
274 		assertEquals(0, tapc.testInterceptor.nrOfInvocations);
275 		tb.getAge();
276 		assertEquals(1, tapc.testInterceptor.nrOfInvocations);
277 
278 		TestBean tb2 = (TestBean) sac.getBean("singletonFactoryToBeProxied");
279 		assertSame(tb, tb2);
280 		assertEquals(1, tapc.testInterceptor.nrOfInvocations);
281 		tb2.getAge();
282 		assertEquals(2, tapc.testInterceptor.nrOfInvocations);
283 	}
284 
285 	@Test
286 	public void testAutoProxyCreatorWithFactoryBeanAndProxyFactoryBeanOnly() {
287 		StaticApplicationContext sac = new StaticApplicationContext();
288 
289 		MutablePropertyValues pvs = new MutablePropertyValues();
290 		pvs.add("proxyObject", "false");
291 		sac.registerSingleton("testAutoProxyCreator", TestAutoProxyCreator.class, pvs);
292 
293 		pvs = new MutablePropertyValues();
294 		pvs.add("singleton", "false");
295 		sac.registerSingleton("prototypeFactoryToBeProxied", DummyFactory.class, pvs);
296 
297 		sac.refresh();
298 
299 		TestAutoProxyCreator tapc = (TestAutoProxyCreator) sac.getBean("testAutoProxyCreator");
300 		tapc.testInterceptor.nrOfInvocations = 0;
301 
302 		FactoryBean<?> prototypeFactory = (FactoryBean<?>) sac.getBean("&prototypeFactoryToBeProxied");
303 		assertTrue(AopUtils.isCglibProxy(prototypeFactory));
304 		TestBean tb = (TestBean) sac.getBean("prototypeFactoryToBeProxied");
305 		assertFalse(AopUtils.isCglibProxy(tb));
306 
307 		assertEquals(2, tapc.testInterceptor.nrOfInvocations);
308 		tb.getAge();
309 		assertEquals(2, tapc.testInterceptor.nrOfInvocations);
310 	}
311 
312 
313 	@SuppressWarnings("serial")
314 	public static class TestAutoProxyCreator extends AbstractAutoProxyCreator {
315 
316 		private boolean proxyFactoryBean = true;
317 
318 		private boolean proxyObject = true;
319 
320 		public TestInterceptor testInterceptor = new TestInterceptor();
321 
322 		public TestAutoProxyCreator() {
323 			setProxyTargetClass(true);
324 			setOrder(0);
325 		}
326 
327 		public void setProxyFactoryBean(boolean proxyFactoryBean) {
328 			this.proxyFactoryBean = proxyFactoryBean;
329 		}
330 
331 		public void setProxyObject(boolean proxyObject) {
332 			this.proxyObject = proxyObject;
333 		}
334 
335 		@Override
336 		protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String name, TargetSource customTargetSource) {
337 			if (StaticMessageSource.class.equals(beanClass)) {
338 				return DO_NOT_PROXY;
339 			}
340 			else if (name.endsWith("ToBeProxied")) {
341 				boolean isFactoryBean = FactoryBean.class.isAssignableFrom(beanClass);
342 				if ((this.proxyFactoryBean && isFactoryBean) || (this.proxyObject && !isFactoryBean)) {
343 					return new Object[] {this.testInterceptor};
344 				}
345 				else {
346 					return DO_NOT_PROXY;
347 				}
348 			}
349 			else {
350 				return PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS;
351 			}
352 		}
353 	}
354 
355 
356 	@SuppressWarnings("serial")
357 	public static class FallbackTestAutoProxyCreator extends TestAutoProxyCreator {
358 
359 		public FallbackTestAutoProxyCreator() {
360 			setProxyTargetClass(false);
361 		}
362 	}
363 
364 
365 	/**
366 	 * Interceptor that counts the number of non-finalize method calls.
367 	 */
368 	public static class TestInterceptor implements MethodInterceptor {
369 
370 		public int nrOfInvocations = 0;
371 
372 		@Override
373 		public Object invoke(MethodInvocation invocation) throws Throwable {
374 			if (!invocation.getMethod().getName().equals("finalize")) {
375 				this.nrOfInvocations++;
376 			}
377 			return invocation.proceed();
378 		}
379 	}
380 
381 
382 	public static class NoInterfaces {
383 	}
384 
385 
386 	@SuppressWarnings("serial")
387 	public static class ContainerCallbackInterfacesOnly  // as well as an empty marker interface
388 			implements BeanFactoryAware, ApplicationContextAware, InitializingBean, DisposableBean, Serializable {
389 
390 		@Override
391 		public void setBeanFactory(BeanFactory beanFactory) {
392 		}
393 
394 		@Override
395 		public void setApplicationContext(ApplicationContext applicationContext) {
396 		}
397 
398 		@Override
399 		public void afterPropertiesSet() {
400 		}
401 
402 		@Override
403 		public void destroy() {
404 		}
405 	}
406 
407 }