View Javadoc
1   /*
2    * Copyright 2002-2013 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.IOException;
20  
21  import org.junit.Before;
22  import org.junit.Test;
23  import test.mixin.Lockable;
24  import test.mixin.LockedException;
25  
26  import org.springframework.aop.framework.Advised;
27  import org.springframework.aop.support.AopUtils;
28  import org.springframework.beans.factory.BeanFactory;
29  import org.springframework.beans.factory.FactoryBean;
30  import org.springframework.context.support.ClassPathXmlApplicationContext;
31  import org.springframework.tests.TimeStamped;
32  import org.springframework.tests.aop.advice.CountingBeforeAdvice;
33  import org.springframework.tests.aop.interceptor.NopInterceptor;
34  import org.springframework.tests.sample.beans.ITestBean;
35  import org.springframework.tests.sample.beans.TestBean;
36  
37  import static org.junit.Assert.*;
38  
39  /**
40   * @author Rod Johnson
41   * @author Rob Harrop
42   * @author Chris Beams
43   */
44  public class BeanNameAutoProxyCreatorTests {
45  
46  	private BeanFactory beanFactory;
47  
48  	@Before
49  	public void setUp() throws IOException {
50  		// Note that we need an ApplicationContext, not just a BeanFactory,
51  		// for post-processing and hence auto-proxying to work.
52  		beanFactory =
53  			new ClassPathXmlApplicationContext(getClass().getSimpleName() + "-context.xml", getClass());
54  	}
55  
56  	@Test
57  	public void testNoProxy() {
58  		TestBean tb = (TestBean) beanFactory.getBean("noproxy");
59  		assertFalse(AopUtils.isAopProxy(tb));
60  		assertEquals("noproxy", tb.getName());
61  	}
62  
63  	@Test
64  	public void testJdkProxyWithExactNameMatch() {
65  		ITestBean tb = (ITestBean) beanFactory.getBean("onlyJdk");
66  		jdkAssertions(tb, 1);
67  		assertEquals("onlyJdk", tb.getName());
68  	}
69  
70  	@Test
71  	public void testJdkProxyWithDoubleProxying() {
72  		ITestBean tb = (ITestBean) beanFactory.getBean("doubleJdk");
73  		jdkAssertions(tb, 2);
74  		assertEquals("doubleJdk", tb.getName());
75  	}
76  
77  	@Test
78  	public void testJdkIntroduction() {
79  		ITestBean tb = (ITestBean) beanFactory.getBean("introductionUsingJdk");
80  		NopInterceptor nop = (NopInterceptor) beanFactory.getBean("introductionNopInterceptor");
81  		assertEquals(0, nop.getCount());
82  		assertTrue(AopUtils.isJdkDynamicProxy(tb));
83  		int age = 5;
84  		tb.setAge(age);
85  		assertEquals(age, tb.getAge());
86  		assertTrue("Introduction was made", tb instanceof TimeStamped);
87  		assertEquals(0, ((TimeStamped) tb).getTimeStamp());
88  		assertEquals(3, nop.getCount());
89  		assertEquals("introductionUsingJdk", tb.getName());
90  
91  		ITestBean tb2 = (ITestBean) beanFactory.getBean("second-introductionUsingJdk");
92  
93  		// Check two per-instance mixins were distinct
94  		Lockable lockable1 = (Lockable) tb;
95  		Lockable lockable2 = (Lockable) tb2;
96  		assertFalse(lockable1.locked());
97  		assertFalse(lockable2.locked());
98  		tb.setAge(65);
99  		assertEquals(65, tb.getAge());
100 		lockable1.lock();
101 		assertTrue(lockable1.locked());
102 		// Shouldn't affect second
103 		assertFalse(lockable2.locked());
104 		// Can still mod second object
105 		tb2.setAge(12);
106 		// But can't mod first
107 		try {
108 			tb.setAge(6);
109 			fail("Mixin should have locked this object");
110 		}
111 		catch (LockedException ex) {
112 			// Ok
113 		}
114 	}
115 
116 	@Test
117 	public void testJdkIntroductionAppliesToCreatedObjectsNotFactoryBean() {
118 		ITestBean tb = (ITestBean) beanFactory.getBean("factory-introductionUsingJdk");
119 		NopInterceptor nop = (NopInterceptor) beanFactory.getBean("introductionNopInterceptor");
120 		assertEquals("NOP should not have done any work yet", 0, nop.getCount());
121 		assertTrue(AopUtils.isJdkDynamicProxy(tb));
122 		int age = 5;
123 		tb.setAge(age);
124 		assertEquals(age, tb.getAge());
125 		assertTrue("Introduction was made", tb instanceof TimeStamped);
126 		assertEquals(0, ((TimeStamped) tb).getTimeStamp());
127 		assertEquals(3, nop.getCount());
128 
129 		ITestBean tb2 = (ITestBean) beanFactory.getBean("second-introductionUsingJdk");
130 
131 		// Check two per-instance mixins were distinct
132 		Lockable lockable1 = (Lockable) tb;
133 		Lockable lockable2 = (Lockable) tb2;
134 		assertFalse(lockable1.locked());
135 		assertFalse(lockable2.locked());
136 		tb.setAge(65);
137 		assertEquals(65, tb.getAge());
138 		lockable1.lock();
139 		assertTrue(lockable1.locked());
140 		// Shouldn't affect second
141 		assertFalse(lockable2.locked());
142 		// Can still mod second object
143 		tb2.setAge(12);
144 		// But can't mod first
145 		try {
146 			tb.setAge(6);
147 			fail("Mixin should have locked this object");
148 		}
149 		catch (LockedException ex) {
150 			// Ok
151 		}
152 	}
153 
154 	@Test
155 	public void testJdkProxyWithWildcardMatch() {
156 		ITestBean tb = (ITestBean) beanFactory.getBean("jdk1");
157 		jdkAssertions(tb, 1);
158 		assertEquals("jdk1", tb.getName());
159 	}
160 
161 	@Test
162 	public void testCglibProxyWithWildcardMatch() {
163 		TestBean tb = (TestBean) beanFactory.getBean("cglib1");
164 		cglibAssertions(tb);
165 		assertEquals("cglib1", tb.getName());
166 	}
167 
168 	@Test
169 	public void testWithFrozenProxy() {
170 		ITestBean testBean = (ITestBean) beanFactory.getBean("frozenBean");
171 		assertTrue(((Advised)testBean).isFrozen());
172 	}
173 
174 	private void jdkAssertions(ITestBean tb, int nopInterceptorCount)  {
175 		NopInterceptor nop = (NopInterceptor) beanFactory.getBean("nopInterceptor");
176 		assertEquals(0, nop.getCount());
177 		assertTrue(AopUtils.isJdkDynamicProxy(tb));
178 		int age = 5;
179 		tb.setAge(age);
180 		assertEquals(age, tb.getAge());
181 		assertEquals(2 * nopInterceptorCount, nop.getCount());
182 	}
183 
184 	/**
185 	 * Also has counting before advice.
186 	 */
187 	private void cglibAssertions(TestBean tb) {
188 		CountingBeforeAdvice cba = (CountingBeforeAdvice) beanFactory.getBean("countingBeforeAdvice");
189 		NopInterceptor nop = (NopInterceptor) beanFactory.getBean("nopInterceptor");
190 		assertEquals(0, cba.getCalls());
191 		assertEquals(0, nop.getCount());
192 		assertTrue(AopUtils.isCglibProxy(tb));
193 		int age = 5;
194 		tb.setAge(age);
195 		assertEquals(age, tb.getAge());
196 		assertEquals(2, nop.getCount());
197 		assertEquals(2, cba.getCalls());
198 	}
199 
200 }
201 
202 
203 class CreatesTestBean implements FactoryBean<Object> {
204 
205 	/**
206 	 * @see org.springframework.beans.factory.FactoryBean#getObject()
207 	 */
208 	@Override
209 	public Object getObject() throws Exception {
210 		return new TestBean();
211 	}
212 
213 	/**
214 	 * @see org.springframework.beans.factory.FactoryBean#getObjectType()
215 	 */
216 	@Override
217 	public Class<?> getObjectType() {
218 		return TestBean.class;
219 	}
220 
221 	/**
222 	 * @see org.springframework.beans.factory.FactoryBean#isSingleton()
223 	 */
224 	@Override
225 	public boolean isSingleton() {
226 		return true;
227 	}
228 
229 }