📄 abstractaopproxytests.java
字号:
/*
* Copyright 2002-2005 the original author or authors.
*
* 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.springframework.aop.framework;
import java.lang.reflect.Method;
import java.lang.reflect.UndeclaredThrowableException;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletException;
import javax.transaction.TransactionRequiredException;
import junit.framework.TestCase;
import org.aopalliance.aop.Advice;
import org.aopalliance.aop.AspectException;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.Advisor;
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.DynamicIntroductionAdvice;
import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.aop.TargetSource;
import org.springframework.aop.framework.adapter.ThrowsAdviceInterceptorTests;
import org.springframework.aop.interceptor.DebugInterceptor;
import org.springframework.aop.interceptor.ExposeInvocationInterceptor;
import org.springframework.aop.interceptor.NopInterceptor;
import org.springframework.aop.interceptor.SerializableNopInterceptor;
import org.springframework.aop.support.AopUtils;
import org.springframework.aop.support.DefaultIntroductionAdvisor;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.aop.support.DelegatingIntroductionInterceptor;
import org.springframework.aop.support.DynamicMethodMatcherPointcutAdvisor;
import org.springframework.aop.support.NameMatchMethodPointcut;
import org.springframework.aop.support.Pointcuts;
import org.springframework.aop.support.StaticMethodMatcherPointcutAdvisor;
import org.springframework.aop.target.HotSwappableTargetSource;
import org.springframework.aop.target.SingletonTargetSource;
import org.springframework.beans.IOther;
import org.springframework.beans.ITestBean;
import org.springframework.beans.Person;
import org.springframework.beans.SerializablePerson;
import org.springframework.beans.TestBean;
import org.springframework.jdbc.CannotGetJdbcConnectionException;
import org.springframework.util.SerializationTestUtils;
import org.springframework.util.StopWatch;
/**
* @author Rod Johnson
* @author Juergen Hoeller
* @since 13.03.2003
*/
public abstract class AbstractAopProxyTests extends TestCase {
protected MockTargetSource mockTargetSource = new MockTargetSource();
/**
* Make a clean target source available if code wants to use it.
* The target must be set. Verification will be automatic in tearDown
* to ensure that it was used appropriately by code.
* @see junit.framework.TestCase#setUp()
*/
protected void setUp() {
mockTargetSource.reset();
}
protected void tearDown() {
mockTargetSource.verify();
}
/**
* Set in CGLIB or JDK mode.
*/
protected abstract Object createProxy(AdvisedSupport as);
protected abstract AopProxy createAopProxy(AdvisedSupport as);
/**
* Is a target always required?
*/
protected boolean requiresTarget() {
return false;
}
public void testNoInterceptorsAndNoTarget() {
AdvisedSupport pc =
new AdvisedSupport(new Class[] { ITestBean.class });
// Add no interceptors
try {
AopProxy aop = createAopProxy(pc);
aop.getProxy();
fail("Shouldn't allow no interceptors");
} catch (AopConfigException ex) {
// Ok
}
}
/**
* Simple test that if we set values we can get them out again.
*/
public void testValuesStick() {
int age1 = 33;
int age2 = 37;
String name = "tony";
TestBean target1 = new TestBean();
target1.setAge(age1);
ProxyFactory pf1 = new ProxyFactory(target1);
pf1.addAdvisor(new DefaultPointcutAdvisor(new NopInterceptor()));
pf1.addAdvisor(new DefaultPointcutAdvisor(new TimestampIntroductionInterceptor()));
ITestBean tb = target1;
assertEquals(age1, tb.getAge());
tb.setAge(age2);
assertEquals(age2, tb.getAge());
assertNull(tb.getName());
tb.setName(name);
assertEquals(name, tb.getName());
}
/**
* This is primarily a test for the efficiency of our
* usage of CGLIB. If we create too many classes with
* CGLIB this will be slow or will run out of memory.
*/
public void testManyProxies() {
int howMany = 10000;
StopWatch sw = new StopWatch();
sw.start(getClass() + "." + getName() + ": create " + howMany + " proxies");
testManyProxies(howMany);
sw.stop();
System.out.println(sw);
// Set a performance benchmark.
// It's pretty generous so as not to cause failures on slow machines.
assertTrue("Proxy creation was too slow", sw.getTotalTimeSeconds() < 25);
}
private void testManyProxies(int howMany) {
int age1 = 33;
TestBean target1 = new TestBean();
target1.setAge(age1);
ProxyFactory pf1 = new ProxyFactory(target1);
pf1.addAdvice(new NopInterceptor());
pf1.addAdvice(new NopInterceptor());
ITestBean proxies[] = new ITestBean[howMany];
for (int i = 0; i < howMany; i++) {
proxies[i] = (ITestBean) createAopProxy(pf1).getProxy();
assertEquals(age1, proxies[i].getAge());
}
}
public void testSerializationAdviceAndTargetNotSerializable() throws Exception {
TestBean tb = new TestBean();
assertFalse(SerializationTestUtils.isSerializable(tb));
ProxyFactory pf = new ProxyFactory(tb);
pf.addAdvice(new NopInterceptor());
ITestBean proxy = (ITestBean) createAopProxy(pf).getProxy();
assertFalse(SerializationTestUtils.isSerializable(proxy));
}
public void testSerializationAdviceNotSerializable() throws Exception {
SerializablePerson sp = new SerializablePerson();
assertTrue(SerializationTestUtils.isSerializable(sp));
ProxyFactory pf = new ProxyFactory(sp);
// This isn't serializable
Advice i = new NopInterceptor();
pf.addAdvice(i);
assertFalse(SerializationTestUtils.isSerializable(i));
Object proxy = createAopProxy(pf).getProxy();
assertFalse(SerializationTestUtils.isSerializable(proxy));
}
public void testSerializationSerializableTargetAndAdvice() throws Throwable {
SerializablePerson personTarget = new SerializablePerson();
personTarget.setName("jim");
personTarget.setAge(26);
assertTrue(SerializationTestUtils.isSerializable(personTarget));
ProxyFactory pf = new ProxyFactory(personTarget);
CountingThrowsAdvice cta = new CountingThrowsAdvice();
pf.addAdvice(new SerializableNopInterceptor());
// Try various advice types
pf.addAdvice(new CountingBeforeAdvice());
pf.addAdvice(new CountingAfterReturningAdvice());
pf.addAdvice(cta);
Person p = (Person) createAopProxy(pf).getProxy();
p.echo(null);
assertEquals(0, cta.getCalls());
try {
p.echo(new ServletException());
}
catch (ServletException ex) {
}
assertEquals(1, cta.getCalls());
// Will throw exception if it fails
Person p2 = (Person) SerializationTestUtils.serializeAndDeserialize(p);
assertNotSame(p, p2);
assertEquals(p.getName(), p2.getName());
assertEquals(p.getAge(), p2.getAge());
assertTrue("Deserialized object is an AOP proxy", AopUtils.isAopProxy(p2));
Advised a1 = (Advised) p;
Advised a2 = (Advised) p2;
// Check we can manipulate state of p2
assertEquals(a1.getAdvisors().length, a2.getAdvisors().length);
// This should work as SerializablePerson is equal
assertEquals("Proxies should be equal, even after one was serialized", p, p2);
assertEquals("Proxies should be equal, even after one was serialized", p2, p);
// Check we can add a new advisor to the target
NopInterceptor ni = new NopInterceptor();
p2.getAge();
assertEquals(0, ni.getCount());
a2.addAdvice(ni);
p2.getAge();
assertEquals(1, ni.getCount());
cta = (CountingThrowsAdvice) a2.getAdvisors()[3].getAdvice();
p2.echo(null);
assertEquals(1, cta.getCalls());
try {
p2.echo(new ServletException());
}
catch (ServletException ex) {
}
assertEquals(2, cta.getCalls());
}
/**
* Check that the two MethodInvocations necessary are independent and
* don't conflict.
* Check also proxy exposure.
*/
public void testOneAdvisedObjectCallsAnother() {
int age1 = 33;
int age2 = 37;
TestBean target1 = new TestBean();
ProxyFactory pf1 = new ProxyFactory(target1);
// Permit proxy and invocation checkers to get context from AopContext
pf1.setExposeProxy(true);
NopInterceptor di1 = new NopInterceptor();
pf1.addAdvice(0, di1);
pf1.addAdvice(1, new ProxyMatcherInterceptor());
pf1.addAdvice(2, new CheckMethodInvocationIsSameInAndOutInterceptor());
pf1.addAdvice(1, new CheckMethodInvocationViaThreadLocalIsSameInAndOutInterceptor());
// Must be first
pf1.addAdvice(0, ExposeInvocationInterceptor.INSTANCE);
ITestBean advised1 = (ITestBean) pf1.getProxy();
advised1.setAge(age1); // = 1 invocation
TestBean target2 = new TestBean();
ProxyFactory pf2 = new ProxyFactory(target2);
pf2.setExposeProxy(true);
NopInterceptor di2 = new NopInterceptor();
pf2.addAdvice(0, di2);
pf2.addAdvice(1, new ProxyMatcherInterceptor());
pf2.addAdvice(2, new CheckMethodInvocationIsSameInAndOutInterceptor());
pf2.addAdvice(1, new CheckMethodInvocationViaThreadLocalIsSameInAndOutInterceptor());
pf2.addAdvice(0, ExposeInvocationInterceptor.INSTANCE);
//System.err.println(pf2.toProxyConfigString());
ITestBean advised2 = (ITestBean) createProxy(pf2);
advised2.setAge(age2);
advised1.setSpouse(advised2); // = 2 invocations
assertEquals("Advised one has correct age", age1, advised1.getAge()); // = 3 invocations
assertEquals("Advised two has correct age", age2, advised2.getAge());
// Means extra call on advised 2
assertEquals("Advised one spouse has correct age", age2, advised1.getSpouse().getAge()); // = 4 invocations on 1 and another one on 2
assertEquals("one was invoked correct number of times", 4, di1.getCount());
// Got hit by call to advised1.getSpouse().getAge()
assertEquals("one was invoked correct number of times", 3, di2.getCount());
}
public void testReentrance() {
int age1 = 33;
TestBean target1 = new TestBean();
ProxyFactory pf1 = new ProxyFactory(target1);
NopInterceptor di1 = new NopInterceptor();
pf1.addAdvice(0, di1);
ITestBean advised1 = (ITestBean) createProxy(pf1);
advised1.setAge(age1); // = 1 invocation
advised1.setSpouse(advised1); // = 2 invocations
assertEquals("one was invoked correct number of times", 2, di1.getCount());
assertEquals("Advised one has correct age", age1, advised1.getAge()); // = 3 invocations
assertEquals("one was invoked correct number of times", 3, di1.getCount());
// = 5 invocations, as reentrant call to spouse is advised also
assertEquals("Advised spouse has correct age", age1, advised1.getSpouse().getAge());
assertEquals("one was invoked correct number of times", 5, di1.getCount());
}
public void testTargetCanGetProxy() {
NopInterceptor di = new NopInterceptor();
INeedsToSeeProxy target = new TargetChecker();
ProxyFactory proxyFactory = new ProxyFactory(target);
proxyFactory.setExposeProxy(true);
assertTrue(proxyFactory.isExposeProxy());
proxyFactory.addAdvice(0, di);
INeedsToSeeProxy proxied = (INeedsToSeeProxy) createProxy(proxyFactory);
assertEquals(0, di.getCount());
assertEquals(0, target.getCount());
proxied.incrementViaThis();
assertEquals("Increment happened", 1, target.getCount());
assertEquals("Only one invocation via AOP as use of this wasn't proxied", 1, di.getCount());
// 1 invocation
assertEquals("Increment happened", 1, proxied.getCount());
proxied.incrementViaProxy(); // 2 invoocations
assertEquals("Increment happened", 2, target.getCount());
assertEquals("3 more invocations via AOP as the first call was reentrant through the proxy", 4, di.getCount());
}
public void testTargetCantGetProxyByDefault() {
NeedsToSeeProxy et = new NeedsToSeeProxy();
ProxyFactory pf1 = new ProxyFactory(et);
assertFalse(pf1.isExposeProxy());
INeedsToSeeProxy proxied = (INeedsToSeeProxy) createProxy(pf1);
try {
proxied.incrementViaProxy();
fail("Should have failed to get proxy as exposeProxy wasn't set to true");
}
catch (AspectException ex) {
// Ok
}
}
public void testContext() throws Throwable {
testContext(true);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -