⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 abstractaopproxytests.java

📁 spring的源代码
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
/*
 * 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 + -