Rename modules {org.springframework.*=>spring-*}
This renaming more intuitively expresses the relationship between
subprojects and the JAR artifacts they produce.
Tracking history across these renames is possible, but it requires
use of the --follow flag to `git log`, for example
$ git log spring-aop/src/main/java/org/springframework/aop/Advisor.java
will show history up until the renaming event, where
$ git log --follow spring-aop/src/main/java/org/springframework/aop/Advisor.java
will show history for all changes to the file, before and after the
renaming.
See http://chrisbeams.com/git-diff-across-renamed-directories
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.aspectj;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.junit.Test;
|
||||
|
||||
|
||||
/**
|
||||
* Additional parameter name discover tests that need Java 5.
|
||||
* Yes this will re-run the tests from the superclass, but that
|
||||
* doesn't matter in the grand scheme of things...
|
||||
*
|
||||
* @author Adrian Colyer
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public final class AspectJAdviceParameterNameDiscoverAnnotationTests
|
||||
extends AspectJAdviceParameterNameDiscovererTests {
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@interface MyAnnotation {}
|
||||
|
||||
public void pjpAndAnAnnotation(ProceedingJoinPoint pjp, MyAnnotation ann) {}
|
||||
|
||||
@Test
|
||||
public void testAnnotationBinding() {
|
||||
assertParameterNames(getMethod("pjpAndAnAnnotation"),
|
||||
"execution(* *(..)) && @annotation(ann)",
|
||||
new String[] {"thisJoinPoint","ann"});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,330 @@
|
||||
/*
|
||||
* Copyright 2002-2006 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.aspectj;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.junit.Test;
|
||||
import org.springframework.aop.aspectj.AspectJAdviceParameterNameDiscoverer.AmbiguousBindingException;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* Unit tests for the {@link AspectJAdviceParameterNameDiscoverer} class.
|
||||
*
|
||||
* <p>See also {@link TigerAspectJAdviceParameterNameDiscovererTests} in
|
||||
* the 'tiger' tree for tests relating to annotations.
|
||||
*
|
||||
* @author Adrian Colyer
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public class AspectJAdviceParameterNameDiscovererTests {
|
||||
|
||||
// methods to discover parameter names for
|
||||
public void noArgs() {
|
||||
}
|
||||
|
||||
public void tjp(JoinPoint jp) {
|
||||
}
|
||||
|
||||
public void tjpsp(JoinPoint.StaticPart tjpsp) {
|
||||
}
|
||||
|
||||
public void twoJoinPoints(JoinPoint jp1, JoinPoint jp2) {
|
||||
}
|
||||
|
||||
public void oneThrowable(Exception ex) {
|
||||
}
|
||||
|
||||
public void jpAndOneThrowable(JoinPoint jp, Exception ex) {
|
||||
}
|
||||
|
||||
public void jpAndTwoThrowables(JoinPoint jp, Exception ex, Error err) {
|
||||
}
|
||||
|
||||
public void oneObject(Object x) {
|
||||
}
|
||||
|
||||
public void twoObjects(Object x, Object y) {
|
||||
}
|
||||
|
||||
public void onePrimitive(int x) {
|
||||
}
|
||||
|
||||
public void oneObjectOnePrimitive(Object x, int y) {
|
||||
}
|
||||
|
||||
public void oneThrowableOnePrimitive(Throwable x, int y) {
|
||||
}
|
||||
|
||||
public void theBigOne(JoinPoint jp, Throwable x, int y, Object foo) {
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testNoArgs() {
|
||||
assertParameterNames(getMethod("noArgs"), "execution(* *(..))", new String[0]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJoinPointOnly() {
|
||||
assertParameterNames(getMethod("tjp"), "execution(* *(..))", new String[]{"thisJoinPoint"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJoinPointStaticPartOnly() {
|
||||
assertParameterNames(getMethod("tjpsp"), "execution(* *(..))", new String[]{"thisJoinPointStaticPart"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTwoJoinPoints() {
|
||||
assertException(getMethod("twoJoinPoints"), "foo()", IllegalStateException.class, "Failed to bind all argument names: 1 argument(s) could not be bound");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOneThrowable() {
|
||||
assertParameterNames(getMethod("oneThrowable"), "foo()", null, "ex", new String[]{"ex"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOneJPAndOneThrowable() {
|
||||
assertParameterNames(getMethod("jpAndOneThrowable"), "foo()", null, "ex", new String[]{"thisJoinPoint", "ex"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOneJPAndTwoThrowables() {
|
||||
assertException(getMethod("jpAndTwoThrowables"), "foo()", null, "ex", AmbiguousBindingException.class,
|
||||
"Binding of throwing parameter 'ex' is ambiguous: could be bound to argument 1 or argument 2");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThrowableNoCandidates() {
|
||||
assertException(getMethod("noArgs"), "foo()", null, "ex", IllegalStateException.class,
|
||||
"Not enough arguments in method to satisfy binding of returning and throwing variables");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReturning() {
|
||||
assertParameterNames(getMethod("oneObject"), "foo()", "obj", null, new String[]{"obj"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAmbiguousReturning() {
|
||||
assertException(getMethod("twoObjects"), "foo()", "obj", null, AmbiguousBindingException.class,
|
||||
"Binding of returning parameter 'obj' is ambiguous, there are 2 candidates.");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReturningNoCandidates() {
|
||||
assertException(getMethod("noArgs"), "foo()", "obj", null, IllegalStateException.class,
|
||||
"Not enough arguments in method to satisfy binding of returning and throwing variables");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThisBindingOneCandidate() {
|
||||
assertParameterNames(getMethod("oneObject"), "this(x)", new String[]{"x"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThisBindingWithAlternateTokenizations() {
|
||||
assertParameterNames(getMethod("oneObject"), "this( x )", new String[]{"x"});
|
||||
assertParameterNames(getMethod("oneObject"), "this( x)", new String[]{"x"});
|
||||
assertParameterNames(getMethod("oneObject"), "this (x )", new String[]{"x"});
|
||||
assertParameterNames(getMethod("oneObject"), "this(x )", new String[]{"x"});
|
||||
assertParameterNames(getMethod("oneObject"), "foo() && this(x)", new String[]{"x"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThisBindingTwoCandidates() {
|
||||
assertException(getMethod("oneObject"), "this(x) || this(y)", AmbiguousBindingException.class,
|
||||
"Found 2 candidate this(), target() or args() variables but only one unbound argument slot");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThisBindingWithBadPointcutExpressions() {
|
||||
assertException(getMethod("oneObject"), "this(", IllegalStateException.class,
|
||||
"Failed to bind all argument names: 1 argument(s) could not be bound");
|
||||
assertException(getMethod("oneObject"), "this(x && foo()", IllegalStateException.class,
|
||||
"Failed to bind all argument names: 1 argument(s) could not be bound");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTargetBindingOneCandidate() {
|
||||
assertParameterNames(getMethod("oneObject"), "target(x)", new String[]{"x"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTargetBindingWithAlternateTokenizations() {
|
||||
assertParameterNames(getMethod("oneObject"), "target( x )", new String[]{"x"});
|
||||
assertParameterNames(getMethod("oneObject"), "target( x)", new String[]{"x"});
|
||||
assertParameterNames(getMethod("oneObject"), "target (x )", new String[]{"x"});
|
||||
assertParameterNames(getMethod("oneObject"), "target(x )", new String[]{"x"});
|
||||
assertParameterNames(getMethod("oneObject"), "foo() && target(x)", new String[]{"x"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTargetBindingTwoCandidates() {
|
||||
assertException(getMethod("oneObject"), "target(x) || target(y)", AmbiguousBindingException.class,
|
||||
"Found 2 candidate this(), target() or args() variables but only one unbound argument slot");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTargetBindingWithBadPointcutExpressions() {
|
||||
assertException(getMethod("oneObject"), "target(", IllegalStateException.class,
|
||||
"Failed to bind all argument names: 1 argument(s) could not be bound");
|
||||
assertException(getMethod("oneObject"), "target(x && foo()", IllegalStateException.class,
|
||||
"Failed to bind all argument names: 1 argument(s) could not be bound");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testArgsBindingOneObject() {
|
||||
assertParameterNames(getMethod("oneObject"), "args(x)", new String[]{"x"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testArgsBindingOneObjectTwoCandidates() {
|
||||
assertException(getMethod("oneObject"), "args(x,y)", AmbiguousBindingException.class,
|
||||
"Found 2 candidate this(), target() or args() variables but only one unbound argument slot");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAmbiguousArgsBinding() {
|
||||
assertException(getMethod("twoObjects"), "args(x,y)", AmbiguousBindingException.class,
|
||||
"Still 2 unbound args at this(),target(),args() binding stage, with no way to determine between them");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testArgsOnePrimitive() {
|
||||
assertParameterNames(getMethod("onePrimitive"), "args(count)", new String[]{"count"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testArgsOnePrimitiveOneObject() {
|
||||
assertException(getMethod("oneObjectOnePrimitive"), "args(count,obj)", AmbiguousBindingException.class,
|
||||
"Found 2 candidate variable names but only one candidate binding slot when matching primitive args");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThisAndPrimitive() {
|
||||
assertParameterNames(getMethod("oneObjectOnePrimitive"), "args(count) && this(obj)", new String[]{"obj", "count"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTargetAndPrimitive() {
|
||||
assertParameterNames(getMethod("oneObjectOnePrimitive"), "args(count) && target(obj)", new String[]{"obj", "count"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThrowingAndPrimitive() {
|
||||
assertParameterNames(getMethod("oneThrowableOnePrimitive"), "args(count)", null, "ex", new String[]{"ex", "count"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAllTogetherNow() {
|
||||
assertParameterNames(getMethod("theBigOne"), "this(foo) && args(x)", null, "ex", new String[]{"thisJoinPoint", "ex", "x", "foo"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReferenceBinding() {
|
||||
assertParameterNames(getMethod("onePrimitive"),"somepc(foo)",new String[] {"foo"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReferenceBindingWithAlternateTokenizations() {
|
||||
assertParameterNames(getMethod("onePrimitive"),"call(bar *) && somepc(foo)",new String[] {"foo"});
|
||||
assertParameterNames(getMethod("onePrimitive"),"somepc ( foo )",new String[] {"foo"});
|
||||
assertParameterNames(getMethod("onePrimitive"),"somepc( foo)",new String[] {"foo"});
|
||||
}
|
||||
|
||||
|
||||
protected Method getMethod(String name) {
|
||||
// assumes no overloading of test methods...
|
||||
Method[] candidates = this.getClass().getMethods();
|
||||
for (int i = 0; i < candidates.length; i++) {
|
||||
if (candidates[i].getName().equals(name)) {
|
||||
return candidates[i];
|
||||
}
|
||||
}
|
||||
fail("Bad test specification, no method '" + name + "' found in test class");
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void assertParameterNames(Method m, String pointcut, String[] parameterNames) {
|
||||
assertParameterNames(m, pointcut, null, null, parameterNames);
|
||||
}
|
||||
|
||||
protected void assertParameterNames(Method m, String pointcut, String returning, String throwing, String[] parameterNames) {
|
||||
assertEquals("bad test specification, must have same number of parameter names as method arguments",
|
||||
m.getParameterTypes().length, parameterNames.length);
|
||||
|
||||
AspectJAdviceParameterNameDiscoverer discoverer = new AspectJAdviceParameterNameDiscoverer(pointcut);
|
||||
discoverer.setRaiseExceptions(true);
|
||||
discoverer.setReturningName(returning);
|
||||
discoverer.setThrowingName(throwing);
|
||||
String[] discoveredNames = discoverer.getParameterNames(m);
|
||||
|
||||
String formattedExpectedNames = format(parameterNames);
|
||||
String formattedActualNames = format(discoveredNames);
|
||||
|
||||
assertEquals("Expecting " + parameterNames.length + " parameter names in return set '" +
|
||||
formattedExpectedNames + "', but found " + discoveredNames.length +
|
||||
" '" + formattedActualNames + "'",
|
||||
parameterNames.length, discoveredNames.length);
|
||||
|
||||
for (int i = 0; i < discoveredNames.length; i++) {
|
||||
assertNotNull("Parameter names must never be null", discoveredNames[i]);
|
||||
assertEquals("Expecting parameter " + i + " to be named '" +
|
||||
parameterNames[i] + "' but was '" + discoveredNames[i] + "'",
|
||||
parameterNames[i], discoveredNames[i]);
|
||||
}
|
||||
}
|
||||
|
||||
protected void assertException(Method m, String pointcut, Class<?> exceptionType, String message) {
|
||||
assertException(m, pointcut, null, null, exceptionType, message);
|
||||
}
|
||||
|
||||
protected void assertException(Method m, String pointcut, String returning, String throwing, Class<?> exceptionType, String message) {
|
||||
AspectJAdviceParameterNameDiscoverer discoverer = new AspectJAdviceParameterNameDiscoverer(pointcut);
|
||||
discoverer.setRaiseExceptions(true);
|
||||
discoverer.setReturningName(returning);
|
||||
discoverer.setThrowingName(throwing);
|
||||
|
||||
try {
|
||||
discoverer.getParameterNames(m);
|
||||
fail("Expecting " + exceptionType.getName() + " with message '" + message + "'");
|
||||
} catch (RuntimeException expected) {
|
||||
assertEquals("Expecting exception of type " + exceptionType.getName(),
|
||||
exceptionType, expected.getClass());
|
||||
assertEquals("Exception message does not match expected", message, expected.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static String format(String[] names) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append("(");
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
sb.append(names[i]);
|
||||
if ((i + 1) < names.length) {
|
||||
sb.append(",");
|
||||
}
|
||||
}
|
||||
sb.append(")");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,370 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.aspectj;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.aspectj.weaver.tools.PointcutExpression;
|
||||
import org.aspectj.weaver.tools.PointcutPrimitive;
|
||||
import org.aspectj.weaver.tools.UnsupportedPointcutPrimitiveException;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.aop.ClassFilter;
|
||||
import org.springframework.aop.MethodMatcher;
|
||||
import org.springframework.aop.Pointcut;
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.aop.support.DefaultPointcutAdvisor;
|
||||
|
||||
import test.beans.IOther;
|
||||
import test.beans.ITestBean;
|
||||
import test.beans.TestBean;
|
||||
import test.beans.subpkg.DeepBean;
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
* @author Rod Johnson
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public final class AspectJExpressionPointcutTests {
|
||||
|
||||
public static final String MATCH_ALL_METHODS = "execution(* *(..))";
|
||||
|
||||
private Method getAge;
|
||||
|
||||
private Method setAge;
|
||||
|
||||
private Method setSomeNumber;
|
||||
|
||||
private Method isPostProcessed;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() throws NoSuchMethodException {
|
||||
getAge = TestBean.class.getMethod("getAge", (Class<?>[])null);
|
||||
setAge = TestBean.class.getMethod("setAge", new Class[]{int.class});
|
||||
setSomeNumber = TestBean.class.getMethod("setSomeNumber", new Class[]{Number.class});
|
||||
isPostProcessed = TestBean.class.getMethod("isPostProcessed", (Class[]) null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchExplicit() {
|
||||
String expression = "execution(int test.beans.TestBean.getAge())";
|
||||
|
||||
Pointcut pointcut = getPointcut(expression);
|
||||
ClassFilter classFilter = pointcut.getClassFilter();
|
||||
MethodMatcher methodMatcher = pointcut.getMethodMatcher();
|
||||
|
||||
assertMatchesTestBeanClass(classFilter);
|
||||
|
||||
// not currently testable in a reliable fashion
|
||||
//assertDoesNotMatchStringClass(classFilter);
|
||||
|
||||
assertFalse("Should not be a runtime match", methodMatcher.isRuntime());
|
||||
assertMatchesGetAge(methodMatcher);
|
||||
assertFalse("Expression should match setAge() method", methodMatcher.matches(setAge, TestBean.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchWithTypePattern() throws Exception {
|
||||
String expression = "execution(* *..TestBean.*Age(..))";
|
||||
|
||||
Pointcut pointcut = getPointcut(expression);
|
||||
ClassFilter classFilter = pointcut.getClassFilter();
|
||||
MethodMatcher methodMatcher = pointcut.getMethodMatcher();
|
||||
|
||||
assertMatchesTestBeanClass(classFilter);
|
||||
|
||||
// not currently testable in a reliable fashion
|
||||
//assertDoesNotMatchStringClass(classFilter);
|
||||
|
||||
assertFalse("Should not be a runtime match", methodMatcher.isRuntime());
|
||||
assertMatchesGetAge(methodMatcher);
|
||||
assertTrue("Expression should match setAge(int) method", methodMatcher.matches(setAge, TestBean.class));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testThis() throws SecurityException, NoSuchMethodException{
|
||||
testThisOrTarget("this");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTarget() throws SecurityException, NoSuchMethodException {
|
||||
testThisOrTarget("target");
|
||||
}
|
||||
|
||||
public static class OtherIOther implements IOther {
|
||||
|
||||
public void absquatulate() {
|
||||
// Empty
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This and target are equivalent. Really instanceof pointcuts.
|
||||
* @throws Exception
|
||||
* @param which this or target
|
||||
* @throws NoSuchMethodException
|
||||
* @throws SecurityException
|
||||
*/
|
||||
private void testThisOrTarget(String which) throws SecurityException, NoSuchMethodException {
|
||||
String matchesTestBean = which + "(test.beans.TestBean)";
|
||||
String matchesIOther = which + "(test.beans.IOther)";
|
||||
AspectJExpressionPointcut testBeanPc = new AspectJExpressionPointcut();
|
||||
testBeanPc.setExpression(matchesTestBean);
|
||||
|
||||
AspectJExpressionPointcut iOtherPc = new AspectJExpressionPointcut();
|
||||
iOtherPc.setExpression(matchesIOther);
|
||||
|
||||
assertTrue(testBeanPc.matches(TestBean.class));
|
||||
assertTrue(testBeanPc.matches(getAge, TestBean.class));
|
||||
assertTrue(iOtherPc.matches(OtherIOther.class.getMethod("absquatulate", (Class<?>[])null),
|
||||
OtherIOther.class));
|
||||
|
||||
assertFalse(testBeanPc.matches(OtherIOther.class.getMethod("absquatulate", (Class<?>[])null),
|
||||
OtherIOther.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithinRootPackage() throws SecurityException, NoSuchMethodException {
|
||||
testWithinPackage(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithinRootAndSubpackages() throws SecurityException, NoSuchMethodException {
|
||||
testWithinPackage(true);
|
||||
}
|
||||
|
||||
private void testWithinPackage(boolean matchSubpackages) throws SecurityException, NoSuchMethodException {
|
||||
String withinBeansPackage = "within(test.beans.";
|
||||
// Subpackages are matched by **
|
||||
if (matchSubpackages) {
|
||||
withinBeansPackage += ".";
|
||||
}
|
||||
withinBeansPackage = withinBeansPackage + "*)";
|
||||
AspectJExpressionPointcut withinBeansPc = new AspectJExpressionPointcut();
|
||||
withinBeansPc.setExpression(withinBeansPackage);
|
||||
|
||||
assertTrue(withinBeansPc.matches(TestBean.class));
|
||||
assertTrue(withinBeansPc.matches(getAge, TestBean.class));
|
||||
assertEquals(matchSubpackages, withinBeansPc.matches(DeepBean.class));
|
||||
assertEquals(matchSubpackages, withinBeansPc.matches(
|
||||
DeepBean.class.getMethod("aMethod", String.class), DeepBean.class));
|
||||
assertFalse(withinBeansPc.matches(String.class));
|
||||
assertFalse(withinBeansPc.matches(OtherIOther.class.getMethod("absquatulate", (Class<?>[])null),
|
||||
OtherIOther.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFriendlyErrorOnNoLocationClassMatching() {
|
||||
AspectJExpressionPointcut pc = new AspectJExpressionPointcut();
|
||||
try {
|
||||
pc.matches(ITestBean.class);
|
||||
fail();
|
||||
}
|
||||
catch (IllegalStateException ex) {
|
||||
assertTrue(ex.getMessage().indexOf("expression") != -1);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFriendlyErrorOnNoLocation2ArgMatching() {
|
||||
AspectJExpressionPointcut pc = new AspectJExpressionPointcut();
|
||||
try {
|
||||
pc.matches(getAge, ITestBean.class);
|
||||
fail();
|
||||
}
|
||||
catch (IllegalStateException ex) {
|
||||
assertTrue(ex.getMessage().indexOf("expression") != -1);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFriendlyErrorOnNoLocation3ArgMatching() {
|
||||
AspectJExpressionPointcut pc = new AspectJExpressionPointcut();
|
||||
try {
|
||||
pc.matches(getAge, ITestBean.class, (Object[]) null);
|
||||
fail();
|
||||
}
|
||||
catch (IllegalStateException ex) {
|
||||
assertTrue(ex.getMessage().indexOf("expression") != -1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testMatchWithArgs() throws Exception {
|
||||
String expression = "execution(void test.beans.TestBean.setSomeNumber(Number)) && args(Double)";
|
||||
|
||||
Pointcut pointcut = getPointcut(expression);
|
||||
ClassFilter classFilter = pointcut.getClassFilter();
|
||||
MethodMatcher methodMatcher = pointcut.getMethodMatcher();
|
||||
|
||||
assertMatchesTestBeanClass(classFilter);
|
||||
|
||||
// not currently testable in a reliable fashion
|
||||
//assertDoesNotMatchStringClass(classFilter);
|
||||
|
||||
assertTrue("Should match with setSomeNumber with Double input",
|
||||
methodMatcher.matches(setSomeNumber, TestBean.class, new Object[]{new Double(12)}));
|
||||
assertFalse("Should not match setSomeNumber with Integer input",
|
||||
methodMatcher.matches(setSomeNumber, TestBean.class, new Object[]{new Integer(11)}));
|
||||
assertFalse("Should not match getAge", methodMatcher.matches(getAge, TestBean.class, null));
|
||||
assertTrue("Should be a runtime match", methodMatcher.isRuntime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleAdvice() {
|
||||
String expression = "execution(int test.beans.TestBean.getAge())";
|
||||
|
||||
CallCountingInterceptor interceptor = new CallCountingInterceptor();
|
||||
|
||||
TestBean testBean = getAdvisedProxy(expression, interceptor);
|
||||
|
||||
assertEquals("Calls should be 0", 0, interceptor.getCount());
|
||||
|
||||
testBean.getAge();
|
||||
|
||||
assertEquals("Calls should be 1", 1, interceptor.getCount());
|
||||
|
||||
testBean.setAge(90);
|
||||
|
||||
assertEquals("Calls should still be 1", 1, interceptor.getCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDynamicMatchingProxy() {
|
||||
String expression = "execution(void test.beans.TestBean.setSomeNumber(Number)) && args(Double)";
|
||||
|
||||
CallCountingInterceptor interceptor = new CallCountingInterceptor();
|
||||
|
||||
TestBean testBean = getAdvisedProxy(expression, interceptor);
|
||||
|
||||
assertEquals("Calls should be 0", 0, interceptor.getCount());
|
||||
|
||||
testBean.setSomeNumber(new Double(30));
|
||||
|
||||
assertEquals("Calls should be 1", 1, interceptor.getCount());
|
||||
|
||||
testBean.setSomeNumber(new Integer(90));
|
||||
|
||||
assertEquals("Calls should be 1", 1, interceptor.getCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvalidExpression() {
|
||||
String expression = "execution(void test.beans.TestBean.setSomeNumber(Number) && args(Double)";
|
||||
|
||||
try {
|
||||
getPointcut(expression).getClassFilter(); // call to getClassFilter forces resolution
|
||||
fail("Invalid expression should throw IllegalArgumentException");
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
assertTrue(true);
|
||||
System.out.println(ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private TestBean getAdvisedProxy(String pointcutExpression, CallCountingInterceptor interceptor) {
|
||||
TestBean target = new TestBean();
|
||||
|
||||
Pointcut pointcut = getPointcut(pointcutExpression);
|
||||
|
||||
DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor();
|
||||
advisor.setAdvice(interceptor);
|
||||
advisor.setPointcut(pointcut);
|
||||
|
||||
ProxyFactory pf = new ProxyFactory();
|
||||
pf.setTarget(target);
|
||||
pf.addAdvisor(advisor);
|
||||
|
||||
return (TestBean) pf.getProxy();
|
||||
}
|
||||
|
||||
private void assertMatchesGetAge(MethodMatcher methodMatcher) {
|
||||
assertTrue("Expression should match getAge() method", methodMatcher.matches(getAge, TestBean.class));
|
||||
}
|
||||
|
||||
private void assertMatchesTestBeanClass(ClassFilter classFilter) {
|
||||
assertTrue("Expression should match TestBean class", classFilter.matches(TestBean.class));
|
||||
}
|
||||
|
||||
private void assertDoesNotMatchStringClass(ClassFilter classFilter) {
|
||||
assertFalse("Expression should not match String class", classFilter.matches(String.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithUnsupportedPointcutPrimitive() throws Exception {
|
||||
String expression = "call(int test.beans.TestBean.getAge())";
|
||||
|
||||
try {
|
||||
getPointcut(expression).getClassFilter(); // call to getClassFilter forces resolution...
|
||||
fail("Should not support call pointcuts");
|
||||
}
|
||||
catch (UnsupportedPointcutPrimitiveException ex) {
|
||||
assertEquals("Should not support call pointcut", PointcutPrimitive.CALL, ex.getUnsupportedPrimitive());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAndSubstitution() {
|
||||
Pointcut pc = getPointcut("execution(* *(..)) and args(String)");
|
||||
PointcutExpression expr =
|
||||
((AspectJExpressionPointcut) pc).getPointcutExpression();
|
||||
assertEquals("execution(* *(..)) && args(String)",expr.getPointcutExpression());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleAndSubstitutions() {
|
||||
Pointcut pc = getPointcut("execution(* *(..)) and args(String) and this(Object)");
|
||||
PointcutExpression expr =
|
||||
((AspectJExpressionPointcut) pc).getPointcutExpression();
|
||||
assertEquals("execution(* *(..)) && args(String) && this(Object)",expr.getPointcutExpression());
|
||||
}
|
||||
|
||||
private Pointcut getPointcut(String expression) {
|
||||
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
|
||||
pointcut.setExpression(expression);
|
||||
return pointcut;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class CallCountingInterceptor implements MethodInterceptor {
|
||||
|
||||
private int count;
|
||||
|
||||
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
|
||||
count++;
|
||||
return methodInvocation.proceed();
|
||||
}
|
||||
|
||||
public int getCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
this.count = 0;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.aspectj;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import test.beans.TestBean;
|
||||
|
||||
/**
|
||||
* Tests for matching of bean() pointcut designator.
|
||||
*
|
||||
* @author Ramnivas Laddad
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public final class BeanNamePointcutMatchingTests {
|
||||
|
||||
@Test
|
||||
public void testMatchingPointcuts() {
|
||||
assertMatch("someName", "bean(someName)");
|
||||
|
||||
// Spring bean names are less restrictive compared to AspectJ names (methods, types etc.)
|
||||
// MVC Controller-kind
|
||||
assertMatch("someName/someOtherName", "bean(someName/someOtherName)");
|
||||
assertMatch("someName/foo/someOtherName", "bean(someName/*/someOtherName)");
|
||||
assertMatch("someName/foo/bar/someOtherName", "bean(someName/*/someOtherName)");
|
||||
assertMatch("someName/*/**", "bean(someName/*)");
|
||||
// JMX-kind
|
||||
assertMatch("service:name=traceService", "bean(service:name=traceService)");
|
||||
assertMatch("service:name=traceService", "bean(service:name=*)");
|
||||
assertMatch("service:name=traceService", "bean(*:name=traceService)");
|
||||
|
||||
// Wildcards
|
||||
assertMatch("someName", "bean(*someName)");
|
||||
assertMatch("someName", "bean(*Name)");
|
||||
assertMatch("someName", "bean(*)");
|
||||
assertMatch("someName", "bean(someName*)");
|
||||
assertMatch("someName", "bean(some*)");
|
||||
assertMatch("someName", "bean(some*Name)");
|
||||
assertMatch("someName", "bean(*some*Name*)");
|
||||
assertMatch("someName", "bean(*s*N*)");
|
||||
|
||||
// Or, and, not expressions
|
||||
assertMatch("someName", "bean(someName) || bean(someOtherName)");
|
||||
assertMatch("someOtherName", "bean(someName) || bean(someOtherName)");
|
||||
|
||||
assertMatch("someName", "!bean(someOtherName)");
|
||||
|
||||
assertMatch("someName", "bean(someName) || !bean(someOtherName)");
|
||||
assertMatch("someName", "bean(someName) && !bean(someOtherName)");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNonMatchingPointcuts() {
|
||||
assertMisMatch("someName", "bean(someNamex)");
|
||||
assertMisMatch("someName", "bean(someX*Name)");
|
||||
|
||||
// And, not expressions
|
||||
assertMisMatch("someName", "bean(someName) && bean(someOtherName)");
|
||||
assertMisMatch("someName", "!bean(someName)");
|
||||
assertMisMatch("someName", "!bean(someName) && bean(someOtherName)");
|
||||
assertMisMatch("someName", "!bean(someName) || bean(someOtherName)");
|
||||
}
|
||||
|
||||
private void assertMatch(String beanName, String pcExpression) {
|
||||
assertTrue("Unexpected mismatch for bean \"" + beanName + "\" for pcExpression \"" + pcExpression + "\"",
|
||||
matches(beanName, pcExpression));
|
||||
}
|
||||
|
||||
private void assertMisMatch(String beanName, String pcExpression) {
|
||||
assertFalse("Unexpected match for bean \"" + beanName + "\" for pcExpression \"" + pcExpression + "\"",
|
||||
matches(beanName, pcExpression));
|
||||
}
|
||||
|
||||
private static boolean matches(final String beanName, String pcExpression) {
|
||||
@SuppressWarnings("serial")
|
||||
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut() {
|
||||
protected String getCurrentProxiedBeanName() {
|
||||
return beanName;
|
||||
}
|
||||
};
|
||||
pointcut.setExpression(pcExpression);
|
||||
return pointcut.matches(TestBean.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
* Copyright 2002-2009 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.aspectj;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.JoinPoint.StaticPart;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.reflect.MethodSignature;
|
||||
import org.aspectj.lang.reflect.SourceLocation;
|
||||
import org.aspectj.runtime.reflect.Factory;
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Test;
|
||||
import test.beans.ITestBean;
|
||||
import test.beans.TestBean;
|
||||
|
||||
import org.springframework.aop.MethodBeforeAdvice;
|
||||
import org.springframework.aop.framework.AopContext;
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.aop.interceptor.ExposeInvocationInterceptor;
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
|
||||
/**
|
||||
* @author Rod Johnson
|
||||
* @author Chris Beams
|
||||
* @author Ramnivas Laddad
|
||||
* @since 2.0
|
||||
*/
|
||||
public final class MethodInvocationProceedingJoinPointTests {
|
||||
|
||||
@Test
|
||||
public void testingBindingWithJoinPoint() {
|
||||
try {
|
||||
AbstractAspectJAdvice.currentJoinPoint();
|
||||
fail("Needs to be bound by interceptor action");
|
||||
}
|
||||
catch (IllegalStateException ex) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testingBindingWithProceedingJoinPoint() {
|
||||
try {
|
||||
AbstractAspectJAdvice.currentJoinPoint();
|
||||
fail("Needs to be bound by interceptor action");
|
||||
}
|
||||
catch (IllegalStateException ex) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCanGetMethodSignatureFromJoinPoint() {
|
||||
final Object raw = new TestBean();
|
||||
// Will be set by advice during a method call
|
||||
final int newAge = 23;
|
||||
|
||||
ProxyFactory pf = new ProxyFactory(raw);
|
||||
pf.setExposeProxy(true);
|
||||
pf.addAdvisor(ExposeInvocationInterceptor.ADVISOR);
|
||||
pf.addAdvice(new MethodBeforeAdvice() {
|
||||
private int depth;
|
||||
|
||||
public void before(Method method, Object[] args, Object target) throws Throwable {
|
||||
JoinPoint jp = AbstractAspectJAdvice.currentJoinPoint();
|
||||
assertTrue("Method named in toString", jp.toString().contains(method.getName()));
|
||||
// Ensure that these don't cause problems
|
||||
jp.toShortString();
|
||||
jp.toLongString();
|
||||
|
||||
assertSame(target, AbstractAspectJAdvice.currentJoinPoint().getTarget());
|
||||
assertFalse(AopUtils.isAopProxy(AbstractAspectJAdvice.currentJoinPoint().getTarget()));
|
||||
|
||||
ITestBean thisProxy = (ITestBean) AbstractAspectJAdvice.currentJoinPoint().getThis();
|
||||
assertTrue(AopUtils.isAopProxy(AbstractAspectJAdvice.currentJoinPoint().getThis()));
|
||||
|
||||
assertNotSame(target, thisProxy);
|
||||
|
||||
// Check getting again doesn't cause a problem
|
||||
assertSame(thisProxy, AbstractAspectJAdvice.currentJoinPoint().getThis());
|
||||
|
||||
// Try reentrant call--will go through this advice.
|
||||
// Be sure to increment depth to avoid infinite recursion
|
||||
if (depth++ == 0) {
|
||||
// Check that toString doesn't cause a problem
|
||||
thisProxy.toString();
|
||||
// Change age, so this will be returned by invocation
|
||||
thisProxy.setAge(newAge);
|
||||
assertEquals(newAge, thisProxy.getAge());
|
||||
}
|
||||
|
||||
assertSame(AopContext.currentProxy(), thisProxy);
|
||||
assertSame(target, raw);
|
||||
|
||||
assertSame(method.getName(), AbstractAspectJAdvice.currentJoinPoint().getSignature().getName());
|
||||
assertEquals(method.getModifiers(), AbstractAspectJAdvice.currentJoinPoint().getSignature().getModifiers());
|
||||
|
||||
MethodSignature msig = (MethodSignature) AbstractAspectJAdvice.currentJoinPoint().getSignature();
|
||||
assertSame("Return same MethodSignature repeatedly", msig, AbstractAspectJAdvice.currentJoinPoint().getSignature());
|
||||
assertSame("Return same JoinPoint repeatedly", AbstractAspectJAdvice.currentJoinPoint(), AbstractAspectJAdvice.currentJoinPoint());
|
||||
assertEquals(method.getDeclaringClass(), msig.getDeclaringType());
|
||||
assertTrue(Arrays.equals(method.getParameterTypes(), msig.getParameterTypes()));
|
||||
assertEquals(method.getReturnType(), msig.getReturnType());
|
||||
assertTrue(Arrays.equals(method.getExceptionTypes(), msig.getExceptionTypes()));
|
||||
msig.toLongString();
|
||||
msig.toShortString();
|
||||
}
|
||||
});
|
||||
ITestBean itb = (ITestBean) pf.getProxy();
|
||||
// Any call will do
|
||||
assertEquals("Advice reentrantly set age", newAge, itb.getAge());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCanGetSourceLocationFromJoinPoint() {
|
||||
final Object raw = new TestBean();
|
||||
ProxyFactory pf = new ProxyFactory(raw);
|
||||
pf.addAdvisor(ExposeInvocationInterceptor.ADVISOR);
|
||||
pf.addAdvice(new MethodBeforeAdvice() {
|
||||
public void before(Method method, Object[] args, Object target) throws Throwable {
|
||||
SourceLocation sloc = AbstractAspectJAdvice.currentJoinPoint().getSourceLocation();
|
||||
assertEquals("Same source location must be returned on subsequent requests", sloc, AbstractAspectJAdvice.currentJoinPoint().getSourceLocation());
|
||||
assertEquals(TestBean.class, sloc.getWithinType());
|
||||
try {
|
||||
sloc.getLine();
|
||||
fail("Can't get line number");
|
||||
}
|
||||
catch (UnsupportedOperationException ex) {
|
||||
// Expected
|
||||
}
|
||||
|
||||
try {
|
||||
sloc.getFileName();
|
||||
fail("Can't get file name");
|
||||
}
|
||||
catch (UnsupportedOperationException ex) {
|
||||
// Expected
|
||||
}
|
||||
}
|
||||
});
|
||||
ITestBean itb = (ITestBean) pf.getProxy();
|
||||
// Any call will do
|
||||
itb.getAge();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCanGetStaticPartFromJoinPoint() {
|
||||
final Object raw = new TestBean();
|
||||
ProxyFactory pf = new ProxyFactory(raw);
|
||||
pf.addAdvisor(ExposeInvocationInterceptor.ADVISOR);
|
||||
pf.addAdvice(new MethodBeforeAdvice() {
|
||||
public void before(Method method, Object[] args, Object target) throws Throwable {
|
||||
StaticPart staticPart = AbstractAspectJAdvice.currentJoinPoint().getStaticPart();
|
||||
assertEquals("Same static part must be returned on subsequent requests", staticPart, AbstractAspectJAdvice.currentJoinPoint().getStaticPart());
|
||||
assertEquals(ProceedingJoinPoint.METHOD_EXECUTION, staticPart.getKind());
|
||||
assertSame(AbstractAspectJAdvice.currentJoinPoint().getSignature(), staticPart.getSignature());
|
||||
assertEquals(AbstractAspectJAdvice.currentJoinPoint().getSourceLocation(), staticPart.getSourceLocation());
|
||||
}
|
||||
});
|
||||
ITestBean itb = (ITestBean) pf.getProxy();
|
||||
// Any call will do
|
||||
itb.getAge();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toShortAndLongStringFormedCorrectly() throws Exception {
|
||||
final Object raw = new TestBean();
|
||||
ProxyFactory pf = new ProxyFactory(raw);
|
||||
pf.addAdvisor(ExposeInvocationInterceptor.ADVISOR);
|
||||
pf.addAdvice(new MethodBeforeAdvice() {
|
||||
public void before(Method method, Object[] args, Object target) throws Throwable {
|
||||
// makeEncSJP, although meant for computing the enclosing join point,
|
||||
// it serves our purpose here
|
||||
JoinPoint.StaticPart aspectJVersionJp = Factory.makeEncSJP(method);
|
||||
JoinPoint jp = AbstractAspectJAdvice.currentJoinPoint();
|
||||
|
||||
assertEquals(aspectJVersionJp.getSignature().toLongString(), jp.getSignature().toLongString());
|
||||
assertEquals(aspectJVersionJp.getSignature().toShortString(), jp.getSignature().toShortString());
|
||||
assertEquals(aspectJVersionJp.getSignature().toString(), jp.getSignature().toString());
|
||||
|
||||
assertEquals(aspectJVersionJp.toLongString(), jp.toLongString());
|
||||
assertEquals(aspectJVersionJp.toShortString(), jp.toShortString());
|
||||
assertEquals(aspectJVersionJp.toString(), jp.toString());
|
||||
}
|
||||
});
|
||||
ITestBean itb = (ITestBean) pf.getProxy();
|
||||
itb.getAge();
|
||||
itb.setName("foo");
|
||||
itb.getDoctor();
|
||||
itb.getStringArray();
|
||||
itb.getSpouses();
|
||||
itb.setSpouse(new TestBean());
|
||||
try {
|
||||
itb.unreliableFileOperation();
|
||||
} catch (IOException ex) {
|
||||
// we don't realy care...
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.aspectj;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.aop.aspectj.AspectJAdviceParameterNameDiscoverer.AmbiguousBindingException;
|
||||
|
||||
/**
|
||||
* Tests just the annotation binding part of {@link AspectJAdviceParameterNameDiscoverer};
|
||||
* see supertype for remaining tests.
|
||||
*
|
||||
* @author Adrian Colyer
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public final class TigerAspectJAdviceParameterNameDiscovererTests
|
||||
extends AspectJAdviceParameterNameDiscovererTests {
|
||||
|
||||
@Test
|
||||
public void testAtThis() {
|
||||
assertParameterNames(getMethod("oneAnnotation"),"@this(a)",new String[]{"a"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAtTarget() {
|
||||
assertParameterNames(getMethod("oneAnnotation"),"@target(a)",new String[]{"a"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAtArgs() {
|
||||
assertParameterNames(getMethod("oneAnnotation"),"@args(a)",new String[]{"a"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAtWithin() {
|
||||
assertParameterNames(getMethod("oneAnnotation"),"@within(a)",new String[]{"a"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAtWithincode() {
|
||||
assertParameterNames(getMethod("oneAnnotation"),"@withincode(a)",new String[]{"a"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAtAnnotation() {
|
||||
assertParameterNames(getMethod("oneAnnotation"),"@annotation(a)",new String[]{"a"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAmbiguousAnnotationTwoVars() {
|
||||
assertException(getMethod("twoAnnotations"),"@annotation(a) && @this(x)",AmbiguousBindingException.class,
|
||||
"Found 2 potential annotation variable(s), and 2 potential argument slots");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAmbiguousAnnotationOneVar() {
|
||||
assertException(getMethod("oneAnnotation"),"@annotation(a) && @this(x)",IllegalArgumentException.class,
|
||||
"Found 2 candidate annotation binding variables but only one potential argument binding slot");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnnotationMedley() {
|
||||
assertParameterNames(getMethod("annotationMedley"),"@annotation(a) && args(count) && this(foo)",null,"ex",
|
||||
new String[] {"ex","foo","count","a"});
|
||||
}
|
||||
|
||||
|
||||
public void oneAnnotation(MyAnnotation ann) {}
|
||||
|
||||
public void twoAnnotations(MyAnnotation ann, MyAnnotation anotherAnn) {}
|
||||
|
||||
public void annotationMedley(Throwable t, Object foo, int x, MyAnnotation ma) {}
|
||||
|
||||
@interface MyAnnotation {}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,296 @@
|
||||
/*
|
||||
* 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.aspectj;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import test.annotation.EmptySpringAnnotation;
|
||||
import test.annotation.transaction.Tx;
|
||||
import test.beans.TestBean;
|
||||
|
||||
|
||||
/**
|
||||
* Java5-specific {@link AspectJExpressionPointcutTests}.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public final class TigerAspectJExpressionPointcutTests {
|
||||
|
||||
// TODO factor into static in AspectJExpressionPointcut
|
||||
private Method getAge;
|
||||
|
||||
private Map<String,Method> methodsOnHasGeneric = new HashMap<String,Method>();
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() throws NoSuchMethodException {
|
||||
getAge = TestBean.class.getMethod("getAge", (Class[]) null);
|
||||
// Assumes no overloading
|
||||
for (Method m : HasGeneric.class.getMethods()) {
|
||||
methodsOnHasGeneric.put(m.getName(), m);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class HasGeneric {
|
||||
|
||||
public void setFriends(List<TestBean> friends) {
|
||||
}
|
||||
public void setEnemies(List<TestBean> enemies) {
|
||||
}
|
||||
public void setPartners(List<?> partners) {
|
||||
}
|
||||
public void setPhoneNumbers(List<String> numbers) {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchGenericArgument() {
|
||||
String expression = "execution(* set*(java.util.List<test.beans.TestBean>) )";
|
||||
AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut();
|
||||
ajexp.setExpression(expression);
|
||||
|
||||
// TODO this will currently map, would be nice for optimization
|
||||
//assertTrue(ajexp.matches(HasGeneric.class));
|
||||
//assertFalse(ajexp.matches(TestBean.class));
|
||||
|
||||
Method takesGenericList = methodsOnHasGeneric.get("setFriends");
|
||||
assertTrue(ajexp.matches(takesGenericList, HasGeneric.class));
|
||||
assertTrue(ajexp.matches(methodsOnHasGeneric.get("setEnemies"), HasGeneric.class));
|
||||
assertFalse(ajexp.matches(methodsOnHasGeneric.get("setPartners"), HasGeneric.class));
|
||||
assertFalse(ajexp.matches(methodsOnHasGeneric.get("setPhoneNumbers"), HasGeneric.class));
|
||||
|
||||
assertFalse(ajexp.matches(getAge, TestBean.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchVarargs() throws SecurityException, NoSuchMethodException {
|
||||
class MyTemplate {
|
||||
public int queryForInt(String sql, Object... params) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
String expression = "execution(int *.*(String, Object...))";
|
||||
AspectJExpressionPointcut jdbcVarArgs = new AspectJExpressionPointcut();
|
||||
jdbcVarArgs.setExpression(expression);
|
||||
|
||||
// TODO: the expression above no longer matches Object[]
|
||||
// assertFalse(jdbcVarArgs.matches(
|
||||
// JdbcTemplate.class.getMethod("queryForInt", String.class, Object[].class),
|
||||
// JdbcTemplate.class));
|
||||
|
||||
assertTrue(jdbcVarArgs.matches(
|
||||
MyTemplate.class.getMethod("queryForInt", String.class, Object[].class),
|
||||
MyTemplate.class));
|
||||
|
||||
Method takesGenericList = methodsOnHasGeneric.get("setFriends");
|
||||
assertFalse(jdbcVarArgs.matches(takesGenericList, HasGeneric.class));
|
||||
assertFalse(jdbcVarArgs.matches(methodsOnHasGeneric.get("setEnemies"), HasGeneric.class));
|
||||
assertFalse(jdbcVarArgs.matches(methodsOnHasGeneric.get("setPartners"), HasGeneric.class));
|
||||
assertFalse(jdbcVarArgs.matches(methodsOnHasGeneric.get("setPhoneNumbers"), HasGeneric.class));
|
||||
assertFalse(jdbcVarArgs.matches(getAge, TestBean.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchAnnotationOnClassWithAtWithin() throws SecurityException, NoSuchMethodException {
|
||||
String expression = "@within(test.annotation.transaction.Tx)";
|
||||
testMatchAnnotationOnClass(expression);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchAnnotationOnClassWithoutBinding() throws SecurityException, NoSuchMethodException {
|
||||
String expression = "within(@test.annotation.transaction.Tx *)";
|
||||
testMatchAnnotationOnClass(expression);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchAnnotationOnClassWithSubpackageWildcard() throws SecurityException, NoSuchMethodException {
|
||||
String expression = "within(@(test.annotation..*) *)";
|
||||
AspectJExpressionPointcut springAnnotatedPc = testMatchAnnotationOnClass(expression);
|
||||
assertFalse(springAnnotatedPc.matches(TestBean.class.getMethod("setName", String.class),
|
||||
TestBean.class));
|
||||
assertTrue(springAnnotatedPc.matches(SpringAnnotated.class.getMethod("foo", (Class[]) null),
|
||||
SpringAnnotated.class));
|
||||
|
||||
expression = "within(@(test.annotation.transaction..*) *)";
|
||||
AspectJExpressionPointcut springTxAnnotatedPc = testMatchAnnotationOnClass(expression);
|
||||
assertFalse(springTxAnnotatedPc.matches(SpringAnnotated.class.getMethod("foo", (Class[]) null),
|
||||
SpringAnnotated.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchAnnotationOnClassWithExactPackageWildcard() throws SecurityException, NoSuchMethodException {
|
||||
String expression = "within(@(test.annotation.transaction.*) *)";
|
||||
testMatchAnnotationOnClass(expression);
|
||||
}
|
||||
|
||||
private AspectJExpressionPointcut testMatchAnnotationOnClass(String expression) throws SecurityException, NoSuchMethodException {
|
||||
AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut();
|
||||
ajexp.setExpression(expression);
|
||||
|
||||
assertFalse(ajexp.matches(getAge, TestBean.class));
|
||||
assertTrue(ajexp.matches(HasTransactionalAnnotation.class.getMethod("foo", (Class[]) null), HasTransactionalAnnotation.class));
|
||||
assertTrue(ajexp.matches(HasTransactionalAnnotation.class.getMethod("bar", String.class), HasTransactionalAnnotation.class));
|
||||
assertTrue(ajexp.matches(BeanB.class.getMethod("setName", String.class), BeanB.class));
|
||||
assertFalse(ajexp.matches(BeanA.class.getMethod("setName", String.class), BeanA.class));
|
||||
return ajexp;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnnotationOnMethodWithFQN() throws SecurityException, NoSuchMethodException {
|
||||
String expression = "@annotation(test.annotation.transaction.Tx)";
|
||||
AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut();
|
||||
ajexp.setExpression(expression);
|
||||
|
||||
assertFalse(ajexp.matches(getAge, TestBean.class));
|
||||
assertFalse(ajexp.matches(HasTransactionalAnnotation.class.getMethod("foo", (Class[]) null), HasTransactionalAnnotation.class));
|
||||
assertFalse(ajexp.matches(HasTransactionalAnnotation.class.getMethod("bar", String.class), HasTransactionalAnnotation.class));
|
||||
assertFalse(ajexp.matches(BeanA.class.getMethod("setName", String.class), BeanA.class));
|
||||
assertTrue(ajexp.matches(BeanA.class.getMethod("getAge", (Class[]) null), BeanA.class));
|
||||
assertFalse(ajexp.matches(BeanA.class.getMethod("setName", String.class), BeanA.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnnotationOnMethodWithWildcard() throws SecurityException, NoSuchMethodException {
|
||||
String expression = "execution(@(test.annotation..*) * *(..))";
|
||||
AspectJExpressionPointcut anySpringMethodAnnotation = new AspectJExpressionPointcut();
|
||||
anySpringMethodAnnotation.setExpression(expression);
|
||||
|
||||
assertFalse(anySpringMethodAnnotation.matches(getAge, TestBean.class));
|
||||
assertFalse(anySpringMethodAnnotation.matches(HasTransactionalAnnotation.class.getMethod("foo", (Class[]) null), HasTransactionalAnnotation.class));
|
||||
assertFalse(anySpringMethodAnnotation.matches(HasTransactionalAnnotation.class.getMethod("bar", String.class), HasTransactionalAnnotation.class));
|
||||
assertFalse(anySpringMethodAnnotation.matches(BeanA.class.getMethod("setName", String.class), BeanA.class));
|
||||
assertTrue(anySpringMethodAnnotation.matches(BeanA.class.getMethod("getAge", (Class[]) null), BeanA.class));
|
||||
assertFalse(anySpringMethodAnnotation.matches(BeanA.class.getMethod("setName", String.class), BeanA.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnnotationOnMethodArgumentsWithFQN() throws SecurityException, NoSuchMethodException {
|
||||
String expression = "@args(*, test.annotation.EmptySpringAnnotation))";
|
||||
AspectJExpressionPointcut takesSpringAnnotatedArgument2 = new AspectJExpressionPointcut();
|
||||
takesSpringAnnotatedArgument2.setExpression(expression);
|
||||
|
||||
assertFalse(takesSpringAnnotatedArgument2.matches(getAge, TestBean.class));
|
||||
assertFalse(takesSpringAnnotatedArgument2.matches(HasTransactionalAnnotation.class.getMethod("foo", (Class[]) null), HasTransactionalAnnotation.class));
|
||||
assertFalse(takesSpringAnnotatedArgument2.matches(HasTransactionalAnnotation.class.getMethod("bar", String.class), HasTransactionalAnnotation.class));
|
||||
assertFalse(takesSpringAnnotatedArgument2.matches(BeanA.class.getMethod("setName", String.class), BeanA.class));
|
||||
assertFalse(takesSpringAnnotatedArgument2.matches(BeanA.class.getMethod("getAge", (Class[]) null), BeanA.class));
|
||||
assertFalse(takesSpringAnnotatedArgument2.matches(BeanA.class.getMethod("setName", String.class), BeanA.class));
|
||||
|
||||
assertTrue(takesSpringAnnotatedArgument2.matches(
|
||||
ProcessesSpringAnnotatedParameters.class.getMethod("takesAnnotatedParameters", TestBean.class, SpringAnnotated.class),
|
||||
ProcessesSpringAnnotatedParameters.class));
|
||||
|
||||
// True because it maybeMatches with potential argument subtypes
|
||||
assertTrue(takesSpringAnnotatedArgument2.matches(
|
||||
ProcessesSpringAnnotatedParameters.class.getMethod("takesNoAnnotatedParameters", TestBean.class, BeanA.class),
|
||||
ProcessesSpringAnnotatedParameters.class));
|
||||
|
||||
assertFalse(takesSpringAnnotatedArgument2.matches(
|
||||
ProcessesSpringAnnotatedParameters.class.getMethod("takesNoAnnotatedParameters", TestBean.class, BeanA.class),
|
||||
ProcessesSpringAnnotatedParameters.class,
|
||||
new Object[] { new TestBean(), new BeanA()})
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnnotationOnMethodArgumentsWithWildcards() throws SecurityException, NoSuchMethodException {
|
||||
String expression = "execution(* *(*, @(test..*) *))";
|
||||
AspectJExpressionPointcut takesSpringAnnotatedArgument2 = new AspectJExpressionPointcut();
|
||||
takesSpringAnnotatedArgument2.setExpression(expression);
|
||||
|
||||
assertFalse(takesSpringAnnotatedArgument2.matches(getAge, TestBean.class));
|
||||
assertFalse(takesSpringAnnotatedArgument2.matches(HasTransactionalAnnotation.class.getMethod("foo", (Class[]) null), HasTransactionalAnnotation.class));
|
||||
assertFalse(takesSpringAnnotatedArgument2.matches(HasTransactionalAnnotation.class.getMethod("bar", String.class), HasTransactionalAnnotation.class));
|
||||
assertFalse(takesSpringAnnotatedArgument2.matches(BeanA.class.getMethod("setName", String.class), BeanA.class));
|
||||
assertFalse(takesSpringAnnotatedArgument2.matches(BeanA.class.getMethod("getAge", (Class[]) null), BeanA.class));
|
||||
assertFalse(takesSpringAnnotatedArgument2.matches(BeanA.class.getMethod("setName", String.class), BeanA.class));
|
||||
|
||||
assertTrue(takesSpringAnnotatedArgument2.matches(
|
||||
ProcessesSpringAnnotatedParameters.class.getMethod("takesAnnotatedParameters", TestBean.class, SpringAnnotated.class),
|
||||
ProcessesSpringAnnotatedParameters.class));
|
||||
assertFalse(takesSpringAnnotatedArgument2.matches(
|
||||
ProcessesSpringAnnotatedParameters.class.getMethod("takesNoAnnotatedParameters", TestBean.class, BeanA.class),
|
||||
ProcessesSpringAnnotatedParameters.class));
|
||||
}
|
||||
|
||||
|
||||
public static class ProcessesSpringAnnotatedParameters {
|
||||
|
||||
public void takesAnnotatedParameters(TestBean tb, SpringAnnotated sa) {
|
||||
}
|
||||
|
||||
public void takesNoAnnotatedParameters(TestBean tb, BeanA tb3) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Tx
|
||||
public static class HasTransactionalAnnotation {
|
||||
|
||||
public void foo() {
|
||||
}
|
||||
public Object bar(String foo) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@EmptySpringAnnotation
|
||||
public static class SpringAnnotated {
|
||||
public void foo() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static class BeanA {
|
||||
private String name;
|
||||
|
||||
private int age;
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Tx
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Tx
|
||||
static class BeanB {
|
||||
private String name;
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
package org.springframework.aop.aspectj;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.aop.Advisor;
|
||||
import org.springframework.aop.MethodBeforeAdvice;
|
||||
import org.springframework.aop.ThrowsAdvice;
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.aop.support.DefaultPointcutAdvisor;
|
||||
import org.springframework.core.OverridingClassLoader;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class TrickyAspectJPointcutExpressionTests {
|
||||
|
||||
@Test
|
||||
public void testManualProxyJavaWithUnconditionalPointcut() throws Exception {
|
||||
TestService target = new TestServiceImpl();
|
||||
LogUserAdvice logAdvice = new LogUserAdvice();
|
||||
testAdvice(new DefaultPointcutAdvisor(logAdvice), logAdvice, target, "TestServiceImpl");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testManualProxyJavaWithStaticPointcut() throws Exception {
|
||||
TestService target = new TestServiceImpl();
|
||||
LogUserAdvice logAdvice = new LogUserAdvice();
|
||||
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
|
||||
pointcut.setExpression(String.format("execution(* %s.TestService.*(..))", getClass().getName()));
|
||||
testAdvice(new DefaultPointcutAdvisor(pointcut, logAdvice), logAdvice, target, "TestServiceImpl");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testManualProxyJavaWithDynamicPointcut() throws Exception {
|
||||
TestService target = new TestServiceImpl();
|
||||
LogUserAdvice logAdvice = new LogUserAdvice();
|
||||
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
|
||||
pointcut.setExpression(String.format("@within(%s.Log)", getClass().getName()));
|
||||
testAdvice(new DefaultPointcutAdvisor(pointcut, logAdvice), logAdvice, target, "TestServiceImpl");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testManualProxyJavaWithDynamicPointcutAndProxyTargetClass() throws Exception {
|
||||
TestService target = new TestServiceImpl();
|
||||
LogUserAdvice logAdvice = new LogUserAdvice();
|
||||
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
|
||||
pointcut.setExpression(String.format("@within(%s.Log)", getClass().getName()));
|
||||
testAdvice(new DefaultPointcutAdvisor(pointcut, logAdvice), logAdvice, target, "TestServiceImpl", true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testManualProxyJavaWithStaticPointcutAndTwoClassLoaders() throws Exception {
|
||||
|
||||
LogUserAdvice logAdvice = new LogUserAdvice();
|
||||
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
|
||||
pointcut.setExpression(String.format("execution(* %s.TestService.*(..))", getClass().getName()));
|
||||
|
||||
// Test with default class loader first...
|
||||
testAdvice(new DefaultPointcutAdvisor(pointcut, logAdvice), logAdvice, new TestServiceImpl(), "TestServiceImpl");
|
||||
|
||||
// Then try again with a different class loader on the target...
|
||||
SimpleThrowawayClassLoader loader = new SimpleThrowawayClassLoader(new TestServiceImpl().getClass().getClassLoader());
|
||||
// Make sure the interface is loaded from the parent class loader
|
||||
loader.excludeClass(TestService.class.getName());
|
||||
loader.excludeClass(TestException.class.getName());
|
||||
TestService other = (TestService) loader.loadClass(TestServiceImpl.class.getName()).newInstance();
|
||||
testAdvice(new DefaultPointcutAdvisor(pointcut, logAdvice), logAdvice, other, "TestServiceImpl");
|
||||
|
||||
}
|
||||
|
||||
private void testAdvice(Advisor advisor, LogUserAdvice logAdvice, TestService target, String message)
|
||||
throws Exception {
|
||||
testAdvice(advisor, logAdvice, target, message, false);
|
||||
}
|
||||
|
||||
private void testAdvice(Advisor advisor, LogUserAdvice logAdvice, TestService target, String message,
|
||||
boolean proxyTargetClass) throws Exception {
|
||||
|
||||
logAdvice.reset();
|
||||
|
||||
ProxyFactory factory = new ProxyFactory(target);
|
||||
factory.setProxyTargetClass(proxyTargetClass);
|
||||
factory.addAdvisor(advisor);
|
||||
TestService bean = (TestService) factory.getProxy();
|
||||
|
||||
assertEquals(0, logAdvice.getCountThrows());
|
||||
try {
|
||||
bean.sayHello();
|
||||
fail("Expected exception");
|
||||
} catch (TestException e) {
|
||||
assertEquals(message, e.getMessage());
|
||||
}
|
||||
assertEquals(1, logAdvice.getCountThrows());
|
||||
}
|
||||
|
||||
public static class SimpleThrowawayClassLoader extends OverridingClassLoader {
|
||||
|
||||
/**
|
||||
* Create a new SimpleThrowawayClassLoader for the given class loader.
|
||||
* @param parent the ClassLoader to build a throwaway ClassLoader for
|
||||
*/
|
||||
public SimpleThrowawayClassLoader(ClassLoader parent) {
|
||||
super(parent);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class TestException extends RuntimeException {
|
||||
|
||||
public TestException(String string) {
|
||||
super(string);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Target({ ElementType.METHOD, ElementType.TYPE })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Inherited
|
||||
public static @interface Log {
|
||||
}
|
||||
|
||||
public static interface TestService {
|
||||
public String sayHello();
|
||||
}
|
||||
|
||||
@Log
|
||||
public static class TestServiceImpl implements TestService{
|
||||
public String sayHello() {
|
||||
throw new TestException("TestServiceImpl");
|
||||
}
|
||||
}
|
||||
|
||||
public class LogUserAdvice implements MethodBeforeAdvice, ThrowsAdvice {
|
||||
|
||||
private int countBefore = 0;
|
||||
|
||||
private int countThrows = 0;
|
||||
|
||||
public void before(Method method, Object[] objects, Object o) throws Throwable {
|
||||
countBefore++;
|
||||
}
|
||||
|
||||
public void afterThrowing(Exception e) throws Throwable {
|
||||
countThrows++;
|
||||
throw e;
|
||||
}
|
||||
|
||||
public int getCountBefore() {
|
||||
return countBefore;
|
||||
}
|
||||
|
||||
public int getCountThrows() {
|
||||
return countThrows;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
countThrows = 0;
|
||||
countBefore = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright 2002-2006 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.aspectj;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
|
||||
import test.beans.CountingTestBean;
|
||||
import test.beans.IOther;
|
||||
import test.beans.ITestBean;
|
||||
import test.beans.TestBean;
|
||||
import test.beans.subpkg.DeepBean;
|
||||
|
||||
/**
|
||||
* Unit tests for the {@link TypePatternClassFilter} class.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Rick Evans
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public final class TypePatternClassFilterTests {
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testInvalidPattern() {
|
||||
// should throw - pattern must be recognized as invalid
|
||||
new TypePatternClassFilter("-");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidPatternMatching() {
|
||||
TypePatternClassFilter tpcf = new TypePatternClassFilter("test.beans.*");
|
||||
assertTrue("Must match: in package", tpcf.matches(TestBean.class));
|
||||
assertTrue("Must match: in package", tpcf.matches(ITestBean.class));
|
||||
assertTrue("Must match: in package", tpcf.matches(IOther.class));
|
||||
assertFalse("Must be excluded: in wrong package", tpcf.matches(DeepBean.class));
|
||||
assertFalse("Must be excluded: in wrong package", tpcf.matches(BeanFactory.class));
|
||||
assertFalse("Must be excluded: in wrong package", tpcf.matches(DefaultListableBeanFactory.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSubclassMatching() {
|
||||
TypePatternClassFilter tpcf = new TypePatternClassFilter("test.beans.ITestBean+");
|
||||
assertTrue("Must match: in package", tpcf.matches(TestBean.class));
|
||||
assertTrue("Must match: in package", tpcf.matches(ITestBean.class));
|
||||
assertTrue("Must match: in package", tpcf.matches(CountingTestBean.class));
|
||||
assertFalse("Must be excluded: not subclass", tpcf.matches(IOther.class));
|
||||
assertFalse("Must be excluded: not subclass", tpcf.matches(DefaultListableBeanFactory.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAndOrNotReplacement() {
|
||||
TypePatternClassFilter tpcf = new TypePatternClassFilter("java.lang.Object or java.lang.String");
|
||||
assertFalse("matches Number",tpcf.matches(Number.class));
|
||||
assertTrue("matches Object",tpcf.matches(Object.class));
|
||||
assertTrue("matchesString",tpcf.matches(String.class));
|
||||
tpcf = new TypePatternClassFilter("java.lang.Number+ and java.lang.Float");
|
||||
assertTrue("matches Float",tpcf.matches(Float.class));
|
||||
assertFalse("matches Double",tpcf.matches(Double.class));
|
||||
tpcf = new TypePatternClassFilter("java.lang.Number+ and not java.lang.Float");
|
||||
assertFalse("matches Float",tpcf.matches(Float.class));
|
||||
assertTrue("matches Double",tpcf.matches(Double.class));
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testSetTypePatternWithNullArgument() throws Exception {
|
||||
new TypePatternClassFilter(null);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalStateException.class)
|
||||
public void testInvocationOfMatchesMethodBlowsUpWhenNoTypePatternHasBeenSet() throws Exception {
|
||||
new TypePatternClassFilter().matches(String.class);
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.aspectj.annotation;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Pointcut;
|
||||
import org.junit.Test;
|
||||
import org.springframework.aop.aspectj.AspectJAdviceParameterNameDiscoverer;
|
||||
|
||||
import test.beans.ITestBean;
|
||||
import test.beans.TestBean;
|
||||
|
||||
/**
|
||||
* @author Adrian Colyer
|
||||
* @author Juergen Hoeller
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public final class ArgumentBindingTests {
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testBindingInPointcutUsedByAdvice() {
|
||||
TestBean tb = new TestBean();
|
||||
AspectJProxyFactory proxyFactory = new AspectJProxyFactory(tb);
|
||||
proxyFactory.addAspect(NamedPointcutWithArgs.class);
|
||||
|
||||
ITestBean proxiedTestBean = (ITestBean) proxyFactory.getProxy();
|
||||
proxiedTestBean.setName("Supercalifragalisticexpialidocious"); // should throw
|
||||
}
|
||||
|
||||
@Test(expected=IllegalStateException.class)
|
||||
public void testAnnotationArgumentNameBinding() {
|
||||
TransactionalBean tb = new TransactionalBean();
|
||||
AspectJProxyFactory proxyFactory = new AspectJProxyFactory(tb);
|
||||
proxyFactory.addAspect(PointcutWithAnnotationArgument.class);
|
||||
|
||||
ITransactionalBean proxiedTestBean = (ITransactionalBean) proxyFactory.getProxy();
|
||||
proxiedTestBean.doInTransaction(); // should throw
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParameterNameDiscoverWithReferencePointcut() throws Exception {
|
||||
AspectJAdviceParameterNameDiscoverer discoverer =
|
||||
new AspectJAdviceParameterNameDiscoverer("somepc(formal) && set(* *)");
|
||||
discoverer.setRaiseExceptions(true);
|
||||
Method methodUsedForParameterTypeDiscovery =
|
||||
getClass().getMethod("methodWithOneParam", String.class);
|
||||
String[] pnames = discoverer.getParameterNames(methodUsedForParameterTypeDiscovery);
|
||||
assertEquals("one parameter name", 1, pnames.length);
|
||||
assertEquals("formal", pnames[0]);
|
||||
}
|
||||
|
||||
public void methodWithOneParam(String aParam) {
|
||||
}
|
||||
|
||||
|
||||
public interface ITransactionalBean {
|
||||
|
||||
@Transactional
|
||||
void doInTransaction();
|
||||
}
|
||||
|
||||
|
||||
public static class TransactionalBean implements ITransactionalBean {
|
||||
|
||||
@Transactional
|
||||
public void doInTransaction() {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents Spring's Transactional annotation without actually introducing the dependency
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@interface Transactional {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
@Aspect
|
||||
class PointcutWithAnnotationArgument {
|
||||
|
||||
@Around(value = "execution(* org.springframework..*.*(..)) && @annotation(transaction)")
|
||||
public Object around(ProceedingJoinPoint pjp, Transactional transaction) throws Throwable {
|
||||
System.out.println("Invoked with transaction " + transaction);
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @author Adrian Colyer
|
||||
*/
|
||||
@Aspect
|
||||
class NamedPointcutWithArgs {
|
||||
|
||||
@Pointcut("execution(* *(..)) && args(s,..)")
|
||||
public void pointcutWithArgs(String s) {}
|
||||
|
||||
@Around("pointcutWithArgs(aString)")
|
||||
public Object doAround(ProceedingJoinPoint pjp, String aString) throws Throwable {
|
||||
System.out.println("got '" + aString + "' at '" + pjp + "'");
|
||||
throw new IllegalArgumentException(aString);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.aspectj.annotation;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.aop.Pointcut;
|
||||
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
|
||||
import org.springframework.aop.aspectj.AspectJExpressionPointcutTests;
|
||||
import org.springframework.aop.framework.AopConfigException;
|
||||
|
||||
import test.aop.PerTargetAspect;
|
||||
import test.beans.TestBean;
|
||||
|
||||
|
||||
/**
|
||||
* @author Rod Johnson
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public final class AspectJPointcutAdvisorTests {
|
||||
|
||||
private AspectJAdvisorFactory af = new ReflectiveAspectJAdvisorFactory();
|
||||
|
||||
@Test
|
||||
public void testSingleton() throws SecurityException, NoSuchMethodException {
|
||||
AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut();
|
||||
ajexp.setExpression(AspectJExpressionPointcutTests.MATCH_ALL_METHODS);
|
||||
|
||||
InstantiationModelAwarePointcutAdvisorImpl ajpa = new InstantiationModelAwarePointcutAdvisorImpl(af, ajexp,
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new AbstractAspectJAdvisorFactoryTests.ExceptionAspect(null),"someBean"),
|
||||
TestBean.class.getMethod("getAge", (Class[]) null),1,"someBean");
|
||||
assertSame(Pointcut.TRUE, ajpa.getAspectMetadata().getPerClausePointcut());
|
||||
assertFalse(ajpa.isPerInstance());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPerTarget() throws SecurityException, NoSuchMethodException {
|
||||
AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut();
|
||||
ajexp.setExpression(AspectJExpressionPointcutTests.MATCH_ALL_METHODS);
|
||||
|
||||
InstantiationModelAwarePointcutAdvisorImpl ajpa = new InstantiationModelAwarePointcutAdvisorImpl(af, ajexp,
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new PerTargetAspect(),"someBean"), null, 1, "someBean");
|
||||
assertNotSame(Pointcut.TRUE, ajpa.getAspectMetadata().getPerClausePointcut());
|
||||
assertTrue(ajpa.getAspectMetadata().getPerClausePointcut() instanceof AspectJExpressionPointcut);
|
||||
assertTrue(ajpa.isPerInstance());
|
||||
|
||||
assertTrue(ajpa.getAspectMetadata().getPerClausePointcut().getClassFilter().matches(TestBean.class));
|
||||
assertFalse(ajpa.getAspectMetadata().getPerClausePointcut().getMethodMatcher().matches(
|
||||
TestBean.class.getMethod("getAge", (Class[]) null),
|
||||
TestBean.class));
|
||||
|
||||
assertTrue(ajpa.getAspectMetadata().getPerClausePointcut().getMethodMatcher().matches(
|
||||
TestBean.class.getMethod("getSpouse", (Class[]) null),
|
||||
TestBean.class));
|
||||
}
|
||||
|
||||
@Test(expected=AopConfigException.class)
|
||||
public void testPerCflowTarget() {
|
||||
testIllegalInstantiationModel(AbstractAspectJAdvisorFactoryTests.PerCflowAspect.class);
|
||||
}
|
||||
|
||||
@Test(expected=AopConfigException.class)
|
||||
public void testPerCflowBelowTarget() {
|
||||
testIllegalInstantiationModel(AbstractAspectJAdvisorFactoryTests.PerCflowBelowAspect.class);
|
||||
}
|
||||
|
||||
private void testIllegalInstantiationModel(Class<?> c) throws AopConfigException {
|
||||
new AspectMetadata(c,"someBean");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.aspectj.annotation;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import org.aspectj.lang.reflect.PerClauseKind;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.aop.Pointcut;
|
||||
import org.springframework.aop.aspectj.annotation.AbstractAspectJAdvisorFactoryTests.ExceptionAspect;
|
||||
|
||||
import test.aop.PerTargetAspect;
|
||||
|
||||
|
||||
/**
|
||||
* @since 2.0
|
||||
* @author Rod Johnson
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public final class AspectMetadataTests {
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testNotAnAspect() {
|
||||
new AspectMetadata(String.class,"someBean");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingletonAspect() {
|
||||
AspectMetadata am = new AspectMetadata(ExceptionAspect.class,"someBean");
|
||||
assertFalse(am.isPerThisOrPerTarget());
|
||||
assertSame(Pointcut.TRUE, am.getPerClausePointcut());
|
||||
assertEquals(PerClauseKind.SINGLETON, am.getAjType().getPerClause().getKind());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPerTargetAspect() {
|
||||
AspectMetadata am = new AspectMetadata(PerTargetAspect.class,"someBean");
|
||||
assertTrue(am.isPerThisOrPerTarget());
|
||||
assertNotSame(Pointcut.TRUE, am.getPerClausePointcut());
|
||||
assertEquals(PerClauseKind.PERTARGET, am.getAjType().getPerClause().getKind());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPerThisAspect() {
|
||||
AspectMetadata am = new AspectMetadata(PerThisAspect.class,"someBean");
|
||||
assertTrue(am.isPerThisOrPerTarget());
|
||||
assertNotSame(Pointcut.TRUE, am.getPerClausePointcut());
|
||||
assertEquals(PerClauseKind.PERTHIS, am.getAjType().getPerClause().getKind());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* Copyright 2002-2010 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.aspectj.annotation;
|
||||
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import test.aop.PerThisAspect;
|
||||
import test.util.SerializationTestUtils;
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
* @author Juergen Hoeller
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public final class AspectProxyFactoryTests {
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testWithNonAspect() {
|
||||
AspectJProxyFactory proxyFactory = new AspectJProxyFactory(new TestBean());
|
||||
proxyFactory.addAspect(TestBean.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithSimpleAspect() throws Exception {
|
||||
TestBean bean = new TestBean();
|
||||
bean.setAge(2);
|
||||
AspectJProxyFactory proxyFactory = new AspectJProxyFactory(bean);
|
||||
proxyFactory.addAspect(MultiplyReturnValue.class);
|
||||
ITestBean proxy = proxyFactory.getProxy();
|
||||
assertEquals("Multiplication did not occur", bean.getAge() * 2, proxy.getAge());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithPerThisAspect() throws Exception {
|
||||
TestBean bean1 = new TestBean();
|
||||
TestBean bean2 = new TestBean();
|
||||
|
||||
AspectJProxyFactory pf1 = new AspectJProxyFactory(bean1);
|
||||
pf1.addAspect(PerThisAspect.class);
|
||||
|
||||
AspectJProxyFactory pf2 = new AspectJProxyFactory(bean2);
|
||||
pf2.addAspect(PerThisAspect.class);
|
||||
|
||||
ITestBean proxy1 = pf1.getProxy();
|
||||
ITestBean proxy2 = pf2.getProxy();
|
||||
|
||||
assertEquals(0, proxy1.getAge());
|
||||
assertEquals(1, proxy1.getAge());
|
||||
assertEquals(0, proxy2.getAge());
|
||||
assertEquals(2, proxy1.getAge());
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testWithInstanceWithNonAspect() throws Exception {
|
||||
AspectJProxyFactory pf = new AspectJProxyFactory();
|
||||
pf.addAspect(new TestBean());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore // InstantiationModelAwarePointcutAdvisorImpl not serializable yet
|
||||
public void testWithInstance() throws Exception {
|
||||
MultiplyReturnValue aspect = new MultiplyReturnValue();
|
||||
int multiple = 3;
|
||||
aspect.setMultiple(multiple);
|
||||
|
||||
TestBean target = new TestBean();
|
||||
target.setAge(24);
|
||||
|
||||
AspectJProxyFactory proxyFactory = new AspectJProxyFactory(target);
|
||||
proxyFactory.addAspect(aspect);
|
||||
|
||||
ITestBean proxy = proxyFactory.getProxy();
|
||||
assertEquals(target.getAge() * multiple, proxy.getAge());
|
||||
|
||||
ITestBean serializedProxy = (ITestBean) SerializationTestUtils.serializeAndDeserialize(proxy);
|
||||
assertEquals(target.getAge() * multiple, serializedProxy.getAge());
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testWithNonSingletonAspectInstance() throws Exception {
|
||||
AspectJProxyFactory pf = new AspectJProxyFactory();
|
||||
pf.addAspect(new PerThisAspect());
|
||||
}
|
||||
|
||||
|
||||
public static interface ITestBean {
|
||||
|
||||
int getAge();
|
||||
}
|
||||
|
||||
|
||||
public static class TestBean implements ITestBean {
|
||||
|
||||
private int age;
|
||||
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @author Rod Johnson
|
||||
*/
|
||||
@Aspect
|
||||
class MultiplyReturnValue {
|
||||
|
||||
private int multiple = 2;
|
||||
|
||||
public int invocations;
|
||||
|
||||
public void setMultiple(int multiple) {
|
||||
this.multiple = multiple;
|
||||
}
|
||||
|
||||
public int getMultiple() {
|
||||
return this.multiple;
|
||||
}
|
||||
|
||||
@Around("execution(int *.getAge())")
|
||||
public Object doubleReturnValue(ProceedingJoinPoint pjp) throws Throwable {
|
||||
++this.invocations;
|
||||
int result = (Integer) pjp.proceed();
|
||||
return result * this.multiple;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2002-2006 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.aspectj.annotation;
|
||||
|
||||
/**
|
||||
* Tests for ReflectiveAtAspectJAdvisorFactory.
|
||||
* Tests are inherited: we only set the test fixture here.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @since 2.0
|
||||
*/
|
||||
public final class ReflectiveAspectJAdvisorFactoryTests extends AbstractAspectJAdvisorFactoryTests {
|
||||
|
||||
@Override
|
||||
protected AspectJAdvisorFactory getFixture() {
|
||||
return new ReflectiveAspectJAdvisorFactory();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.aspectj.autoproxy;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.aop.config.AopConfigUtils;
|
||||
import org.springframework.aop.config.AopNamespaceUtils;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.parsing.PassThroughSourceExtractor;
|
||||
import org.springframework.beans.factory.parsing.SourceExtractor;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
|
||||
import org.springframework.beans.factory.xml.XmlReaderContext;
|
||||
|
||||
import test.parsing.CollectingReaderEventListener;
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public final class AspectJNamespaceHandlerTests {
|
||||
|
||||
private ParserContext parserContext;
|
||||
|
||||
private CollectingReaderEventListener readerEventListener = new CollectingReaderEventListener();
|
||||
|
||||
private BeanDefinitionRegistry registry = new DefaultListableBeanFactory();
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
SourceExtractor sourceExtractor = new PassThroughSourceExtractor();
|
||||
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this.registry);
|
||||
XmlReaderContext readerContext =
|
||||
new XmlReaderContext(null, null, this.readerEventListener, sourceExtractor, reader, null);
|
||||
this.parserContext = new ParserContext(readerContext, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegisterAutoProxyCreator() throws Exception {
|
||||
AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(this.parserContext, null);
|
||||
assertEquals("Incorrect number of definitions registered", 1, registry.getBeanDefinitionCount());
|
||||
|
||||
AopNamespaceUtils.registerAspectJAutoProxyCreatorIfNecessary(this.parserContext, null);
|
||||
assertEquals("Incorrect number of definitions registered", 1, registry.getBeanDefinitionCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegisterAspectJAutoProxyCreator() throws Exception {
|
||||
AopNamespaceUtils.registerAspectJAutoProxyCreatorIfNecessary(this.parserContext, null);
|
||||
assertEquals("Incorrect number of definitions registered", 1, registry.getBeanDefinitionCount());
|
||||
|
||||
AopNamespaceUtils.registerAspectJAutoProxyCreatorIfNecessary(this.parserContext, null);
|
||||
assertEquals("Incorrect number of definitions registered", 1, registry.getBeanDefinitionCount());
|
||||
|
||||
BeanDefinition definition = registry.getBeanDefinition(AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME);
|
||||
assertEquals("Incorrect APC class",
|
||||
AspectJAwareAdvisorAutoProxyCreator.class.getName(), definition.getBeanClassName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegisterAspectJAutoProxyCreatorWithExistingAutoProxyCreator() throws Exception {
|
||||
AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(this.parserContext, null);
|
||||
assertEquals(1, registry.getBeanDefinitionCount());
|
||||
|
||||
AopNamespaceUtils.registerAspectJAutoProxyCreatorIfNecessary(this.parserContext, null);
|
||||
assertEquals("Incorrect definition count", 1, registry.getBeanDefinitionCount());
|
||||
|
||||
BeanDefinition definition = registry.getBeanDefinition(AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME);
|
||||
assertEquals("APC class not switched",
|
||||
AspectJAwareAdvisorAutoProxyCreator.class.getName(), definition.getBeanClassName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegisterAutoProxyCreatorWhenAspectJAutoProxyCreatorAlreadyExists() throws Exception {
|
||||
AopNamespaceUtils.registerAspectJAutoProxyCreatorIfNecessary(this.parserContext, null);
|
||||
assertEquals(1, registry.getBeanDefinitionCount());
|
||||
|
||||
AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(this.parserContext, null);
|
||||
assertEquals("Incorrect definition count", 1, registry.getBeanDefinitionCount());
|
||||
|
||||
BeanDefinition definition = registry.getBeanDefinition(AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME);
|
||||
assertEquals("Incorrect APC class",
|
||||
AspectJAwareAdvisorAutoProxyCreator.class.getName(), definition.getBeanClassName());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,236 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.aspectj.autoproxy;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.aop.Advisor;
|
||||
import org.springframework.aop.AfterReturningAdvice;
|
||||
import org.springframework.aop.BeforeAdvice;
|
||||
import org.springframework.aop.aspectj.AbstractAspectJAdvice;
|
||||
import org.springframework.aop.aspectj.AspectJAfterAdvice;
|
||||
import org.springframework.aop.aspectj.AspectJAfterReturningAdvice;
|
||||
import org.springframework.aop.aspectj.AspectJAfterThrowingAdvice;
|
||||
import org.springframework.aop.aspectj.AspectJAroundAdvice;
|
||||
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
|
||||
import org.springframework.aop.aspectj.AspectJMethodBeforeAdvice;
|
||||
import org.springframework.aop.aspectj.AspectJPointcutAdvisor;
|
||||
import org.springframework.aop.support.DefaultPointcutAdvisor;
|
||||
|
||||
/**
|
||||
* @author Adrian Colyer
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public final class AspectJPrecedenceComparatorTests {
|
||||
|
||||
/*
|
||||
* Specification for the comparator (as defined in the
|
||||
* AspectJPrecedenceComparator class)
|
||||
*
|
||||
* <p>
|
||||
* Orders AspectJ advice/advisors by invocation order.
|
||||
* </p>
|
||||
* <p>
|
||||
* Given two pieces of advice, <code>a</code> and <code>b</code>:
|
||||
* </p>
|
||||
* <ul>
|
||||
* <li>if <code>a</code> and <code>b</code> are defined in different
|
||||
* aspects, then the advice in the aspect with the lowest order
|
||||
* value has the highest precedence</li>
|
||||
* <li>if <code>a</code> and <code>b</code> are defined in the same
|
||||
* aspect, then if one of <code>a</code> or <code>b</code> is a form of
|
||||
* after advice, then the advice declared last in the aspect has the
|
||||
* highest precedence. If neither <code>a</code> nor <code>b</code> is a
|
||||
* form of after advice, then the advice declared first in the aspect has
|
||||
* the highest precedence.</li>
|
||||
* </ul>
|
||||
*/
|
||||
|
||||
private static final int HIGH_PRECEDENCE_ADVISOR_ORDER = 100;
|
||||
private static final int LOW_PRECEDENCE_ADVISOR_ORDER = 200;
|
||||
private static final int EARLY_ADVICE_DECLARATION_ORDER = 5;
|
||||
private static final int LATE_ADVICE_DECLARATION_ORDER = 10;
|
||||
|
||||
|
||||
private AspectJPrecedenceComparator comparator;
|
||||
|
||||
private Method anyOldMethod;
|
||||
|
||||
private AspectJExpressionPointcut anyOldPointcut;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
this.comparator = new AspectJPrecedenceComparator();
|
||||
this.anyOldMethod = getClass().getMethods()[0];
|
||||
this.anyOldPointcut = new AspectJExpressionPointcut();
|
||||
this.anyOldPointcut.setExpression("execution(* *(..))");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSameAspectNoAfterAdvice() {
|
||||
Advisor advisor1 = createAspectJBeforeAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, EARLY_ADVICE_DECLARATION_ORDER, "someAspect");
|
||||
Advisor advisor2 = createAspectJBeforeAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, LATE_ADVICE_DECLARATION_ORDER, "someAspect");
|
||||
assertEquals("advisor1 sorted before advisor2", -1, this.comparator.compare(advisor1, advisor2));
|
||||
|
||||
advisor1 = createAspectJBeforeAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, LATE_ADVICE_DECLARATION_ORDER, "someAspect");
|
||||
advisor2 = createAspectJAroundAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, EARLY_ADVICE_DECLARATION_ORDER, "someAspect");
|
||||
assertEquals("advisor2 sorted before advisor1", 1, this.comparator.compare(advisor1, advisor2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSameAspectAfterAdvice() {
|
||||
Advisor advisor1 = createAspectJAfterAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, EARLY_ADVICE_DECLARATION_ORDER, "someAspect");
|
||||
Advisor advisor2 = createAspectJAroundAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, LATE_ADVICE_DECLARATION_ORDER, "someAspect");
|
||||
assertEquals("advisor2 sorted before advisor1", 1, this.comparator.compare(advisor1, advisor2));
|
||||
|
||||
advisor1 = createAspectJAfterReturningAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, LATE_ADVICE_DECLARATION_ORDER, "someAspect");
|
||||
advisor2 = createAspectJAfterThrowingAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, EARLY_ADVICE_DECLARATION_ORDER, "someAspect");
|
||||
assertEquals("advisor1 sorted before advisor2", -1, this.comparator.compare(advisor1, advisor2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSameAspectOneOfEach() {
|
||||
Advisor advisor1 = createAspectJAfterAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, EARLY_ADVICE_DECLARATION_ORDER, "someAspect");
|
||||
Advisor advisor2 = createAspectJBeforeAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, LATE_ADVICE_DECLARATION_ORDER, "someAspect");
|
||||
assertEquals("advisor1 and advisor2 not comparable", 0, this.comparator.compare(advisor1, advisor2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSameAdvisorPrecedenceDifferentAspectNoAfterAdvice() {
|
||||
Advisor advisor1 = createAspectJBeforeAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, EARLY_ADVICE_DECLARATION_ORDER, "someAspect");
|
||||
Advisor advisor2 = createAspectJBeforeAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, LATE_ADVICE_DECLARATION_ORDER, "someOtherAspect");
|
||||
assertEquals("nothing to say about order here", 0, this.comparator.compare(advisor1, advisor2));
|
||||
|
||||
advisor1 = createAspectJBeforeAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, LATE_ADVICE_DECLARATION_ORDER, "someAspect");
|
||||
advisor2 = createAspectJAroundAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, EARLY_ADVICE_DECLARATION_ORDER, "someOtherAspect");
|
||||
assertEquals("nothing to say about order here", 0, this.comparator.compare(advisor1, advisor2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSameAdvisorPrecedenceDifferentAspectAfterAdvice() {
|
||||
Advisor advisor1 = createAspectJAfterAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, EARLY_ADVICE_DECLARATION_ORDER, "someAspect");
|
||||
Advisor advisor2 = createAspectJAroundAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, LATE_ADVICE_DECLARATION_ORDER, "someOtherAspect");
|
||||
assertEquals("nothing to say about order here", 0, this.comparator.compare(advisor1, advisor2));
|
||||
|
||||
advisor1 = createAspectJAfterReturningAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, LATE_ADVICE_DECLARATION_ORDER, "someAspect");
|
||||
advisor2 = createAspectJAfterThrowingAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, EARLY_ADVICE_DECLARATION_ORDER, "someOtherAspect");
|
||||
assertEquals("nothing to say about order here", 0, this.comparator.compare(advisor1, advisor2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHigherAdvisorPrecedenceNoAfterAdvice() {
|
||||
Advisor advisor1 = createSpringAOPBeforeAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER);
|
||||
Advisor advisor2 = createAspectJBeforeAdvice(LOW_PRECEDENCE_ADVISOR_ORDER, EARLY_ADVICE_DECLARATION_ORDER, "someOtherAspect");
|
||||
assertEquals("advisor1 sorted before advisor2", -1, this.comparator.compare(advisor1, advisor2));
|
||||
|
||||
advisor1 = createAspectJBeforeAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, LATE_ADVICE_DECLARATION_ORDER, "someAspect");
|
||||
advisor2 = createAspectJAroundAdvice(LOW_PRECEDENCE_ADVISOR_ORDER, EARLY_ADVICE_DECLARATION_ORDER, "someOtherAspect");
|
||||
assertEquals("advisor1 sorted before advisor2", -1, this.comparator.compare(advisor1, advisor2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHigherAdvisorPrecedenceAfterAdvice() {
|
||||
Advisor advisor1 = createAspectJAfterAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, EARLY_ADVICE_DECLARATION_ORDER, "someAspect");
|
||||
Advisor advisor2 = createAspectJAroundAdvice(LOW_PRECEDENCE_ADVISOR_ORDER, LATE_ADVICE_DECLARATION_ORDER, "someOtherAspect");
|
||||
assertEquals("advisor1 sorted before advisor2", -1, this.comparator.compare(advisor1, advisor2));
|
||||
|
||||
advisor1 = createAspectJAfterReturningAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, LATE_ADVICE_DECLARATION_ORDER, "someAspect");
|
||||
advisor2 = createAspectJAfterThrowingAdvice(LOW_PRECEDENCE_ADVISOR_ORDER, EARLY_ADVICE_DECLARATION_ORDER, "someOtherAspect");
|
||||
assertEquals("advisor2 sorted after advisor1", -1, this.comparator.compare(advisor1, advisor2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLowerAdvisorPrecedenceNoAfterAdvice() {
|
||||
Advisor advisor1 = createAspectJBeforeAdvice(LOW_PRECEDENCE_ADVISOR_ORDER, EARLY_ADVICE_DECLARATION_ORDER, "someAspect");
|
||||
Advisor advisor2 = createAspectJBeforeAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, EARLY_ADVICE_DECLARATION_ORDER, "someOtherAspect");
|
||||
assertEquals("advisor1 sorted after advisor2", 1, this.comparator.compare(advisor1, advisor2));
|
||||
|
||||
advisor1 = createAspectJBeforeAdvice(LOW_PRECEDENCE_ADVISOR_ORDER, LATE_ADVICE_DECLARATION_ORDER, "someAspect");
|
||||
advisor2 = createAspectJAroundAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, EARLY_ADVICE_DECLARATION_ORDER, "someOtherAspect");
|
||||
assertEquals("advisor1 sorted after advisor2", 1, this.comparator.compare(advisor1, advisor2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLowerAdvisorPrecedenceAfterAdvice() {
|
||||
Advisor advisor1 = createAspectJAfterAdvice(LOW_PRECEDENCE_ADVISOR_ORDER, EARLY_ADVICE_DECLARATION_ORDER, "someAspect");
|
||||
Advisor advisor2 = createAspectJAroundAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, LATE_ADVICE_DECLARATION_ORDER, "someOtherAspect");
|
||||
assertEquals("advisor1 sorted after advisor2", 1, this.comparator.compare(advisor1, advisor2));
|
||||
|
||||
advisor1 = createSpringAOPAfterAdvice(LOW_PRECEDENCE_ADVISOR_ORDER);
|
||||
advisor2 = createAspectJAfterThrowingAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, EARLY_ADVICE_DECLARATION_ORDER, "someOtherAspect");
|
||||
assertEquals("advisor1 sorted after advisor2", 1, this.comparator.compare(advisor1, advisor2));
|
||||
}
|
||||
|
||||
|
||||
private Advisor createAspectJBeforeAdvice(int advisorOrder, int adviceDeclarationOrder, String aspectName) {
|
||||
AspectJMethodBeforeAdvice advice = new AspectJMethodBeforeAdvice(this.anyOldMethod, this.anyOldPointcut, null);
|
||||
return createAspectJAdvice(advisorOrder, adviceDeclarationOrder, aspectName, advice);
|
||||
}
|
||||
|
||||
private Advisor createAspectJAroundAdvice(int advisorOrder, int adviceDeclarationOrder, String aspectName) {
|
||||
AspectJAroundAdvice advice = new AspectJAroundAdvice(this.anyOldMethod, this.anyOldPointcut, null);
|
||||
return createAspectJAdvice(advisorOrder, adviceDeclarationOrder, aspectName, advice);
|
||||
}
|
||||
|
||||
private Advisor createAspectJAfterAdvice(int advisorOrder, int adviceDeclarationOrder, String aspectName) {
|
||||
AspectJAfterAdvice advice = new AspectJAfterAdvice(this.anyOldMethod, this.anyOldPointcut, null);
|
||||
return createAspectJAdvice(advisorOrder, adviceDeclarationOrder, aspectName, advice);
|
||||
}
|
||||
|
||||
private Advisor createAspectJAfterReturningAdvice(int advisorOrder, int adviceDeclarationOrder, String aspectName) {
|
||||
AspectJAfterReturningAdvice advice = new AspectJAfterReturningAdvice(this.anyOldMethod, this.anyOldPointcut, null);
|
||||
return createAspectJAdvice(advisorOrder, adviceDeclarationOrder, aspectName, advice);
|
||||
}
|
||||
|
||||
private Advisor createAspectJAfterThrowingAdvice(int advisorOrder, int adviceDeclarationOrder, String aspectName) {
|
||||
AspectJAfterThrowingAdvice advice = new AspectJAfterThrowingAdvice(this.anyOldMethod, this.anyOldPointcut, null);
|
||||
return createAspectJAdvice(advisorOrder, adviceDeclarationOrder, aspectName, advice);
|
||||
}
|
||||
|
||||
private Advisor createAspectJAdvice(int advisorOrder, int adviceDeclarationOrder, String aspectName, AbstractAspectJAdvice advice) {
|
||||
advice.setDeclarationOrder(adviceDeclarationOrder);
|
||||
advice.setAspectName(aspectName);
|
||||
AspectJPointcutAdvisor advisor = new AspectJPointcutAdvisor(advice);
|
||||
advisor.setOrder(advisorOrder);
|
||||
return advisor;
|
||||
}
|
||||
|
||||
private Advisor createSpringAOPAfterAdvice(int order) {
|
||||
AfterReturningAdvice advice = new AfterReturningAdvice() {
|
||||
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
|
||||
}
|
||||
};
|
||||
DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(this.anyOldPointcut, advice);
|
||||
advisor.setOrder(order);
|
||||
return advisor;
|
||||
}
|
||||
|
||||
private Advisor createSpringAOPBeforeAdvice(int order) {
|
||||
BeforeAdvice advice = new BeforeAdvice() {
|
||||
};
|
||||
DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(this.anyOldPointcut, advice);
|
||||
advisor.setOrder(order);
|
||||
return advisor;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:aop="http://www.springframework.org/schema/aop"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
|
||||
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
|
||||
|
||||
<aop:config>
|
||||
<aop:aspect id="countAgeCalls" ref="countingAdvice">
|
||||
<aop:pointcut id="pc" expression="execution(* getAge())"/>
|
||||
<aop:before pointcut-ref="pc" method="myBeforeAdvice" />
|
||||
<aop:after pointcut-ref="pc" method="myAfterAdvice" />
|
||||
<aop:after-returning pointcut-ref="pc" method="myAfterReturningAdvice" returning="age"/>
|
||||
<aop:after-throwing pointcut-ref="pc" method="myAfterThrowingAdvice" throwing="ex"/>
|
||||
<aop:around pointcut-ref="pc" method="myAroundAdvice"/>
|
||||
</aop:aspect>
|
||||
</aop:config>
|
||||
|
||||
<bean id="getNameCounter" class="org.springframework.aop.framework.CountingBeforeAdvice"/>
|
||||
|
||||
<bean id="getAgeCounter" class="org.springframework.aop.framework.CountingBeforeAdvice"/>
|
||||
|
||||
<bean id="testBean" class="test.beans.TestBean"/>
|
||||
|
||||
<bean id="countingAdvice" class="org.springframework.aop.config.CountingAspectJAdvice"/>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:aop="http://www.springframework.org/schema/aop"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
|
||||
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
|
||||
|
||||
<aop:config>
|
||||
<aop:advisor advice-ref="countingAdvice" pointcut="within(org.springframework..*)"/>
|
||||
</aop:config>
|
||||
|
||||
<bean id="countingAdvice" class="org.springframework.aop.framework.CountingBeforeAdvice"/>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:aop="http://www.springframework.org/schema/aop"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
|
||||
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
|
||||
|
||||
<aop:config>
|
||||
<aop:pointcut id="myPointcut" expression="within(org.springframework..*)"/>
|
||||
</aop:config>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:aop="http://www.springframework.org/schema/aop"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
|
||||
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
|
||||
|
||||
<aop:config>
|
||||
<aop:pointcut id="pc" expression="within(org.springframework..*)"/>
|
||||
<aop:advisor advice-ref="countingAdvice" pointcut-ref="pc"/>
|
||||
</aop:config>
|
||||
|
||||
<bean id="countingAdvice" class="org.springframework.aop.framework.CountingBeforeAdvice"/>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,195 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.config;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static test.util.TestResourceUtils.qualifiedResource;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanReference;
|
||||
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
||||
import org.springframework.beans.factory.parsing.ComponentDefinition;
|
||||
import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
|
||||
import org.springframework.core.io.Resource;
|
||||
|
||||
import test.parsing.CollectingReaderEventListener;
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
* @author Juergen Hoeller
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public final class AopNamespaceHandlerEventTests {
|
||||
|
||||
private static final Class<?> CLASS = AopNamespaceHandlerEventTests.class;
|
||||
|
||||
private static final Resource CONTEXT = qualifiedResource(CLASS, "context.xml");
|
||||
private static final Resource POINTCUT_EVENTS_CONTEXT = qualifiedResource(CLASS, "pointcutEvents.xml");
|
||||
private static final Resource POINTCUT_REF_CONTEXT = qualifiedResource(CLASS, "pointcutRefEvents.xml");
|
||||
private static final Resource DIRECT_POINTCUT_EVENTS_CONTEXT = qualifiedResource(CLASS, "directPointcutEvents.xml");
|
||||
|
||||
private CollectingReaderEventListener eventListener = new CollectingReaderEventListener();
|
||||
|
||||
private XmlBeanDefinitionReader reader;
|
||||
|
||||
private DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
||||
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
this.reader = new XmlBeanDefinitionReader(this.beanFactory);
|
||||
this.reader.setEventListener(this.eventListener);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPointcutEvents() throws Exception {
|
||||
this.reader.loadBeanDefinitions(POINTCUT_EVENTS_CONTEXT);
|
||||
ComponentDefinition[] componentDefinitions = this.eventListener.getComponentDefinitions();
|
||||
assertEquals("Incorrect number of events fired", 1, componentDefinitions.length);
|
||||
assertTrue("No holder with nested components", componentDefinitions[0] instanceof CompositeComponentDefinition);
|
||||
|
||||
CompositeComponentDefinition compositeDef = (CompositeComponentDefinition) componentDefinitions[0];
|
||||
assertEquals("aop:config", compositeDef.getName());
|
||||
|
||||
ComponentDefinition[] nestedComponentDefs = compositeDef.getNestedComponents();
|
||||
assertEquals("Incorrect number of inner components", 2, nestedComponentDefs.length);
|
||||
PointcutComponentDefinition pcd = null;
|
||||
for (int i = 0; i < nestedComponentDefs.length; i++) {
|
||||
ComponentDefinition componentDefinition = nestedComponentDefs[i];
|
||||
if (componentDefinition instanceof PointcutComponentDefinition) {
|
||||
pcd = (PointcutComponentDefinition) componentDefinition;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assertNotNull("PointcutComponentDefinition not found", pcd);
|
||||
assertEquals("Incorrect number of BeanDefinitions", 1, pcd.getBeanDefinitions().length);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAdvisorEventsWithPointcutRef() throws Exception {
|
||||
this.reader.loadBeanDefinitions(POINTCUT_REF_CONTEXT);
|
||||
ComponentDefinition[] componentDefinitions = this.eventListener.getComponentDefinitions();
|
||||
assertEquals("Incorrect number of events fired", 2, componentDefinitions.length);
|
||||
|
||||
assertTrue("No holder with nested components", componentDefinitions[0] instanceof CompositeComponentDefinition);
|
||||
CompositeComponentDefinition compositeDef = (CompositeComponentDefinition) componentDefinitions[0];
|
||||
assertEquals("aop:config", compositeDef.getName());
|
||||
|
||||
ComponentDefinition[] nestedComponentDefs = compositeDef.getNestedComponents();
|
||||
assertEquals("Incorrect number of inner components", 3, nestedComponentDefs.length);
|
||||
AdvisorComponentDefinition acd = null;
|
||||
for (int i = 0; i < nestedComponentDefs.length; i++) {
|
||||
ComponentDefinition componentDefinition = nestedComponentDefs[i];
|
||||
if (componentDefinition instanceof AdvisorComponentDefinition) {
|
||||
acd = (AdvisorComponentDefinition) componentDefinition;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assertNotNull("AdvisorComponentDefinition not found", acd);
|
||||
assertEquals(1, acd.getBeanDefinitions().length);
|
||||
assertEquals(2, acd.getBeanReferences().length);
|
||||
|
||||
assertTrue("No advice bean found", componentDefinitions[1] instanceof BeanComponentDefinition);
|
||||
BeanComponentDefinition adviceDef = (BeanComponentDefinition) componentDefinitions[1];
|
||||
assertEquals("countingAdvice", adviceDef.getBeanName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAdvisorEventsWithDirectPointcut() throws Exception {
|
||||
this.reader.loadBeanDefinitions(DIRECT_POINTCUT_EVENTS_CONTEXT);
|
||||
ComponentDefinition[] componentDefinitions = this.eventListener.getComponentDefinitions();
|
||||
assertEquals("Incorrect number of events fired", 2, componentDefinitions.length);
|
||||
|
||||
assertTrue("No holder with nested components", componentDefinitions[0] instanceof CompositeComponentDefinition);
|
||||
CompositeComponentDefinition compositeDef = (CompositeComponentDefinition) componentDefinitions[0];
|
||||
assertEquals("aop:config", compositeDef.getName());
|
||||
|
||||
ComponentDefinition[] nestedComponentDefs = compositeDef.getNestedComponents();
|
||||
assertEquals("Incorrect number of inner components", 2, nestedComponentDefs.length);
|
||||
AdvisorComponentDefinition acd = null;
|
||||
for (int i = 0; i < nestedComponentDefs.length; i++) {
|
||||
ComponentDefinition componentDefinition = nestedComponentDefs[i];
|
||||
if (componentDefinition instanceof AdvisorComponentDefinition) {
|
||||
acd = (AdvisorComponentDefinition) componentDefinition;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assertNotNull("AdvisorComponentDefinition not found", acd);
|
||||
assertEquals(2, acd.getBeanDefinitions().length);
|
||||
assertEquals(1, acd.getBeanReferences().length);
|
||||
|
||||
assertTrue("No advice bean found", componentDefinitions[1] instanceof BeanComponentDefinition);
|
||||
BeanComponentDefinition adviceDef = (BeanComponentDefinition) componentDefinitions[1];
|
||||
assertEquals("countingAdvice", adviceDef.getBeanName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAspectEvent() throws Exception {
|
||||
this.reader.loadBeanDefinitions(CONTEXT);
|
||||
ComponentDefinition[] componentDefinitions = this.eventListener.getComponentDefinitions();
|
||||
assertEquals("Incorrect number of events fired", 5, componentDefinitions.length);
|
||||
|
||||
assertTrue("No holder with nested components", componentDefinitions[0] instanceof CompositeComponentDefinition);
|
||||
CompositeComponentDefinition compositeDef = (CompositeComponentDefinition) componentDefinitions[0];
|
||||
assertEquals("aop:config", compositeDef.getName());
|
||||
|
||||
ComponentDefinition[] nestedComponentDefs = compositeDef.getNestedComponents();
|
||||
assertEquals("Incorrect number of inner components", 2, nestedComponentDefs.length);
|
||||
AspectComponentDefinition acd = null;
|
||||
for (int i = 0; i < nestedComponentDefs.length; i++) {
|
||||
ComponentDefinition componentDefinition = nestedComponentDefs[i];
|
||||
if (componentDefinition instanceof AspectComponentDefinition) {
|
||||
acd = (AspectComponentDefinition) componentDefinition;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assertNotNull("AspectComponentDefinition not found", acd);
|
||||
BeanDefinition[] beanDefinitions = acd.getBeanDefinitions();
|
||||
assertEquals(5, beanDefinitions.length);
|
||||
BeanReference[] beanReferences = acd.getBeanReferences();
|
||||
assertEquals(6, beanReferences.length);
|
||||
|
||||
Set<String> expectedReferences = new HashSet<String>();
|
||||
expectedReferences.add("pc");
|
||||
expectedReferences.add("countingAdvice");
|
||||
for (int i = 0; i < beanReferences.length; i++) {
|
||||
BeanReference beanReference = beanReferences[i];
|
||||
expectedReferences.remove(beanReference.getBeanName());
|
||||
}
|
||||
assertEquals("Incorrect references found", 0, expectedReferences.size());
|
||||
|
||||
for (int i = 1; i < componentDefinitions.length; i++) {
|
||||
assertTrue(componentDefinitions[i] instanceof BeanComponentDefinition);
|
||||
}
|
||||
|
||||
ComponentDefinition[] nestedComponentDefs2 = acd.getNestedComponents();
|
||||
assertEquals("Inner PointcutComponentDefinition not found", 1, nestedComponentDefs2.length);
|
||||
assertTrue(nestedComponentDefs2[0] instanceof PointcutComponentDefinition);
|
||||
PointcutComponentDefinition pcd = (PointcutComponentDefinition) nestedComponentDefs2[0];
|
||||
assertEquals("Incorrect number of BeanDefinitions", 1, pcd.getBeanDefinitions().length);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:aop="http://www.springframework.org/schema/aop"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
|
||||
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
|
||||
|
||||
<aop:config>
|
||||
<aop:aspect id="countAgeCalls" ref="countingAdvice">
|
||||
<aop:pointcut id="pc" expression="execution(* getAge())"/>
|
||||
<aop:before pointcut-ref="pc" pointcut="execution(* getAge())" method="myBeforeAdvice"/>
|
||||
</aop:aspect>
|
||||
</aop:config>
|
||||
|
||||
<bean id="getAgeCounter" class="org.springframework.aop.framework.CountingBeforeAdvice"/>
|
||||
|
||||
<bean id="testBean" class="test.beans.TestBean"/>
|
||||
|
||||
<bean id="countingAdvice" class="org.springframework.aop.config.CountingAspectJAdvice"/>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:aop="http://www.springframework.org/schema/aop"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
|
||||
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
|
||||
|
||||
<aop:config>
|
||||
<aop:aspect id="countAgeCalls" ref="countingAdvice">
|
||||
<aop:pointcut id="pc" expression="execution(* getAge())"/>
|
||||
<aop:before method="myBeforeAdvice" />
|
||||
</aop:aspect>
|
||||
</aop:config>
|
||||
|
||||
<bean id="getAgeCounter" class="org.springframework.aop.framework.CountingBeforeAdvice"/>
|
||||
|
||||
<bean id="testBean" class="test.beans.TestBean"/>
|
||||
|
||||
<bean id="countingAdvice" class="org.springframework.aop.config.CountingAspectJAdvice"/>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.config;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static test.util.TestResourceUtils.qualifiedResource;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||
import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
|
||||
import org.springframework.beans.factory.xml.XmlBeanFactory;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public final class AopNamespaceHandlerPointcutErrorTests {
|
||||
|
||||
@Test
|
||||
public void testDuplicatePointcutConfig() {
|
||||
try {
|
||||
new XmlBeanFactory(qualifiedResource(getClass(), "pointcutDuplication.xml"));
|
||||
fail("parsing should have caused a BeanDefinitionStoreException");
|
||||
}
|
||||
catch (BeanDefinitionStoreException ex) {
|
||||
assertTrue(ex.contains(BeanDefinitionParsingException.class));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMissingPointcutConfig() {
|
||||
try {
|
||||
new XmlBeanFactory(qualifiedResource(getClass(), "pointcutMissing.xml"));
|
||||
fail("parsing should have caused a BeanDefinitionStoreException");
|
||||
}
|
||||
catch (BeanDefinitionStoreException ex) {
|
||||
assertTrue(ex.contains(BeanDefinitionParsingException.class));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<config xmlns="http://www.springframework.org/schema/aop"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
|
||||
|
||||
<pointcut id="testPointcut" expression="execution(* foo(..)) and within(springbank.dao.AccountDao+)"/>
|
||||
<pointcut id="testPointcut1" expression="execution(* springbank.dao.AccountDao.foo(..))"/>
|
||||
|
||||
<aspect ref="myAspect">
|
||||
<after method="foo" pointcut-ref="testPointcut"/>
|
||||
</aspect>
|
||||
|
||||
</config>
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.config;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static test.util.TestResourceUtils.qualifiedResource;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
|
||||
import org.springframework.core.io.Resource;
|
||||
|
||||
/**
|
||||
* Tests that the <aop:config/> element can be used as a top level element.
|
||||
*
|
||||
* @author Rob Harrop
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public final class TopLevelAopTagTests {
|
||||
|
||||
private static final Resource CONTEXT = qualifiedResource(TopLevelAopTagTests.class, "context.xml");
|
||||
|
||||
@Test
|
||||
public void testParse() throws Exception {
|
||||
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
||||
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
|
||||
reader.loadBeanDefinitions(CONTEXT);
|
||||
|
||||
assertTrue(beanFactory.containsBeanDefinition("testPointcut"));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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 static org.junit.Assert.*;
|
||||
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.aop.SpringProxy;
|
||||
|
||||
import test.beans.ITestBean;
|
||||
import test.beans.TestBean;
|
||||
|
||||
/**
|
||||
* @author Rod Johnson
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public final class AopProxyUtilsTests {
|
||||
|
||||
@Test
|
||||
public void testCompleteProxiedInterfacesWorksWithNull() {
|
||||
AdvisedSupport as = new AdvisedSupport();
|
||||
Class<?>[] completedInterfaces = AopProxyUtils.completeProxiedInterfaces(as);
|
||||
assertEquals(2, completedInterfaces.length);
|
||||
List<?> ifaces = Arrays.asList(completedInterfaces);
|
||||
assertTrue(ifaces.contains(Advised.class));
|
||||
assertTrue(ifaces.contains(SpringProxy.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCompleteProxiedInterfacesWorksWithNullOpaque() {
|
||||
AdvisedSupport as = new AdvisedSupport();
|
||||
as.setOpaque(true);
|
||||
Class<?>[] completedInterfaces = AopProxyUtils.completeProxiedInterfaces(as);
|
||||
assertEquals(1, completedInterfaces.length);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCompleteProxiedInterfacesAdvisedNotIncluded() {
|
||||
AdvisedSupport as = new AdvisedSupport();
|
||||
as.addInterface(ITestBean.class);
|
||||
as.addInterface(Comparable.class);
|
||||
Class<?>[] completedInterfaces = AopProxyUtils.completeProxiedInterfaces(as);
|
||||
assertEquals(4, completedInterfaces.length);
|
||||
|
||||
// Can't assume ordering for others, so use a list
|
||||
List<?> l = Arrays.asList(completedInterfaces);
|
||||
assertTrue(l.contains(Advised.class));
|
||||
assertTrue(l.contains(ITestBean.class));
|
||||
assertTrue(l.contains(Comparable.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCompleteProxiedInterfacesAdvisedIncluded() {
|
||||
AdvisedSupport as = new AdvisedSupport();
|
||||
as.addInterface(ITestBean.class);
|
||||
as.addInterface(Comparable.class);
|
||||
as.addInterface(Advised.class);
|
||||
Class<?>[] completedInterfaces = AopProxyUtils.completeProxiedInterfaces(as);
|
||||
assertEquals(4, completedInterfaces.length);
|
||||
|
||||
// Can't assume ordering for others, so use a list
|
||||
List<?> l = Arrays.asList(completedInterfaces);
|
||||
assertTrue(l.contains(Advised.class));
|
||||
assertTrue(l.contains(ITestBean.class));
|
||||
assertTrue(l.contains(Comparable.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCompleteProxiedInterfacesAdvisedNotIncludedOpaque() {
|
||||
AdvisedSupport as = new AdvisedSupport();
|
||||
as.setOpaque(true);
|
||||
as.addInterface(ITestBean.class);
|
||||
as.addInterface(Comparable.class);
|
||||
Class<?>[] completedInterfaces = AopProxyUtils.completeProxiedInterfaces(as);
|
||||
assertEquals(3, completedInterfaces.length);
|
||||
|
||||
// Can't assume ordering for others, so use a list
|
||||
List<?> l = Arrays.asList(completedInterfaces);
|
||||
assertFalse(l.contains(Advised.class));
|
||||
assertTrue(l.contains(ITestBean.class));
|
||||
assertTrue(l.contains(Comparable.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProxiedUserInterfacesWithSingleInterface() {
|
||||
ProxyFactory pf = new ProxyFactory();
|
||||
pf.setTarget(new TestBean());
|
||||
pf.addInterface(ITestBean.class);
|
||||
Object proxy = pf.getProxy();
|
||||
Class<?>[] userInterfaces = AopProxyUtils.proxiedUserInterfaces(proxy);
|
||||
assertEquals(1, userInterfaces.length);
|
||||
assertEquals(ITestBean.class, userInterfaces[0]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProxiedUserInterfacesWithMultipleInterfaces() {
|
||||
ProxyFactory pf = new ProxyFactory();
|
||||
pf.setTarget(new TestBean());
|
||||
pf.addInterface(ITestBean.class);
|
||||
pf.addInterface(Comparable.class);
|
||||
Object proxy = pf.getProxy();
|
||||
Class<?>[] userInterfaces = AopProxyUtils.proxiedUserInterfaces(proxy);
|
||||
assertEquals(2, userInterfaces.length);
|
||||
assertEquals(ITestBean.class, userInterfaces[0]);
|
||||
assertEquals(Comparable.class, userInterfaces[1]);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testProxiedUserInterfacesWithNoInterface() {
|
||||
Object proxy = Proxy.newProxyInstance(getClass().getClassLoader(), new Class[0],
|
||||
new InvocationHandler() {
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
AopProxyUtils.proxiedUserInterfaces(proxy);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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 org.junit.Test;
|
||||
import org.springframework.aop.support.DelegatingIntroductionInterceptor;
|
||||
import org.springframework.util.StopWatch;
|
||||
|
||||
import test.beans.ITestBean;
|
||||
import test.beans.TestBean;
|
||||
|
||||
/**
|
||||
* Benchmarks for introductions.
|
||||
*
|
||||
* NOTE: No assertions!
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Chris Beams
|
||||
* @since 2.0
|
||||
*/
|
||||
public final class IntroductionBenchmarkTests {
|
||||
|
||||
private static final int EXPECTED_COMPARE = 13;
|
||||
|
||||
/** Increase this if you want meaningful results! */
|
||||
private static final int INVOCATIONS = 100000;
|
||||
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public static class SimpleCounterIntroduction extends DelegatingIntroductionInterceptor implements Counter {
|
||||
public int getCount() {
|
||||
return EXPECTED_COMPARE;
|
||||
}
|
||||
}
|
||||
|
||||
public static interface Counter {
|
||||
int getCount();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void timeManyInvocations() {
|
||||
StopWatch sw = new StopWatch();
|
||||
|
||||
TestBean target = new TestBean();
|
||||
ProxyFactory pf = new ProxyFactory(target);
|
||||
pf.setProxyTargetClass(false);
|
||||
pf.addAdvice(new SimpleCounterIntroduction());
|
||||
ITestBean proxy = (ITestBean) pf.getProxy();
|
||||
|
||||
Counter counter = (Counter) proxy;
|
||||
|
||||
sw.start(INVOCATIONS + " invocations on proxy, not hitting introduction");
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
proxy.getAge();
|
||||
}
|
||||
sw.stop();
|
||||
|
||||
sw.start(INVOCATIONS + " invocations on proxy, hitting introduction");
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
counter.getCount();
|
||||
}
|
||||
sw.stop();
|
||||
|
||||
sw.start(INVOCATIONS + " invocations on target");
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
target.getAge();
|
||||
}
|
||||
sw.stop();
|
||||
|
||||
System.out.println(sw.prettyPrint());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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 static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.junit.Test;
|
||||
|
||||
import test.beans.TestBean;
|
||||
|
||||
/**
|
||||
* @author Rod Johnson
|
||||
* @author Chris Beams
|
||||
* @since 14.03.2003
|
||||
*/
|
||||
public final class MethodInvocationTests {
|
||||
|
||||
@Test
|
||||
public void testValidInvocation() throws Throwable {
|
||||
Method m = Object.class.getMethod("hashCode", (Class[]) null);
|
||||
Object proxy = new Object();
|
||||
final Object returnValue = new Object();
|
||||
List<Object> is = new LinkedList<Object>();
|
||||
is.add(new MethodInterceptor() {
|
||||
public Object invoke(MethodInvocation invocation) throws Throwable {
|
||||
return returnValue;
|
||||
}
|
||||
});
|
||||
ReflectiveMethodInvocation invocation = new ReflectiveMethodInvocation(proxy, null, //?
|
||||
m, null, null, is // list
|
||||
);
|
||||
Object rv = invocation.proceed();
|
||||
assertTrue("correct response", rv == returnValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* toString on target can cause failure.
|
||||
*/
|
||||
@Test
|
||||
public void testToStringDoesntHitTarget() throws Throwable {
|
||||
Object target = new TestBean() {
|
||||
public String toString() {
|
||||
throw new UnsupportedOperationException("toString");
|
||||
}
|
||||
};
|
||||
List<Object> is = new LinkedList<Object>();
|
||||
|
||||
Method m = Object.class.getMethod("hashCode", (Class[]) null);
|
||||
Object proxy = new Object();
|
||||
ReflectiveMethodInvocation invocation =
|
||||
new ReflectiveMethodInvocation(proxy, target, m, null, null, is);
|
||||
|
||||
// If it hits target, the test will fail with the UnsupportedOpException
|
||||
// in the inner class above.
|
||||
invocation.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
|
||||
|
||||
<beans>
|
||||
|
||||
<bean id="testBeanTarget" class="org.springframework.aop.framework.PrototypeTargetTests$TestBeanImpl"
|
||||
scope="prototype"/>
|
||||
|
||||
<bean id="testInterceptor" class="org.springframework.aop.framework.PrototypeTargetTests$TestInterceptor"
|
||||
scope="singleton"/>
|
||||
|
||||
<bean id="testBeanPrototype" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||
<property name="proxyInterfaces">
|
||||
<value>org.springframework.aop.framework.PrototypeTargetTests$TestBean</value>
|
||||
</property>
|
||||
<property name="singleton">
|
||||
<value>false</value>
|
||||
</property>
|
||||
<property name="interceptorNames">
|
||||
<list>
|
||||
<value>testInterceptor</value>
|
||||
<value>testBeanTarget</value>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="testBeanSingleton" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||
<property name="proxyInterfaces">
|
||||
<value>org.springframework.aop.framework.PrototypeTargetTests$TestBean</value>
|
||||
</property>
|
||||
<property name="singleton">
|
||||
<value>true</value>
|
||||
</property>
|
||||
<property name="interceptorNames">
|
||||
<list>
|
||||
<value>testInterceptor</value>
|
||||
<value>testBeanTarget</value>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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 static org.junit.Assert.assertEquals;
|
||||
import static test.util.TestResourceUtils.qualifiedResource;
|
||||
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.xml.XmlBeanFactory;
|
||||
import org.springframework.core.io.Resource;
|
||||
|
||||
/**
|
||||
* @author Juergen Hoeller
|
||||
* @author Chris Beams
|
||||
* @since 03.09.2004
|
||||
*/
|
||||
public final class PrototypeTargetTests {
|
||||
|
||||
private static final Resource CONTEXT = qualifiedResource(PrototypeTargetTests.class, "context.xml");
|
||||
|
||||
@Test
|
||||
public void testPrototypeProxyWithPrototypeTarget() {
|
||||
TestBeanImpl.constructionCount = 0;
|
||||
XmlBeanFactory xbf = new XmlBeanFactory(CONTEXT);
|
||||
for (int i = 0; i < 10; i++) {
|
||||
TestBean tb = (TestBean) xbf.getBean("testBeanPrototype");
|
||||
tb.doSomething();
|
||||
}
|
||||
TestInterceptor interceptor = (TestInterceptor) xbf.getBean("testInterceptor");
|
||||
assertEquals(10, TestBeanImpl.constructionCount);
|
||||
assertEquals(10, interceptor.invocationCount);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingletonProxyWithPrototypeTarget() {
|
||||
TestBeanImpl.constructionCount = 0;
|
||||
XmlBeanFactory xbf = new XmlBeanFactory(CONTEXT);
|
||||
for (int i = 0; i < 10; i++) {
|
||||
TestBean tb = (TestBean) xbf.getBean("testBeanSingleton");
|
||||
tb.doSomething();
|
||||
}
|
||||
TestInterceptor interceptor = (TestInterceptor) xbf.getBean("testInterceptor");
|
||||
assertEquals(1, TestBeanImpl.constructionCount);
|
||||
assertEquals(10, interceptor.invocationCount);
|
||||
}
|
||||
|
||||
|
||||
public static interface TestBean {
|
||||
public void doSomething();
|
||||
}
|
||||
|
||||
|
||||
public static class TestBeanImpl implements TestBean {
|
||||
private static int constructionCount = 0;
|
||||
|
||||
public TestBeanImpl() {
|
||||
constructionCount++;
|
||||
}
|
||||
|
||||
public void doSomething() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class TestInterceptor implements MethodInterceptor {
|
||||
private int invocationCount = 0;
|
||||
|
||||
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
|
||||
invocationCount++;
|
||||
return methodInvocation.proceed();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,358 @@
|
||||
/*
|
||||
* Copyright 2002-2010 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 javax.accessibility.Accessible;
|
||||
import javax.swing.*;
|
||||
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import test.aop.CountingBeforeAdvice;
|
||||
import test.aop.NopInterceptor;
|
||||
import test.beans.IOther;
|
||||
import test.beans.ITestBean;
|
||||
import test.beans.TestBean;
|
||||
import test.util.TimeStamped;
|
||||
|
||||
import org.springframework.aop.Advisor;
|
||||
import org.springframework.aop.interceptor.DebugInterceptor;
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.aop.support.DefaultIntroductionAdvisor;
|
||||
import org.springframework.aop.support.DefaultPointcutAdvisor;
|
||||
import org.springframework.aop.support.DelegatingIntroductionInterceptor;
|
||||
|
||||
/**
|
||||
* Also tests AdvisedSupport and ProxyCreatorSupport superclasses.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @author Chris Beams
|
||||
* @since 14.05.2003
|
||||
*/
|
||||
public final class ProxyFactoryTests {
|
||||
|
||||
@Test
|
||||
public void testIndexOfMethods() {
|
||||
TestBean target = new TestBean();
|
||||
ProxyFactory pf = new ProxyFactory(target);
|
||||
NopInterceptor nop = new NopInterceptor();
|
||||
Advisor advisor = new DefaultPointcutAdvisor(new CountingBeforeAdvice());
|
||||
Advised advised = (Advised) pf.getProxy();
|
||||
// Can use advised and ProxyFactory interchangeably
|
||||
advised.addAdvice(nop);
|
||||
pf.addAdvisor(advisor);
|
||||
assertEquals(-1, pf.indexOf(new NopInterceptor()));
|
||||
assertEquals(0, pf.indexOf(nop));
|
||||
assertEquals(1, pf.indexOf(advisor));
|
||||
assertEquals(-1, advised.indexOf(new DefaultPointcutAdvisor(null)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveAdvisorByReference() {
|
||||
TestBean target = new TestBean();
|
||||
ProxyFactory pf = new ProxyFactory(target);
|
||||
NopInterceptor nop = new NopInterceptor();
|
||||
CountingBeforeAdvice cba = new CountingBeforeAdvice();
|
||||
Advisor advisor = new DefaultPointcutAdvisor(cba);
|
||||
pf.addAdvice(nop);
|
||||
pf.addAdvisor(advisor);
|
||||
ITestBean proxied = (ITestBean) pf.getProxy();
|
||||
proxied.setAge(5);
|
||||
assertEquals(1, cba.getCalls());
|
||||
assertEquals(1, nop.getCount());
|
||||
assertTrue(pf.removeAdvisor(advisor));
|
||||
assertEquals(5, proxied.getAge());
|
||||
assertEquals(1, cba.getCalls());
|
||||
assertEquals(2, nop.getCount());
|
||||
assertFalse(pf.removeAdvisor(new DefaultPointcutAdvisor(null)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveAdvisorByIndex() {
|
||||
TestBean target = new TestBean();
|
||||
ProxyFactory pf = new ProxyFactory(target);
|
||||
NopInterceptor nop = new NopInterceptor();
|
||||
CountingBeforeAdvice cba = new CountingBeforeAdvice();
|
||||
Advisor advisor = new DefaultPointcutAdvisor(cba);
|
||||
pf.addAdvice(nop);
|
||||
pf.addAdvisor(advisor);
|
||||
NopInterceptor nop2 = new NopInterceptor();
|
||||
pf.addAdvice(nop2);
|
||||
ITestBean proxied = (ITestBean) pf.getProxy();
|
||||
proxied.setAge(5);
|
||||
assertEquals(1, cba.getCalls());
|
||||
assertEquals(1, nop.getCount());
|
||||
assertEquals(1, nop2.getCount());
|
||||
// Removes counting before advisor
|
||||
pf.removeAdvisor(1);
|
||||
assertEquals(5, proxied.getAge());
|
||||
assertEquals(1, cba.getCalls());
|
||||
assertEquals(2, nop.getCount());
|
||||
assertEquals(2, nop2.getCount());
|
||||
// Removes Nop1
|
||||
pf.removeAdvisor(0);
|
||||
assertEquals(5, proxied.getAge());
|
||||
assertEquals(1, cba.getCalls());
|
||||
assertEquals(2, nop.getCount());
|
||||
assertEquals(3, nop2.getCount());
|
||||
|
||||
// Check out of bounds
|
||||
try {
|
||||
pf.removeAdvisor(-1);
|
||||
}
|
||||
catch (AopConfigException ex) {
|
||||
// Ok
|
||||
}
|
||||
|
||||
try {
|
||||
pf.removeAdvisor(2);
|
||||
}
|
||||
catch (AopConfigException ex) {
|
||||
// Ok
|
||||
}
|
||||
|
||||
assertEquals(5, proxied.getAge());
|
||||
assertEquals(4, nop2.getCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReplaceAdvisor() {
|
||||
TestBean target = new TestBean();
|
||||
ProxyFactory pf = new ProxyFactory(target);
|
||||
NopInterceptor nop = new NopInterceptor();
|
||||
CountingBeforeAdvice cba1 = new CountingBeforeAdvice();
|
||||
CountingBeforeAdvice cba2 = new CountingBeforeAdvice();
|
||||
Advisor advisor1 = new DefaultPointcutAdvisor(cba1);
|
||||
Advisor advisor2 = new DefaultPointcutAdvisor(cba2);
|
||||
pf.addAdvisor(advisor1);
|
||||
pf.addAdvice(nop);
|
||||
ITestBean proxied = (ITestBean) pf.getProxy();
|
||||
// Use the type cast feature
|
||||
// Replace etc methods on advised should be same as on ProxyFactory
|
||||
Advised advised = (Advised) proxied;
|
||||
proxied.setAge(5);
|
||||
assertEquals(1, cba1.getCalls());
|
||||
assertEquals(0, cba2.getCalls());
|
||||
assertEquals(1, nop.getCount());
|
||||
assertFalse(advised.replaceAdvisor(new DefaultPointcutAdvisor(new NopInterceptor()), advisor2));
|
||||
assertTrue(advised.replaceAdvisor(advisor1, advisor2));
|
||||
assertEquals(advisor2, pf.getAdvisors()[0]);
|
||||
assertEquals(5, proxied.getAge());
|
||||
assertEquals(1, cba1.getCalls());
|
||||
assertEquals(2, nop.getCount());
|
||||
assertEquals(1, cba2.getCalls());
|
||||
assertFalse(pf.replaceAdvisor(new DefaultPointcutAdvisor(null), advisor1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddRepeatedInterface() {
|
||||
TimeStamped tst = new TimeStamped() {
|
||||
public long getTimeStamp() {
|
||||
throw new UnsupportedOperationException("getTimeStamp");
|
||||
}
|
||||
};
|
||||
ProxyFactory pf = new ProxyFactory(tst);
|
||||
// We've already implicitly added this interface.
|
||||
// This call should be ignored without error
|
||||
pf.addInterface(TimeStamped.class);
|
||||
// All cool
|
||||
assertThat(pf.getProxy(), instanceOf(TimeStamped.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetsAllInterfaces() throws Exception {
|
||||
// Extend to get new interface
|
||||
class TestBeanSubclass extends TestBean implements Comparable<Object> {
|
||||
public int compareTo(Object arg0) {
|
||||
throw new UnsupportedOperationException("compareTo");
|
||||
}
|
||||
}
|
||||
TestBeanSubclass raw = new TestBeanSubclass();
|
||||
ProxyFactory factory = new ProxyFactory(raw);
|
||||
//System.out.println("Proxied interfaces are " + StringUtils.arrayToDelimitedString(factory.getProxiedInterfaces(), ","));
|
||||
assertEquals("Found correct number of interfaces", 3, factory.getProxiedInterfaces().length);
|
||||
ITestBean tb = (ITestBean) factory.getProxy();
|
||||
assertThat("Picked up secondary interface", tb, instanceOf(IOther.class));
|
||||
|
||||
raw.setAge(25);
|
||||
assertTrue(tb.getAge() == raw.getAge());
|
||||
|
||||
long t = 555555L;
|
||||
TimestampIntroductionInterceptor ti = new TimestampIntroductionInterceptor(t);
|
||||
|
||||
Class<?>[] oldProxiedInterfaces = factory.getProxiedInterfaces();
|
||||
|
||||
factory.addAdvisor(0, new DefaultIntroductionAdvisor(ti, TimeStamped.class));
|
||||
|
||||
Class<?>[] newProxiedInterfaces = factory.getProxiedInterfaces();
|
||||
assertEquals("Advisor proxies one more interface after introduction", oldProxiedInterfaces.length + 1, newProxiedInterfaces.length);
|
||||
|
||||
TimeStamped ts = (TimeStamped) factory.getProxy();
|
||||
assertTrue(ts.getTimeStamp() == t);
|
||||
// Shouldn't fail;
|
||||
((IOther) ts).absquatulate();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInterceptorInclusionMethods() {
|
||||
class MyInterceptor implements MethodInterceptor {
|
||||
public Object invoke(MethodInvocation invocation) throws Throwable {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
NopInterceptor di = new NopInterceptor();
|
||||
NopInterceptor diUnused = new NopInterceptor();
|
||||
ProxyFactory factory = new ProxyFactory(new TestBean());
|
||||
factory.addAdvice(0, di);
|
||||
assertThat(factory.getProxy(), instanceOf(ITestBean.class));
|
||||
assertTrue(factory.adviceIncluded(di));
|
||||
assertTrue(!factory.adviceIncluded(diUnused));
|
||||
assertTrue(factory.countAdvicesOfType(NopInterceptor.class) == 1);
|
||||
assertTrue(factory.countAdvicesOfType(MyInterceptor.class) == 0);
|
||||
|
||||
factory.addAdvice(0, diUnused);
|
||||
assertTrue(factory.adviceIncluded(diUnused));
|
||||
assertTrue(factory.countAdvicesOfType(NopInterceptor.class) == 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Should see effect immediately on behavior.
|
||||
*/
|
||||
@Test
|
||||
public void testCanAddAndRemoveAspectInterfacesOnSingleton() {
|
||||
ProxyFactory config = new ProxyFactory(new TestBean());
|
||||
|
||||
assertFalse("Shouldn't implement TimeStamped before manipulation",
|
||||
config.getProxy() instanceof TimeStamped);
|
||||
|
||||
long time = 666L;
|
||||
TimestampIntroductionInterceptor ti = new TimestampIntroductionInterceptor();
|
||||
ti.setTime(time);
|
||||
|
||||
// Add to front of interceptor chain
|
||||
int oldCount = config.getAdvisors().length;
|
||||
config.addAdvisor(0, new DefaultIntroductionAdvisor(ti, TimeStamped.class));
|
||||
|
||||
assertTrue(config.getAdvisors().length == oldCount + 1);
|
||||
|
||||
TimeStamped ts = (TimeStamped) config.getProxy();
|
||||
assertTrue(ts.getTimeStamp() == time);
|
||||
|
||||
// Can remove
|
||||
config.removeAdvice(ti);
|
||||
|
||||
assertTrue(config.getAdvisors().length == oldCount);
|
||||
|
||||
try {
|
||||
// Existing reference will fail
|
||||
ts.getTimeStamp();
|
||||
fail("Existing object won't implement this interface any more");
|
||||
}
|
||||
catch (RuntimeException ex) {
|
||||
}
|
||||
|
||||
assertFalse("Should no longer implement TimeStamped",
|
||||
config.getProxy() instanceof TimeStamped);
|
||||
|
||||
// Now check non-effect of removing interceptor that isn't there
|
||||
config.removeAdvice(new DebugInterceptor());
|
||||
|
||||
assertTrue(config.getAdvisors().length == oldCount);
|
||||
|
||||
ITestBean it = (ITestBean) ts;
|
||||
DebugInterceptor debugInterceptor = new DebugInterceptor();
|
||||
config.addAdvice(0, debugInterceptor);
|
||||
it.getSpouse();
|
||||
assertEquals(1, debugInterceptor.getCount());
|
||||
config.removeAdvice(debugInterceptor);
|
||||
it.getSpouse();
|
||||
// not invoked again
|
||||
assertTrue(debugInterceptor.getCount() == 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProxyTargetClassWithInterfaceAsTarget() {
|
||||
ProxyFactory pf = new ProxyFactory();
|
||||
pf.setTargetClass(ITestBean.class);
|
||||
Object proxy = pf.getProxy();
|
||||
assertTrue("Proxy is a JDK proxy", AopUtils.isJdkDynamicProxy(proxy));
|
||||
assertTrue(proxy instanceof ITestBean);
|
||||
assertEquals(ITestBean.class, AopProxyUtils.ultimateTargetClass(proxy));
|
||||
|
||||
ProxyFactory pf2 = new ProxyFactory(proxy);
|
||||
Object proxy2 = pf2.getProxy();
|
||||
assertTrue("Proxy is a JDK proxy", AopUtils.isJdkDynamicProxy(proxy2));
|
||||
assertTrue(proxy2 instanceof ITestBean);
|
||||
assertEquals(ITestBean.class, AopProxyUtils.ultimateTargetClass(proxy2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProxyTargetClassWithConcreteClassAsTarget() {
|
||||
ProxyFactory pf = new ProxyFactory();
|
||||
pf.setTargetClass(TestBean.class);
|
||||
Object proxy = pf.getProxy();
|
||||
assertTrue("Proxy is a CGLIB proxy", AopUtils.isCglibProxy(proxy));
|
||||
assertTrue(proxy instanceof TestBean);
|
||||
assertEquals(TestBean.class, AopProxyUtils.ultimateTargetClass(proxy));
|
||||
|
||||
ProxyFactory pf2 = new ProxyFactory(proxy);
|
||||
pf2.setProxyTargetClass(true);
|
||||
Object proxy2 = pf2.getProxy();
|
||||
assertTrue("Proxy is a CGLIB proxy", AopUtils.isCglibProxy(proxy2));
|
||||
assertTrue(proxy2 instanceof TestBean);
|
||||
assertEquals(TestBean.class, AopProxyUtils.ultimateTargetClass(proxy2));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("Not implemented yet, see http://jira.springframework.org/browse/SPR-5708")
|
||||
public void testExclusionOfNonPublicInterfaces() {
|
||||
JFrame frame = new JFrame();
|
||||
ProxyFactory proxyFactory = new ProxyFactory(frame);
|
||||
Object proxy = proxyFactory.getProxy();
|
||||
assertTrue(proxy instanceof RootPaneContainer);
|
||||
assertTrue(proxy instanceof Accessible);
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private static class TimestampIntroductionInterceptor extends DelegatingIntroductionInterceptor
|
||||
implements TimeStamped {
|
||||
|
||||
private long ts;
|
||||
|
||||
public TimestampIntroductionInterceptor() {
|
||||
}
|
||||
|
||||
public TimestampIntroductionInterceptor(long ts) {
|
||||
this.ts = ts;
|
||||
}
|
||||
|
||||
public void setTime(long ts) {
|
||||
this.ts = ts;
|
||||
}
|
||||
|
||||
public long getTimeStamp() {
|
||||
return ts;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* Copyright 2002-2009 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.adapter;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.rmi.RemoteException;
|
||||
import javax.transaction.TransactionRolledbackException;
|
||||
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import static org.easymock.EasyMock.*;
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Test;
|
||||
import test.aop.MethodCounter;
|
||||
|
||||
import org.springframework.aop.ThrowsAdvice;
|
||||
|
||||
/**
|
||||
* @author Rod Johnson
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public final class ThrowsAdviceInterceptorTests {
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testNoHandlerMethods() {
|
||||
// should require one handler method at least
|
||||
new ThrowsAdviceInterceptor(new Object());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotInvoked() throws Throwable {
|
||||
MyThrowsHandler th = new MyThrowsHandler();
|
||||
ThrowsAdviceInterceptor ti = new ThrowsAdviceInterceptor(th);
|
||||
Object ret = new Object();
|
||||
MethodInvocation mi = createMock(MethodInvocation.class);
|
||||
expect(mi.proceed()).andReturn(ret);
|
||||
replay(mi);
|
||||
assertEquals(ret, ti.invoke(mi));
|
||||
assertEquals(0, th.getCalls());
|
||||
verify(mi);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoHandlerMethodForThrowable() throws Throwable {
|
||||
MyThrowsHandler th = new MyThrowsHandler();
|
||||
ThrowsAdviceInterceptor ti = new ThrowsAdviceInterceptor(th);
|
||||
assertEquals(2, ti.getHandlerMethodCount());
|
||||
Exception ex = new Exception();
|
||||
MethodInvocation mi = createMock(MethodInvocation.class);
|
||||
expect(mi.proceed()).andThrow(ex);
|
||||
replay(mi);
|
||||
try {
|
||||
ti.invoke(mi);
|
||||
fail();
|
||||
}
|
||||
catch (Exception caught) {
|
||||
assertEquals(ex, caught);
|
||||
}
|
||||
assertEquals(0, th.getCalls());
|
||||
verify(mi);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCorrectHandlerUsed() throws Throwable {
|
||||
MyThrowsHandler th = new MyThrowsHandler();
|
||||
ThrowsAdviceInterceptor ti = new ThrowsAdviceInterceptor(th);
|
||||
FileNotFoundException ex = new FileNotFoundException();
|
||||
MethodInvocation mi = createMock(MethodInvocation.class);
|
||||
expect(mi.getMethod()).andReturn(Object.class.getMethod("hashCode", (Class[]) null));
|
||||
expect(mi.getArguments()).andReturn(null);
|
||||
expect(mi.getThis()).andReturn(new Object());
|
||||
expect(mi.proceed()).andThrow(ex);
|
||||
replay(mi);
|
||||
try {
|
||||
ti.invoke(mi);
|
||||
fail();
|
||||
}
|
||||
catch (Exception caught) {
|
||||
assertEquals(ex, caught);
|
||||
}
|
||||
assertEquals(1, th.getCalls());
|
||||
assertEquals(1, th.getCalls("ioException"));
|
||||
verify(mi);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCorrectHandlerUsedForSubclass() throws Throwable {
|
||||
MyThrowsHandler th = new MyThrowsHandler();
|
||||
ThrowsAdviceInterceptor ti = new ThrowsAdviceInterceptor(th);
|
||||
// Extends RemoteException
|
||||
TransactionRolledbackException ex = new TransactionRolledbackException();
|
||||
MethodInvocation mi = createMock(MethodInvocation.class);
|
||||
expect(mi.proceed()).andThrow(ex);
|
||||
replay(mi);
|
||||
try {
|
||||
ti.invoke(mi);
|
||||
fail();
|
||||
}
|
||||
catch (Exception caught) {
|
||||
assertEquals(ex, caught);
|
||||
}
|
||||
assertEquals(1, th.getCalls());
|
||||
assertEquals(1, th.getCalls("remoteException"));
|
||||
verify(mi);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandlerMethodThrowsException() throws Throwable {
|
||||
final Throwable t = new Throwable();
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
MyThrowsHandler th = new MyThrowsHandler() {
|
||||
public void afterThrowing(RemoteException ex) throws Throwable {
|
||||
super.afterThrowing(ex);
|
||||
throw t;
|
||||
}
|
||||
};
|
||||
|
||||
ThrowsAdviceInterceptor ti = new ThrowsAdviceInterceptor(th);
|
||||
// Extends RemoteException
|
||||
TransactionRolledbackException ex = new TransactionRolledbackException();
|
||||
MethodInvocation mi = createMock(MethodInvocation.class);
|
||||
expect(mi.proceed()).andThrow(ex);
|
||||
replay(mi);
|
||||
try {
|
||||
ti.invoke(mi);
|
||||
fail();
|
||||
}
|
||||
catch (Throwable caught) {
|
||||
assertEquals(t, caught);
|
||||
}
|
||||
assertEquals(1, th.getCalls());
|
||||
assertEquals(1, th.getCalls("remoteException"));
|
||||
verify(mi);
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private static class MyThrowsHandler extends MethodCounter implements ThrowsAdvice {
|
||||
// Full method signature
|
||||
public void afterThrowing(Method m, Object[] args, Object target, IOException ex) {
|
||||
count("ioException");
|
||||
}
|
||||
public void afterThrowing(RemoteException ex) throws Throwable {
|
||||
count("remoteException");
|
||||
}
|
||||
|
||||
/** Not valid, wrong number of arguments */
|
||||
public void afterThrowing(Method m, Exception ex) throws Throwable {
|
||||
throw new UnsupportedOperationException("Shouldn't be called");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.interceptor;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.aop.framework.Advised;
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
|
||||
import test.beans.DerivedTestBean;
|
||||
import test.beans.ITestBean;
|
||||
import test.beans.TestBean;
|
||||
import test.util.SerializationTestUtils;
|
||||
|
||||
/**
|
||||
* @author Juergen Hoeller
|
||||
* @author Chris Beams
|
||||
* @since 06.04.2004
|
||||
*/
|
||||
public final class ConcurrencyThrottleInterceptorTests {
|
||||
|
||||
protected static final Log logger = LogFactory.getLog(ConcurrencyThrottleInterceptorTests.class);
|
||||
|
||||
public static final int NR_OF_THREADS = 100;
|
||||
|
||||
public static final int NR_OF_ITERATIONS = 1000;
|
||||
|
||||
|
||||
@Test
|
||||
public void testSerializable() throws Exception {
|
||||
DerivedTestBean tb = new DerivedTestBean();
|
||||
ProxyFactory proxyFactory = new ProxyFactory();
|
||||
proxyFactory.setInterfaces(new Class[] {ITestBean.class});
|
||||
ConcurrencyThrottleInterceptor cti = new ConcurrencyThrottleInterceptor();
|
||||
proxyFactory.addAdvice(cti);
|
||||
proxyFactory.setTarget(tb);
|
||||
ITestBean proxy = (ITestBean) proxyFactory.getProxy();
|
||||
proxy.getAge();
|
||||
|
||||
ITestBean serializedProxy = (ITestBean) SerializationTestUtils.serializeAndDeserialize(proxy);
|
||||
Advised advised = (Advised) serializedProxy;
|
||||
ConcurrencyThrottleInterceptor serializedCti =
|
||||
(ConcurrencyThrottleInterceptor) advised.getAdvisors()[0].getAdvice();
|
||||
assertEquals(cti.getConcurrencyLimit(), serializedCti.getConcurrencyLimit());
|
||||
serializedProxy.getAge();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleThreadsWithLimit1() {
|
||||
testMultipleThreads(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleThreadsWithLimit10() {
|
||||
testMultipleThreads(10);
|
||||
}
|
||||
|
||||
private void testMultipleThreads(int concurrencyLimit) {
|
||||
TestBean tb = new TestBean();
|
||||
ProxyFactory proxyFactory = new ProxyFactory();
|
||||
proxyFactory.setInterfaces(new Class[] {ITestBean.class});
|
||||
ConcurrencyThrottleInterceptor cti = new ConcurrencyThrottleInterceptor();
|
||||
cti.setConcurrencyLimit(concurrencyLimit);
|
||||
proxyFactory.addAdvice(cti);
|
||||
proxyFactory.setTarget(tb);
|
||||
ITestBean proxy = (ITestBean) proxyFactory.getProxy();
|
||||
|
||||
Thread[] threads = new Thread[NR_OF_THREADS];
|
||||
for (int i = 0; i < NR_OF_THREADS; i++) {
|
||||
threads[i] = new ConcurrencyThread(proxy, null);
|
||||
threads[i].start();
|
||||
}
|
||||
for (int i = 0; i < NR_OF_THREADS / 10; i++) {
|
||||
try {
|
||||
Thread.sleep(5);
|
||||
}
|
||||
catch (InterruptedException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
threads[i] = new ConcurrencyThread(proxy,
|
||||
i % 2 == 0 ? (Throwable) new OutOfMemoryError() : (Throwable) new IllegalStateException());
|
||||
threads[i].start();
|
||||
}
|
||||
for (int i = 0; i < NR_OF_THREADS; i++) {
|
||||
try {
|
||||
threads[i].join();
|
||||
}
|
||||
catch (InterruptedException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class ConcurrencyThread extends Thread {
|
||||
|
||||
private ITestBean proxy;
|
||||
private Throwable ex;
|
||||
|
||||
public ConcurrencyThread(ITestBean proxy, Throwable ex) {
|
||||
this.proxy = proxy;
|
||||
this.ex = ex;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
if (this.ex != null) {
|
||||
try {
|
||||
this.proxy.exceptional(this.ex);
|
||||
}
|
||||
catch (RuntimeException ex) {
|
||||
if (ex == this.ex) {
|
||||
logger.debug("Expected exception thrown", ex);
|
||||
}
|
||||
else {
|
||||
// should never happen
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
catch (Error err) {
|
||||
if (err == this.ex) {
|
||||
logger.debug("Expected exception thrown", err);
|
||||
}
|
||||
else {
|
||||
// should never happen
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
// should never happen
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < NR_OF_ITERATIONS; i++) {
|
||||
this.proxy.getName();
|
||||
}
|
||||
}
|
||||
logger.debug("finished");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.interceptor;
|
||||
|
||||
import static org.easymock.EasyMock.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
* @author Rick Evans
|
||||
* @author Juergen Hoeller
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public final class CustomizableTraceInterceptorTests {
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testSetEmptyEnterMessage() {
|
||||
// Must not be able to set empty enter message
|
||||
new CustomizableTraceInterceptor().setEnterMessage("");
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testSetEnterMessageWithReturnValuePlaceholder() {
|
||||
// Must not be able to set enter message with return value placeholder
|
||||
new CustomizableTraceInterceptor().setEnterMessage(CustomizableTraceInterceptor.PLACEHOLDER_RETURN_VALUE);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testSetEnterMessageWithExceptionPlaceholder() {
|
||||
// Must not be able to set enter message with exception placeholder
|
||||
new CustomizableTraceInterceptor().setEnterMessage(CustomizableTraceInterceptor.PLACEHOLDER_EXCEPTION);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testSetEnterMessageWithInvocationTimePlaceholder() {
|
||||
// Must not be able to set enter message with invocation time placeholder
|
||||
new CustomizableTraceInterceptor().setEnterMessage(CustomizableTraceInterceptor.PLACEHOLDER_INVOCATION_TIME);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testSetEmptyExitMessage() {
|
||||
// Must not be able to set empty exit message
|
||||
new CustomizableTraceInterceptor().setExitMessage("");
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testSetExitMessageWithExceptionPlaceholder() {
|
||||
// Must not be able to set exit message with exception placeholder
|
||||
new CustomizableTraceInterceptor().setExitMessage(CustomizableTraceInterceptor.PLACEHOLDER_EXCEPTION);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testSetEmptyExceptionMessage() {
|
||||
// Must not be able to set empty exception message
|
||||
new CustomizableTraceInterceptor().setExceptionMessage("");
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testSetExceptionMethodWithReturnValuePlaceholder() {
|
||||
// Must not be able to set exception message with return value placeholder
|
||||
new CustomizableTraceInterceptor().setExceptionMessage(CustomizableTraceInterceptor.PLACEHOLDER_RETURN_VALUE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSunnyDayPathLogsCorrectly() throws Throwable {
|
||||
Log log = createMock(Log.class);
|
||||
|
||||
MethodInvocation methodInvocation = createMock(MethodInvocation.class);
|
||||
|
||||
Method toString = String.class.getMethod("toString", new Class[]{});
|
||||
|
||||
expect(log.isTraceEnabled()).andReturn(true);
|
||||
expect(methodInvocation.getMethod()).andReturn(toString).times(4);
|
||||
expect(methodInvocation.getThis()).andReturn(this).times(2);
|
||||
log.trace(isA(String.class));
|
||||
expect(methodInvocation.proceed()).andReturn(null);
|
||||
log.trace(isA(String.class));
|
||||
|
||||
replay(methodInvocation);
|
||||
replay(log);
|
||||
|
||||
CustomizableTraceInterceptor interceptor = new StubCustomizableTraceInterceptor(log);
|
||||
interceptor.invoke(methodInvocation);
|
||||
|
||||
verify(log);
|
||||
verify(methodInvocation);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExceptionPathLogsCorrectly() throws Throwable {
|
||||
Log log = createMock(Log.class);
|
||||
|
||||
MethodInvocation methodInvocation = createMock(MethodInvocation.class);
|
||||
|
||||
Method toString = String.class.getMethod("toString", new Class[]{});
|
||||
|
||||
expect(log.isTraceEnabled()).andReturn(true);
|
||||
expect(methodInvocation.getMethod()).andReturn(toString).times(4);
|
||||
expect(methodInvocation.getThis()).andReturn(this).times(2);
|
||||
log.trace(isA(String.class));
|
||||
IllegalArgumentException exception = new IllegalArgumentException();
|
||||
expect(methodInvocation.proceed()).andThrow(exception);
|
||||
log.trace(isA(String.class), eq(exception));
|
||||
|
||||
replay(log);
|
||||
replay(methodInvocation);
|
||||
|
||||
CustomizableTraceInterceptor interceptor = new StubCustomizableTraceInterceptor(log);
|
||||
try {
|
||||
interceptor.invoke(methodInvocation);
|
||||
fail("Must have propagated the IllegalArgumentException.");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
}
|
||||
|
||||
verify(log);
|
||||
verify(methodInvocation);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSunnyDayPathLogsCorrectlyWithPrettyMuchAllPlaceholdersMatching() throws Throwable {
|
||||
Log log = createMock(Log.class);
|
||||
|
||||
MethodInvocation methodInvocation = createMock(MethodInvocation.class);
|
||||
|
||||
Method toString = String.class.getMethod("toString", new Class[0]);
|
||||
Object[] arguments = new Object[]{"$ One \\$", new Long(2)};
|
||||
|
||||
expect(log.isTraceEnabled()).andReturn(true);
|
||||
expect(methodInvocation.getMethod()).andReturn(toString).times(7);
|
||||
expect(methodInvocation.getThis()).andReturn(this).times(2);
|
||||
expect(methodInvocation.getArguments()).andReturn(arguments).times(2);
|
||||
log.trace(isA(String.class));
|
||||
expect(methodInvocation.proceed()).andReturn("Hello!");
|
||||
log.trace(isA(String.class));
|
||||
|
||||
replay(methodInvocation);
|
||||
replay(log);
|
||||
|
||||
CustomizableTraceInterceptor interceptor = new StubCustomizableTraceInterceptor(log);
|
||||
interceptor.setEnterMessage(new StringBuffer()
|
||||
.append("Entering the '").append(CustomizableTraceInterceptor.PLACEHOLDER_METHOD_NAME)
|
||||
.append("' method of the [").append(CustomizableTraceInterceptor.PLACEHOLDER_TARGET_CLASS_NAME)
|
||||
.append("] class with the following args (").append(CustomizableTraceInterceptor.PLACEHOLDER_ARGUMENTS)
|
||||
.append(") and arg types (").append(CustomizableTraceInterceptor.PLACEHOLDER_ARGUMENT_TYPES)
|
||||
.append(").").toString());
|
||||
interceptor.setExitMessage(new StringBuffer()
|
||||
.append("Exiting the '").append(CustomizableTraceInterceptor.PLACEHOLDER_METHOD_NAME)
|
||||
.append("' method of the [").append(CustomizableTraceInterceptor.PLACEHOLDER_TARGET_CLASS_SHORT_NAME)
|
||||
.append("] class with the following args (").append(CustomizableTraceInterceptor.PLACEHOLDER_ARGUMENTS)
|
||||
.append(") and arg types (").append(CustomizableTraceInterceptor.PLACEHOLDER_ARGUMENT_TYPES)
|
||||
.append("), returning '").append(CustomizableTraceInterceptor.PLACEHOLDER_RETURN_VALUE)
|
||||
.append("' and taking '").append(CustomizableTraceInterceptor.PLACEHOLDER_INVOCATION_TIME)
|
||||
.append("' this long.").toString());
|
||||
interceptor.invoke(methodInvocation);
|
||||
|
||||
verify(log);
|
||||
verify(methodInvocation);
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private static class StubCustomizableTraceInterceptor extends CustomizableTraceInterceptor {
|
||||
|
||||
private final Log log;
|
||||
|
||||
public StubCustomizableTraceInterceptor(Log log) {
|
||||
super.setUseDynamicLogger(false);
|
||||
this.log = log;
|
||||
}
|
||||
|
||||
protected Log getLoggerForInvocation(MethodInvocation invocation) {
|
||||
return this.log;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.interceptor;
|
||||
|
||||
import static org.easymock.EasyMock.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Unit tests for the {@link DebugInterceptor} class.
|
||||
*
|
||||
* @author Rick Evans
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public final class DebugInterceptorTests {
|
||||
|
||||
@Test
|
||||
public void testSunnyDayPathLogsCorrectly() throws Throwable {
|
||||
Log log = createMock(Log.class);
|
||||
|
||||
MethodInvocation methodInvocation = createMock(MethodInvocation.class);
|
||||
|
||||
expect(log.isTraceEnabled()).andReturn(true);
|
||||
log.trace(isA(String.class));
|
||||
expect(methodInvocation.proceed()).andReturn(null);
|
||||
log.trace(isA(String.class));
|
||||
|
||||
replay(methodInvocation);
|
||||
replay(log);
|
||||
|
||||
DebugInterceptor interceptor = new StubDebugInterceptor(log);
|
||||
interceptor.invoke(methodInvocation);
|
||||
checkCallCountTotal(interceptor);
|
||||
|
||||
verify(methodInvocation);
|
||||
verify(log);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExceptionPathStillLogsCorrectly() throws Throwable {
|
||||
Log log = createMock(Log.class);
|
||||
|
||||
MethodInvocation methodInvocation = createMock(MethodInvocation.class);
|
||||
|
||||
expect(log.isTraceEnabled()).andReturn(true);
|
||||
log.trace(isA(String.class));
|
||||
IllegalArgumentException exception = new IllegalArgumentException();
|
||||
expect(methodInvocation.proceed()).andThrow(exception);
|
||||
log.trace(isA(String.class), eq(exception));
|
||||
|
||||
replay(methodInvocation);
|
||||
replay(log);
|
||||
|
||||
DebugInterceptor interceptor = new StubDebugInterceptor(log);
|
||||
try {
|
||||
interceptor.invoke(methodInvocation);
|
||||
fail("Must have propagated the IllegalArgumentException.");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
}
|
||||
checkCallCountTotal(interceptor);
|
||||
|
||||
verify(methodInvocation);
|
||||
verify(log);
|
||||
}
|
||||
|
||||
private void checkCallCountTotal(DebugInterceptor interceptor) {
|
||||
assertEquals("Intercepted call count not being incremented correctly", 1, interceptor.getCount());
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private static final class StubDebugInterceptor extends DebugInterceptor {
|
||||
|
||||
private final Log log;
|
||||
|
||||
|
||||
public StubDebugInterceptor(Log log) {
|
||||
super(true);
|
||||
this.log = log;
|
||||
}
|
||||
|
||||
protected Log getLoggerForInvocation(MethodInvocation invocation) {
|
||||
return log;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.interceptor;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.beans.factory.NamedBean;
|
||||
|
||||
import test.beans.ITestBean;
|
||||
import test.beans.TestBean;
|
||||
|
||||
/**
|
||||
* @author Rod Johnson
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public final class ExposeBeanNameAdvisorsTests {
|
||||
|
||||
private class RequiresBeanNameBoundTestBean extends TestBean {
|
||||
private final String beanName;
|
||||
|
||||
public RequiresBeanNameBoundTestBean(String beanName) {
|
||||
this.beanName = beanName;
|
||||
}
|
||||
|
||||
public int getAge() {
|
||||
assertEquals(beanName, ExposeBeanNameAdvisors.getBeanName());
|
||||
return super.getAge();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoIntroduction() {
|
||||
String beanName = "foo";
|
||||
TestBean target = new RequiresBeanNameBoundTestBean(beanName);
|
||||
ProxyFactory pf = new ProxyFactory(target);
|
||||
pf.addAdvisor(ExposeInvocationInterceptor.ADVISOR);
|
||||
pf.addAdvisor(ExposeBeanNameAdvisors.createAdvisorWithoutIntroduction(beanName));
|
||||
ITestBean proxy = (ITestBean) pf.getProxy();
|
||||
|
||||
assertFalse("No introduction", proxy instanceof NamedBean);
|
||||
// Requires binding
|
||||
proxy.getAge();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithIntroduction() {
|
||||
String beanName = "foo";
|
||||
TestBean target = new RequiresBeanNameBoundTestBean(beanName);
|
||||
ProxyFactory pf = new ProxyFactory(target);
|
||||
pf.addAdvisor(ExposeInvocationInterceptor.ADVISOR);
|
||||
pf.addAdvisor(ExposeBeanNameAdvisors.createAdvisorIntroducingNamedBean(beanName));
|
||||
ITestBean proxy = (ITestBean) pf.getProxy();
|
||||
|
||||
assertTrue("Introduction was made", proxy instanceof NamedBean);
|
||||
// Requires binding
|
||||
proxy.getAge();
|
||||
|
||||
NamedBean nb = (NamedBean) proxy;
|
||||
assertEquals("Name returned correctly", beanName, nb.getBeanName());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
|
||||
|
||||
<!--
|
||||
Tests for throws advice.
|
||||
-->
|
||||
<beans>
|
||||
|
||||
<bean id="nopInterceptor" class="test.aop.NopInterceptor"/>
|
||||
|
||||
<bean id="exposeInvocation" class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean">
|
||||
<property name="targetClass">
|
||||
<value>org.springframework.aop.interceptor.ExposeInvocationInterceptor</value>
|
||||
</property>
|
||||
<property name="targetField"><value>INSTANCE</value></property>
|
||||
</bean>
|
||||
|
||||
<bean id="countingBeforeAdvice" class="test.aop.CountingBeforeAdvice"/>
|
||||
|
||||
<bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||
<property name="target">
|
||||
<bean class="org.springframework.aop.interceptor.InvocationCheckExposedInvocationTestBean" />
|
||||
</property>
|
||||
<property name="interceptorNames">
|
||||
<value>exposeInvocation,countingBeforeAdvice,nopInterceptor</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.interceptor;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static test.util.TestResourceUtils.qualifiedResource;
|
||||
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.xml.XmlBeanFactory;
|
||||
import org.springframework.core.io.Resource;
|
||||
|
||||
import test.beans.ITestBean;
|
||||
import test.beans.TestBean;
|
||||
|
||||
/**
|
||||
* Non-XML tests are in AbstractAopProxyTests
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public final class ExposeInvocationInterceptorTests {
|
||||
|
||||
private static final Resource CONTEXT =
|
||||
qualifiedResource(ExposeInvocationInterceptorTests.class, "context.xml");
|
||||
|
||||
@Test
|
||||
public void testXmlConfig() {
|
||||
XmlBeanFactory bf = new XmlBeanFactory(CONTEXT);
|
||||
ITestBean tb = (ITestBean) bf.getBean("proxy");
|
||||
String name= "tony";
|
||||
tb.setName(name);
|
||||
// Fires context checks
|
||||
assertEquals(name, tb.getName());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
abstract class ExposedInvocationTestBean extends TestBean {
|
||||
|
||||
public String getName() {
|
||||
MethodInvocation invocation = ExposeInvocationInterceptor.currentInvocation();
|
||||
assertions(invocation);
|
||||
return super.getName();
|
||||
}
|
||||
|
||||
public void absquatulate() {
|
||||
MethodInvocation invocation = ExposeInvocationInterceptor.currentInvocation();
|
||||
assertions(invocation);
|
||||
super.absquatulate();
|
||||
}
|
||||
|
||||
protected abstract void assertions(MethodInvocation invocation);
|
||||
}
|
||||
|
||||
|
||||
class InvocationCheckExposedInvocationTestBean extends ExposedInvocationTestBean {
|
||||
protected void assertions(MethodInvocation invocation) {
|
||||
assertTrue(invocation.getThis() == this);
|
||||
assertTrue("Invocation should be on ITestBean: " + invocation.getMethod(),
|
||||
ITestBean.class.isAssignableFrom(invocation.getMethod().getDeclaringClass()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.interceptor;
|
||||
|
||||
import static org.easymock.EasyMock.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
* @author Rick Evans
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public final class PerformanceMonitorInterceptorTests {
|
||||
|
||||
@Test
|
||||
public void testSuffixAndPrefixAssignment() {
|
||||
PerformanceMonitorInterceptor interceptor = new PerformanceMonitorInterceptor();
|
||||
|
||||
assertNotNull(interceptor.getPrefix());
|
||||
assertNotNull(interceptor.getSuffix());
|
||||
|
||||
interceptor.setPrefix(null);
|
||||
interceptor.setSuffix(null);
|
||||
|
||||
assertNotNull(interceptor.getPrefix());
|
||||
assertNotNull(interceptor.getSuffix());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSunnyDayPathLogsPerformanceMetricsCorrectly() throws Throwable {
|
||||
Log log = createMock(Log.class);
|
||||
MethodInvocation mi = createMock(MethodInvocation.class);
|
||||
|
||||
Method toString = String.class.getMethod("toString", new Class[0]);
|
||||
|
||||
expect(mi.getMethod()).andReturn(toString);
|
||||
expect(mi.proceed()).andReturn(null);
|
||||
log.trace(isA(String.class));
|
||||
|
||||
replay(mi, log);
|
||||
|
||||
PerformanceMonitorInterceptor interceptor = new PerformanceMonitorInterceptor(true);
|
||||
interceptor.invokeUnderTrace(mi, log);
|
||||
|
||||
verify(mi, log);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExceptionPathStillLogsPerformanceMetricsCorrectly() throws Throwable {
|
||||
Log log = createMock(Log.class);
|
||||
MethodInvocation mi = createMock(MethodInvocation.class);
|
||||
|
||||
Method toString = String.class.getMethod("toString", new Class[0]);
|
||||
|
||||
expect(mi.getMethod()).andReturn(toString);
|
||||
expect(mi.proceed()).andThrow(new IllegalArgumentException());
|
||||
log.trace(isA(String.class));
|
||||
|
||||
replay(mi, log);
|
||||
|
||||
PerformanceMonitorInterceptor interceptor = new PerformanceMonitorInterceptor(true);
|
||||
try {
|
||||
interceptor.invokeUnderTrace(mi, log);
|
||||
fail("Must have propagated the IllegalArgumentException.");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
}
|
||||
|
||||
verify(mi, log);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.interceptor;
|
||||
|
||||
import static org.easymock.EasyMock.*;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Unit tests for the {@link SimpleTraceInterceptor} class.
|
||||
*
|
||||
* @author Rick Evans
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public final class SimpleTraceInterceptorTests {
|
||||
|
||||
@Test
|
||||
public void testSunnyDayPathLogsCorrectly() throws Throwable {
|
||||
Log log = createMock(Log.class);
|
||||
MethodInvocation mi = createMock(MethodInvocation.class);
|
||||
|
||||
Method toString = String.class.getMethod("toString", new Class[]{});
|
||||
|
||||
expect(mi.getMethod()).andReturn(toString);
|
||||
expect(mi.getThis()).andReturn(this);
|
||||
log.trace(isA(String.class));
|
||||
expect(mi.proceed()).andReturn(null);
|
||||
log.trace(isA(String.class));
|
||||
|
||||
replay(mi, log);
|
||||
|
||||
SimpleTraceInterceptor interceptor = new SimpleTraceInterceptor(true);
|
||||
interceptor.invokeUnderTrace(mi, log);
|
||||
|
||||
verify(mi, log);
|
||||
}
|
||||
|
||||
public void testExceptionPathStillLogsCorrectly() throws Throwable {
|
||||
Log log = createMock(Log.class);
|
||||
MethodInvocation mi = createMock(MethodInvocation.class);
|
||||
|
||||
Method toString = String.class.getMethod("toString", new Class[]{});
|
||||
|
||||
expect(mi.getMethod()).andReturn(toString);
|
||||
expect(mi.getThis()).andReturn(this);
|
||||
log.trace(isA(String.class));
|
||||
IllegalArgumentException exception = new IllegalArgumentException();
|
||||
expect(mi.proceed()).andThrow(exception);
|
||||
log.trace(isA(String.class));
|
||||
|
||||
replay(mi, log);
|
||||
|
||||
final SimpleTraceInterceptor interceptor = new SimpleTraceInterceptor(true);
|
||||
|
||||
try {
|
||||
interceptor.invokeUnderTrace(mi, log);
|
||||
fail("Must have propagated the IllegalArgumentException.");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
}
|
||||
|
||||
verify(mi, log);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.scope;
|
||||
|
||||
import static org.easymock.EasyMock.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
|
||||
/**
|
||||
* Unit tests for the {@link DefaultScopedObject} class.
|
||||
*
|
||||
* @author Rick Evans
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public final class DefaultScopedObjectTests {
|
||||
|
||||
private static final String GOOD_BEAN_NAME = "foo";
|
||||
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testCtorWithNullBeanFactory() throws Exception {
|
||||
new DefaultScopedObject(null, GOOD_BEAN_NAME);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testCtorWithNullTargetBeanName() throws Exception {
|
||||
testBadTargetBeanName(null);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testCtorWithEmptyTargetBeanName() throws Exception {
|
||||
testBadTargetBeanName("");
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testCtorWithJustWhitespacedTargetBeanName() throws Exception {
|
||||
testBadTargetBeanName(" ");
|
||||
}
|
||||
|
||||
|
||||
private static void testBadTargetBeanName(final String badTargetBeanName) {
|
||||
ConfigurableBeanFactory factory = createMock(ConfigurableBeanFactory.class);
|
||||
replay(factory);
|
||||
|
||||
new DefaultScopedObject(factory, badTargetBeanName);
|
||||
|
||||
verify(factory);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:aop="http://www.springframework.org/schema/aop"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
|
||||
|
||||
<bean id="scoped" class="org.springframework.aop.scope.ScopedProxyAutowireTests$TestBean" autowire-candidate="false">
|
||||
<aop:scoped-proxy/>
|
||||
</bean>
|
||||
|
||||
<bean id="unscoped" class="org.springframework.aop.scope.ScopedProxyAutowireTests$TestBean" autowire-candidate="true"/>
|
||||
|
||||
<bean id="autowired" class="org.springframework.aop.scope.ScopedProxyAutowireTests$TestBean" autowire="byType"/>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:aop="http://www.springframework.org/schema/aop"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
|
||||
|
||||
<bean id="scoped" class="org.springframework.aop.scope.ScopedProxyAutowireTests$TestBean" autowire-candidate="true">
|
||||
<aop:scoped-proxy/>
|
||||
</bean>
|
||||
|
||||
<bean id="unscoped" class="org.springframework.aop.scope.ScopedProxyAutowireTests$TestBean" autowire-candidate="false"/>
|
||||
|
||||
<bean id="autowired" class="org.springframework.aop.scope.ScopedProxyAutowireTests$TestBean" autowire="byType"/>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.scope;
|
||||
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static test.util.TestResourceUtils.qualifiedResource;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.xml.XmlBeanFactory;
|
||||
import org.springframework.core.io.Resource;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public final class ScopedProxyAutowireTests {
|
||||
|
||||
private static final Class<?> CLASS = ScopedProxyAutowireTests.class;
|
||||
|
||||
private static final Resource SCOPED_AUTOWIRE_TRUE_CONTEXT = qualifiedResource(CLASS, "scopedAutowireTrue.xml");
|
||||
private static final Resource SCOPED_AUTOWIRE_FALSE_CONTEXT = qualifiedResource(CLASS, "scopedAutowireFalse.xml");
|
||||
|
||||
@Test
|
||||
public void testScopedProxyInheritsAutowireCandidateFalse() {
|
||||
XmlBeanFactory bf = new XmlBeanFactory(SCOPED_AUTOWIRE_FALSE_CONTEXT);
|
||||
TestBean autowired = (TestBean) bf.getBean("autowired");
|
||||
TestBean unscoped = (TestBean) bf.getBean("unscoped");
|
||||
assertSame(unscoped, autowired.getChild());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScopedProxyReplacesAutowireCandidateTrue() {
|
||||
XmlBeanFactory bf = new XmlBeanFactory(SCOPED_AUTOWIRE_TRUE_CONTEXT);
|
||||
TestBean autowired = (TestBean) bf.getBean("autowired");
|
||||
TestBean scoped = (TestBean) bf.getBean("scoped");
|
||||
assertSame(scoped, autowired.getChild());
|
||||
}
|
||||
|
||||
|
||||
static class TestBean {
|
||||
|
||||
private TestBean child;
|
||||
|
||||
public void setChild(TestBean child) {
|
||||
this.child = child;
|
||||
}
|
||||
|
||||
public TestBean getChild() {
|
||||
return this.child;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.support;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import test.beans.TestBean;
|
||||
import test.util.SerializationTestUtils;
|
||||
|
||||
/**
|
||||
* @author Rod Johnson
|
||||
* @author Dmitriy Kopylenko
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public abstract class AbstractRegexpMethodPointcutTests {
|
||||
|
||||
private AbstractRegexpMethodPointcut rpc;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
rpc = getRegexpMethodPointcut();
|
||||
}
|
||||
|
||||
protected abstract AbstractRegexpMethodPointcut getRegexpMethodPointcut();
|
||||
|
||||
@Test
|
||||
public void testNoPatternSupplied() throws Exception {
|
||||
noPatternSuppliedTests(rpc);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSerializationWithNoPatternSupplied() throws Exception {
|
||||
rpc = (AbstractRegexpMethodPointcut) SerializationTestUtils.serializeAndDeserialize(rpc);
|
||||
noPatternSuppliedTests(rpc);
|
||||
}
|
||||
|
||||
protected void noPatternSuppliedTests(AbstractRegexpMethodPointcut rpc) throws Exception {
|
||||
assertFalse(rpc.matches(Object.class.getMethod("hashCode", (Class[]) null), String.class));
|
||||
assertFalse(rpc.matches(Object.class.getMethod("wait", (Class[]) null), Object.class));
|
||||
assertEquals(0, rpc.getPatterns().length);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExactMatch() throws Exception {
|
||||
rpc.setPattern("java.lang.Object.hashCode");
|
||||
exactMatchTests(rpc);
|
||||
rpc = (AbstractRegexpMethodPointcut) SerializationTestUtils.serializeAndDeserialize(rpc);
|
||||
exactMatchTests(rpc);
|
||||
}
|
||||
|
||||
protected void exactMatchTests(AbstractRegexpMethodPointcut rpc) throws Exception {
|
||||
// assumes rpc.setPattern("java.lang.Object.hashCode");
|
||||
assertTrue(rpc.matches(Object.class.getMethod("hashCode", (Class[]) null), String.class));
|
||||
assertTrue(rpc.matches(Object.class.getMethod("hashCode", (Class[]) null), Object.class));
|
||||
assertFalse(rpc.matches(Object.class.getMethod("wait", (Class[]) null), Object.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpecificMatch() throws Exception {
|
||||
rpc.setPattern("java.lang.String.hashCode");
|
||||
assertTrue(rpc.matches(Object.class.getMethod("hashCode", (Class[]) null), String.class));
|
||||
assertFalse(rpc.matches(Object.class.getMethod("hashCode", (Class[]) null), Object.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWildcard() throws Exception {
|
||||
rpc.setPattern(".*Object.hashCode");
|
||||
assertTrue(rpc.matches(Object.class.getMethod("hashCode", (Class[]) null), Object.class));
|
||||
assertFalse(rpc.matches(Object.class.getMethod("wait", (Class[]) null), Object.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWildcardForOneClass() throws Exception {
|
||||
rpc.setPattern("java.lang.Object.*");
|
||||
assertTrue(rpc.matches(Object.class.getMethod("hashCode", (Class[]) null), String.class));
|
||||
assertTrue(rpc.matches(Object.class.getMethod("wait", (Class[]) null), String.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchesObjectClass() throws Exception {
|
||||
rpc.setPattern("java.lang.Object.*");
|
||||
assertTrue(rpc.matches(Exception.class.getMethod("hashCode", (Class[]) null), IOException.class));
|
||||
// Doesn't match a method from Throwable
|
||||
assertFalse(rpc.matches(Exception.class.getMethod("getMessage", (Class[]) null), Exception.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithExclusion() throws Exception {
|
||||
this.rpc.setPattern(".*get.*");
|
||||
this.rpc.setExcludedPattern(".*Age.*");
|
||||
assertTrue(this.rpc.matches(TestBean.class.getMethod("getName"), TestBean.class));
|
||||
assertFalse(this.rpc.matches(TestBean.class.getMethod("getAge"), TestBean.class));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.support;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.aop.ClassFilter;
|
||||
import org.springframework.aop.MethodMatcher;
|
||||
import org.springframework.aop.Pointcut;
|
||||
import org.springframework.aop.interceptor.ExposeInvocationInterceptor;
|
||||
import org.springframework.aop.target.EmptyTargetSource;
|
||||
|
||||
import test.aop.NopInterceptor;
|
||||
import test.beans.TestBean;
|
||||
import test.util.SerializationTestUtils;
|
||||
|
||||
/**
|
||||
* @author Rod Johnson
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public final class AopUtilsTests {
|
||||
|
||||
@Test
|
||||
public void testPointcutCanNeverApply() {
|
||||
class TestPointcut extends StaticMethodMatcherPointcut {
|
||||
public boolean matches(Method method, Class<?> clazzy) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Pointcut no = new TestPointcut();
|
||||
assertFalse(AopUtils.canApply(no, Object.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPointcutAlwaysApplies() {
|
||||
assertTrue(AopUtils.canApply(new DefaultPointcutAdvisor(new NopInterceptor()), Object.class));
|
||||
assertTrue(AopUtils.canApply(new DefaultPointcutAdvisor(new NopInterceptor()), TestBean.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPointcutAppliesToOneMethodOnObject() {
|
||||
class TestPointcut extends StaticMethodMatcherPointcut {
|
||||
public boolean matches(Method method, Class<?> clazz) {
|
||||
return method.getName().equals("hashCode");
|
||||
}
|
||||
}
|
||||
|
||||
Pointcut pc = new TestPointcut();
|
||||
|
||||
// will return true if we're not proxying interfaces
|
||||
assertTrue(AopUtils.canApply(pc, Object.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that when we serialize and deserialize various canonical instances
|
||||
* of AOP classes, they return the same instance, not a new instance
|
||||
* that's subverted the singleton construction limitation.
|
||||
*/
|
||||
@Test
|
||||
public void testCanonicalFrameworkClassesStillCanonicalOnDeserialization() throws Exception {
|
||||
assertSame(MethodMatcher.TRUE, SerializationTestUtils.serializeAndDeserialize(MethodMatcher.TRUE));
|
||||
assertSame(ClassFilter.TRUE, SerializationTestUtils.serializeAndDeserialize(ClassFilter.TRUE));
|
||||
assertSame(Pointcut.TRUE, SerializationTestUtils.serializeAndDeserialize(Pointcut.TRUE));
|
||||
assertSame(EmptyTargetSource.INSTANCE, SerializationTestUtils.serializeAndDeserialize(EmptyTargetSource.INSTANCE));
|
||||
assertSame(Pointcuts.SETTERS, SerializationTestUtils.serializeAndDeserialize(Pointcuts.SETTERS));
|
||||
assertSame(Pointcuts.GETTERS, SerializationTestUtils.serializeAndDeserialize(Pointcuts.GETTERS));
|
||||
assertSame(ExposeInvocationInterceptor.INSTANCE,
|
||||
SerializationTestUtils.serializeAndDeserialize(ExposeInvocationInterceptor.INSTANCE));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.support;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.aop.ClassFilter;
|
||||
import org.springframework.core.NestedRuntimeException;
|
||||
|
||||
import test.beans.ITestBean;
|
||||
import test.beans.TestBean;
|
||||
|
||||
/**
|
||||
* @author Rod Johnson
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public final class ClassFiltersTests {
|
||||
|
||||
private ClassFilter exceptionFilter = new RootClassFilter(Exception.class);
|
||||
|
||||
private ClassFilter itbFilter = new RootClassFilter(ITestBean.class);
|
||||
|
||||
private ClassFilter hasRootCauseFilter = new RootClassFilter(NestedRuntimeException.class);
|
||||
|
||||
@Test
|
||||
public void testUnion() {
|
||||
assertTrue(exceptionFilter.matches(RuntimeException.class));
|
||||
assertFalse(exceptionFilter.matches(TestBean.class));
|
||||
assertFalse(itbFilter.matches(Exception.class));
|
||||
assertTrue(itbFilter.matches(TestBean.class));
|
||||
ClassFilter union = ClassFilters.union(exceptionFilter, itbFilter);
|
||||
assertTrue(union.matches(RuntimeException.class));
|
||||
assertTrue(union.matches(TestBean.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIntersection() {
|
||||
assertTrue(exceptionFilter.matches(RuntimeException.class));
|
||||
assertTrue(hasRootCauseFilter.matches(NestedRuntimeException.class));
|
||||
ClassFilter intersection = ClassFilters.intersection(exceptionFilter, hasRootCauseFilter);
|
||||
assertFalse(intersection.matches(RuntimeException.class));
|
||||
assertFalse(intersection.matches(TestBean.class));
|
||||
assertTrue(intersection.matches(NestedRuntimeException.class));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2002-2009 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.support;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import test.beans.TestBean;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* @author Colin Sampaleanu
|
||||
* @author Juergen Hoeller
|
||||
* @author Rob Harrop
|
||||
* @author Rick Evans
|
||||
*/
|
||||
public class ClassUtilsTests extends TestCase {
|
||||
|
||||
public void testGetShortNameForCglibClass() {
|
||||
TestBean tb = new TestBean();
|
||||
ProxyFactory pf = new ProxyFactory();
|
||||
pf.setTarget(tb);
|
||||
pf.setProxyTargetClass(true);
|
||||
TestBean proxy = (TestBean) pf.getProxy();
|
||||
String className = ClassUtils.getShortName(proxy.getClass());
|
||||
assertEquals("Class name did not match", "TestBean", className);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.support;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.aop.ClassFilter;
|
||||
import org.springframework.aop.MethodMatcher;
|
||||
import org.springframework.aop.Pointcut;
|
||||
import org.springframework.core.NestedRuntimeException;
|
||||
|
||||
import test.beans.TestBean;
|
||||
|
||||
/**
|
||||
* @author Rod Johnson
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public final class ComposablePointcutTests {
|
||||
|
||||
public static MethodMatcher GETTER_METHOD_MATCHER = new StaticMethodMatcher() {
|
||||
public boolean matches(Method m, Class<?> targetClass) {
|
||||
return m.getName().startsWith("get");
|
||||
}
|
||||
};
|
||||
|
||||
public static MethodMatcher GET_AGE_METHOD_MATCHER = new StaticMethodMatcher() {
|
||||
public boolean matches(Method m, Class<?> targetClass) {
|
||||
return m.getName().equals("getAge");
|
||||
}
|
||||
};
|
||||
|
||||
public static MethodMatcher ABSQUATULATE_METHOD_MATCHER = new StaticMethodMatcher() {
|
||||
public boolean matches(Method m, Class<?> targetClass) {
|
||||
return m.getName().equals("absquatulate");
|
||||
}
|
||||
};
|
||||
|
||||
public static MethodMatcher SETTER_METHOD_MATCHER = new StaticMethodMatcher() {
|
||||
public boolean matches(Method m, Class<?> targetClass) {
|
||||
return m.getName().startsWith("set");
|
||||
}
|
||||
};
|
||||
|
||||
@Test
|
||||
public void testMatchAll() throws NoSuchMethodException {
|
||||
Pointcut pc = new ComposablePointcut();
|
||||
assertTrue(pc.getClassFilter().matches(Object.class));
|
||||
assertTrue(pc.getMethodMatcher().matches(Object.class.getMethod("hashCode", (Class[]) null), Exception.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFilterByClass() throws NoSuchMethodException {
|
||||
ComposablePointcut pc = new ComposablePointcut();
|
||||
|
||||
assertTrue(pc.getClassFilter().matches(Object.class));
|
||||
|
||||
ClassFilter cf = new RootClassFilter(Exception.class);
|
||||
pc.intersection(cf);
|
||||
assertFalse(pc.getClassFilter().matches(Object.class));
|
||||
assertTrue(pc.getClassFilter().matches(Exception.class));
|
||||
pc.intersection(new RootClassFilter(NestedRuntimeException.class));
|
||||
assertFalse(pc.getClassFilter().matches(Exception.class));
|
||||
assertTrue(pc.getClassFilter().matches(NestedRuntimeException.class));
|
||||
assertFalse(pc.getClassFilter().matches(String.class));
|
||||
pc.union(new RootClassFilter(String.class));
|
||||
assertFalse(pc.getClassFilter().matches(Exception.class));
|
||||
assertTrue(pc.getClassFilter().matches(String.class));
|
||||
assertTrue(pc.getClassFilter().matches(NestedRuntimeException.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnionMethodMatcher() {
|
||||
// Matches the getAge() method in any class
|
||||
ComposablePointcut pc = new ComposablePointcut(ClassFilter.TRUE, GET_AGE_METHOD_MATCHER);
|
||||
assertFalse(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_ABSQUATULATE, TestBean.class, null));
|
||||
assertTrue(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_GET_AGE, TestBean.class, null));
|
||||
assertFalse(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_GET_NAME, TestBean.class, null));
|
||||
|
||||
pc.union(GETTER_METHOD_MATCHER);
|
||||
// Should now match all getter methods
|
||||
assertFalse(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_ABSQUATULATE, TestBean.class, null));
|
||||
assertTrue(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_GET_AGE, TestBean.class, null));
|
||||
assertTrue(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_GET_NAME, TestBean.class, null));
|
||||
|
||||
pc.union(ABSQUATULATE_METHOD_MATCHER);
|
||||
// Should now match absquatulate() as well
|
||||
assertTrue(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_ABSQUATULATE, TestBean.class, null));
|
||||
assertTrue(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_GET_AGE, TestBean.class, null));
|
||||
assertTrue(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_GET_NAME, TestBean.class, null));
|
||||
// But it doesn't match everything
|
||||
assertFalse(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_SET_AGE, TestBean.class, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIntersectionMethodMatcher() {
|
||||
ComposablePointcut pc = new ComposablePointcut();
|
||||
assertTrue(pc.getMethodMatcher().matches(PointcutsTests.TEST_BEAN_ABSQUATULATE, TestBean.class));
|
||||
assertTrue(pc.getMethodMatcher().matches(PointcutsTests.TEST_BEAN_GET_AGE, TestBean.class));
|
||||
assertTrue(pc.getMethodMatcher().matches(PointcutsTests.TEST_BEAN_GET_NAME, TestBean.class));
|
||||
pc.intersection(GETTER_METHOD_MATCHER);
|
||||
assertFalse(pc.getMethodMatcher().matches(PointcutsTests.TEST_BEAN_ABSQUATULATE, TestBean.class));
|
||||
assertTrue(pc.getMethodMatcher().matches(PointcutsTests.TEST_BEAN_GET_AGE, TestBean.class));
|
||||
assertTrue(pc.getMethodMatcher().matches(PointcutsTests.TEST_BEAN_GET_NAME, TestBean.class));
|
||||
pc.intersection(GET_AGE_METHOD_MATCHER);
|
||||
// Use the Pointcuts matches method
|
||||
assertFalse(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_ABSQUATULATE, TestBean.class, null));
|
||||
assertTrue(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_GET_AGE, TestBean.class, null));
|
||||
assertFalse(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_GET_NAME, TestBean.class, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEqualsAndHashCode() throws Exception {
|
||||
ComposablePointcut pc1 = new ComposablePointcut();
|
||||
ComposablePointcut pc2 = new ComposablePointcut();
|
||||
|
||||
assertEquals(pc1, pc2);
|
||||
assertEquals(pc1.hashCode(), pc2.hashCode());
|
||||
|
||||
pc1.intersection(GETTER_METHOD_MATCHER);
|
||||
|
||||
assertFalse(pc1.equals(pc2));
|
||||
assertFalse(pc1.hashCode() == pc2.hashCode());
|
||||
|
||||
pc2.intersection(GETTER_METHOD_MATCHER);
|
||||
|
||||
assertEquals(pc1, pc2);
|
||||
assertEquals(pc1.hashCode(), pc2.hashCode());
|
||||
|
||||
pc1.union(GET_AGE_METHOD_MATCHER);
|
||||
pc2.union(GET_AGE_METHOD_MATCHER);
|
||||
|
||||
assertEquals(pc1, pc2);
|
||||
assertEquals(pc1.hashCode(), pc2.hashCode());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.support;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.aop.Pointcut;
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
|
||||
import test.aop.NopInterceptor;
|
||||
import test.beans.ITestBean;
|
||||
import test.beans.TestBean;
|
||||
|
||||
/**
|
||||
* @author Rod Johnson
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public final class ControlFlowPointcutTests {
|
||||
|
||||
@Test
|
||||
public void testMatches() {
|
||||
TestBean target = new TestBean();
|
||||
target.setAge(27);
|
||||
NopInterceptor nop = new NopInterceptor();
|
||||
ControlFlowPointcut cflow = new ControlFlowPointcut(One.class, "getAge");
|
||||
ProxyFactory pf = new ProxyFactory(target);
|
||||
ITestBean proxied = (ITestBean) pf.getProxy();
|
||||
pf.addAdvisor(new DefaultPointcutAdvisor(cflow, nop));
|
||||
|
||||
// Not advised, not under One
|
||||
assertEquals(target.getAge(), proxied.getAge());
|
||||
assertEquals(0, nop.getCount());
|
||||
|
||||
// Will be advised
|
||||
assertEquals(target.getAge(), new One().getAge(proxied));
|
||||
assertEquals(1, nop.getCount());
|
||||
|
||||
// Won't be advised
|
||||
assertEquals(target.getAge(), new One().nomatch(proxied));
|
||||
assertEquals(1, nop.getCount());
|
||||
assertEquals(3, cflow.getEvaluations());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that we can use a cflow pointcut only in conjunction with
|
||||
* a static pointcut: e.g. all setter methods that are invoked under
|
||||
* a particular class. This greatly reduces the number of calls
|
||||
* to the cflow pointcut, meaning that it's not so prohibitively
|
||||
* expensive.
|
||||
*/
|
||||
@Test
|
||||
public void testSelectiveApplication() {
|
||||
TestBean target = new TestBean();
|
||||
target.setAge(27);
|
||||
NopInterceptor nop = new NopInterceptor();
|
||||
ControlFlowPointcut cflow = new ControlFlowPointcut(One.class);
|
||||
Pointcut settersUnderOne = Pointcuts.intersection(Pointcuts.SETTERS, cflow);
|
||||
ProxyFactory pf = new ProxyFactory(target);
|
||||
ITestBean proxied = (ITestBean) pf.getProxy();
|
||||
pf.addAdvisor(new DefaultPointcutAdvisor(settersUnderOne, nop));
|
||||
|
||||
// Not advised, not under One
|
||||
target.setAge(16);
|
||||
assertEquals(0, nop.getCount());
|
||||
|
||||
// Not advised; under One but not a setter
|
||||
assertEquals(16, new One().getAge(proxied));
|
||||
assertEquals(0, nop.getCount());
|
||||
|
||||
// Won't be advised
|
||||
new One().set(proxied);
|
||||
assertEquals(1, nop.getCount());
|
||||
|
||||
// We saved most evaluations
|
||||
assertEquals(1, cflow.getEvaluations());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEqualsAndHashCode() throws Exception {
|
||||
assertEquals(new ControlFlowPointcut(One.class), new ControlFlowPointcut(One.class));
|
||||
assertEquals(new ControlFlowPointcut(One.class, "getAge"), new ControlFlowPointcut(One.class, "getAge"));
|
||||
assertFalse(new ControlFlowPointcut(One.class, "getAge").equals(new ControlFlowPointcut(One.class)));
|
||||
assertEquals(new ControlFlowPointcut(One.class).hashCode(), new ControlFlowPointcut(One.class).hashCode());
|
||||
assertEquals(new ControlFlowPointcut(One.class, "getAge").hashCode(), new ControlFlowPointcut(One.class, "getAge").hashCode());
|
||||
assertFalse(new ControlFlowPointcut(One.class, "getAge").hashCode() == new ControlFlowPointcut(One.class).hashCode());
|
||||
}
|
||||
|
||||
public class One {
|
||||
int getAge(ITestBean proxied) {
|
||||
return proxied.getAge();
|
||||
}
|
||||
int nomatch(ITestBean proxied) {
|
||||
return proxied.getAge();
|
||||
}
|
||||
void set(ITestBean proxied) {
|
||||
proxied.setAge(5);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,310 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.support;
|
||||
|
||||
import static org.easymock.EasyMock.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.junit.Test;
|
||||
import org.springframework.aop.IntroductionAdvisor;
|
||||
import org.springframework.aop.IntroductionInterceptor;
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
|
||||
import test.aop.SerializableNopInterceptor;
|
||||
import test.beans.INestedTestBean;
|
||||
import test.beans.ITestBean;
|
||||
import test.beans.NestedTestBean;
|
||||
import test.beans.Person;
|
||||
import test.beans.SerializablePerson;
|
||||
import test.beans.TestBean;
|
||||
import test.util.SerializationTestUtils;
|
||||
import test.util.TimeStamped;
|
||||
|
||||
/**
|
||||
* @author Rod Johnson
|
||||
* @author Chris Beams
|
||||
* @since 13.05.2003
|
||||
*/
|
||||
public final class DelegatingIntroductionInterceptorTests {
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testNullTarget() throws Exception {
|
||||
// Shouldn't accept null target
|
||||
new DelegatingIntroductionInterceptor(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIntroductionInterceptorWithDelegation() throws Exception {
|
||||
TestBean raw = new TestBean();
|
||||
assertTrue(! (raw instanceof TimeStamped));
|
||||
ProxyFactory factory = new ProxyFactory(raw);
|
||||
|
||||
TimeStamped ts = createMock(TimeStamped.class);
|
||||
long timestamp = 111L;
|
||||
expect(ts.getTimeStamp()).andReturn(timestamp);
|
||||
replay(ts);
|
||||
|
||||
factory.addAdvisor(0, new DefaultIntroductionAdvisor(new DelegatingIntroductionInterceptor(ts)));
|
||||
|
||||
TimeStamped tsp = (TimeStamped) factory.getProxy();
|
||||
assertTrue(tsp.getTimeStamp() == timestamp);
|
||||
|
||||
verify(ts);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIntroductionInterceptorWithInterfaceHierarchy() throws Exception {
|
||||
TestBean raw = new TestBean();
|
||||
assertTrue(! (raw instanceof SubTimeStamped));
|
||||
ProxyFactory factory = new ProxyFactory(raw);
|
||||
|
||||
TimeStamped ts = createMock(SubTimeStamped.class);
|
||||
long timestamp = 111L;
|
||||
expect(ts.getTimeStamp()).andReturn(timestamp);
|
||||
replay(ts);
|
||||
|
||||
factory.addAdvisor(0, new DefaultIntroductionAdvisor(new DelegatingIntroductionInterceptor(ts), SubTimeStamped.class));
|
||||
|
||||
SubTimeStamped tsp = (SubTimeStamped) factory.getProxy();
|
||||
assertTrue(tsp.getTimeStamp() == timestamp);
|
||||
|
||||
verify(ts);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIntroductionInterceptorWithSuperInterface() throws Exception {
|
||||
TestBean raw = new TestBean();
|
||||
assertTrue(! (raw instanceof TimeStamped));
|
||||
ProxyFactory factory = new ProxyFactory(raw);
|
||||
|
||||
TimeStamped ts = createMock(SubTimeStamped.class);
|
||||
long timestamp = 111L;
|
||||
expect(ts.getTimeStamp()).andReturn(timestamp);
|
||||
replay(ts);
|
||||
|
||||
factory.addAdvisor(0, new DefaultIntroductionAdvisor(new DelegatingIntroductionInterceptor(ts), TimeStamped.class));
|
||||
|
||||
TimeStamped tsp = (TimeStamped) factory.getProxy();
|
||||
assertTrue(!(tsp instanceof SubTimeStamped));
|
||||
assertTrue(tsp.getTimeStamp() == timestamp);
|
||||
|
||||
verify(ts);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAutomaticInterfaceRecognitionInDelegate() throws Exception {
|
||||
final long t = 1001L;
|
||||
class Tester implements TimeStamped, ITester {
|
||||
public void foo() throws Exception {
|
||||
}
|
||||
public long getTimeStamp() {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
DelegatingIntroductionInterceptor ii = new DelegatingIntroductionInterceptor(new Tester());
|
||||
|
||||
TestBean target = new TestBean();
|
||||
|
||||
ProxyFactory pf = new ProxyFactory(target);
|
||||
pf.addAdvisor(0, new DefaultIntroductionAdvisor(ii));
|
||||
|
||||
//assertTrue(Arrays.binarySearch(pf.getProxiedInterfaces(), TimeStamped.class) != -1);
|
||||
TimeStamped ts = (TimeStamped) pf.getProxy();
|
||||
|
||||
assertTrue(ts.getTimeStamp() == t);
|
||||
((ITester) ts).foo();
|
||||
|
||||
((ITestBean) ts).getAge();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testAutomaticInterfaceRecognitionInSubclass() throws Exception {
|
||||
final long t = 1001L;
|
||||
@SuppressWarnings("serial")
|
||||
class TestII extends DelegatingIntroductionInterceptor implements TimeStamped, ITester {
|
||||
public void foo() throws Exception {
|
||||
}
|
||||
public long getTimeStamp() {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
DelegatingIntroductionInterceptor ii = new TestII();
|
||||
|
||||
TestBean target = new TestBean();
|
||||
|
||||
ProxyFactory pf = new ProxyFactory(target);
|
||||
IntroductionAdvisor ia = new DefaultIntroductionAdvisor(ii);
|
||||
assertTrue(ia.isPerInstance());
|
||||
pf.addAdvisor(0, ia);
|
||||
|
||||
//assertTrue(Arrays.binarySearch(pf.getProxiedInterfaces(), TimeStamped.class) != -1);
|
||||
TimeStamped ts = (TimeStamped) pf.getProxy();
|
||||
|
||||
assertTrue(ts instanceof TimeStamped);
|
||||
// Shoulnd't proxy framework interfaces
|
||||
assertTrue(!(ts instanceof MethodInterceptor));
|
||||
assertTrue(!(ts instanceof IntroductionInterceptor));
|
||||
|
||||
assertTrue(ts.getTimeStamp() == t);
|
||||
((ITester) ts).foo();
|
||||
((ITestBean) ts).getAge();
|
||||
|
||||
// Test removal
|
||||
ii.suppressInterface(TimeStamped.class);
|
||||
// Note that we need to construct a new proxy factory,
|
||||
// or suppress the interface on the proxy factory
|
||||
pf = new ProxyFactory(target);
|
||||
pf.addAdvisor(0, new DefaultIntroductionAdvisor(ii));
|
||||
Object o = pf.getProxy();
|
||||
assertTrue(!(o instanceof TimeStamped));
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
@Test
|
||||
public void testIntroductionInterceptorDoesntReplaceToString() throws Exception {
|
||||
TestBean raw = new TestBean();
|
||||
assertTrue(! (raw instanceof TimeStamped));
|
||||
ProxyFactory factory = new ProxyFactory(raw);
|
||||
|
||||
TimeStamped ts = new SerializableTimeStamped(0);
|
||||
|
||||
factory.addAdvisor(0, new DefaultIntroductionAdvisor(new DelegatingIntroductionInterceptor(ts) {
|
||||
public String toString() {
|
||||
throw new UnsupportedOperationException("Shouldn't be invoked");
|
||||
}
|
||||
}));
|
||||
|
||||
TimeStamped tsp = (TimeStamped) factory.getProxy();
|
||||
assertEquals(0, tsp.getTimeStamp());
|
||||
|
||||
assertEquals(raw.toString(), tsp.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDelegateReturnsThisIsMassagedToReturnProxy() {
|
||||
NestedTestBean target = new NestedTestBean();
|
||||
String company = "Interface21";
|
||||
target.setCompany(company);
|
||||
TestBean delegate = new TestBean() {
|
||||
public ITestBean getSpouse() {
|
||||
return this;
|
||||
}
|
||||
};
|
||||
ProxyFactory pf = new ProxyFactory(target);
|
||||
pf.addAdvice(new DelegatingIntroductionInterceptor(delegate));
|
||||
INestedTestBean proxy = (INestedTestBean) pf.getProxy();
|
||||
|
||||
assertEquals(company, proxy.getCompany());
|
||||
ITestBean introduction = (ITestBean) proxy;
|
||||
assertSame("Introduced method returning delegate returns proxy", introduction, introduction.getSpouse());
|
||||
assertTrue("Introduced method returning delegate returns proxy", AopUtils.isAopProxy(introduction.getSpouse()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSerializableDelegatingIntroductionInterceptorSerializable() throws Exception {
|
||||
SerializablePerson serializableTarget = new SerializablePerson();
|
||||
String name = "Tony";
|
||||
serializableTarget.setName("Tony");
|
||||
|
||||
ProxyFactory factory = new ProxyFactory(serializableTarget);
|
||||
factory.addInterface(Person.class);
|
||||
long time = 1000;
|
||||
TimeStamped ts = new SerializableTimeStamped(time);
|
||||
|
||||
factory.addAdvisor(new DefaultIntroductionAdvisor(new DelegatingIntroductionInterceptor(ts)));
|
||||
factory.addAdvice(new SerializableNopInterceptor());
|
||||
|
||||
Person p = (Person) factory.getProxy();
|
||||
|
||||
assertEquals(name, p.getName());
|
||||
assertEquals(time, ((TimeStamped) p).getTimeStamp());
|
||||
|
||||
Person p1 = (Person) SerializationTestUtils.serializeAndDeserialize(p);
|
||||
assertEquals(name, p1.getName());
|
||||
assertEquals(time, ((TimeStamped) p1).getTimeStamp());
|
||||
}
|
||||
|
||||
// Test when target implements the interface: should get interceptor by preference.
|
||||
@Test
|
||||
public void testIntroductionMasksTargetImplementation() throws Exception {
|
||||
final long t = 1001L;
|
||||
@SuppressWarnings("serial")
|
||||
class TestII extends DelegatingIntroductionInterceptor implements TimeStamped {
|
||||
public long getTimeStamp() {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
DelegatingIntroductionInterceptor ii = new TestII();
|
||||
|
||||
// != t
|
||||
TestBean target = new TargetClass(t + 1);
|
||||
|
||||
ProxyFactory pf = new ProxyFactory(target);
|
||||
pf.addAdvisor(0, new DefaultIntroductionAdvisor(ii));
|
||||
|
||||
TimeStamped ts = (TimeStamped) pf.getProxy();
|
||||
// From introduction interceptor, not target
|
||||
assertTrue(ts.getTimeStamp() == t);
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private static class SerializableTimeStamped implements TimeStamped, Serializable {
|
||||
|
||||
private final long ts;
|
||||
|
||||
public SerializableTimeStamped(long ts) {
|
||||
this.ts = ts;
|
||||
}
|
||||
|
||||
public long getTimeStamp() {
|
||||
return ts;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class TargetClass extends TestBean implements TimeStamped {
|
||||
|
||||
long t;
|
||||
|
||||
public TargetClass(long t) {
|
||||
this.t = t;
|
||||
}
|
||||
|
||||
public long getTimeStamp() {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public interface ITester {
|
||||
|
||||
void foo() throws Exception;
|
||||
}
|
||||
|
||||
|
||||
private static interface SubTimeStamped extends TimeStamped {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.support;
|
||||
|
||||
/**
|
||||
* @author Dmitriy Kopylenko
|
||||
*/
|
||||
public final class JdkRegexpMethodPointcutTests extends AbstractRegexpMethodPointcutTests {
|
||||
|
||||
protected AbstractRegexpMethodPointcut getRegexpMethodPointcut() {
|
||||
return new JdkRegexpMethodPointcut();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.support;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.aop.MethodMatcher;
|
||||
|
||||
import test.beans.IOther;
|
||||
import test.beans.ITestBean;
|
||||
import test.beans.TestBean;
|
||||
import test.util.SerializationTestUtils;
|
||||
|
||||
/**
|
||||
* @author Juergen Hoeller
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public final class MethodMatchersTests {
|
||||
|
||||
private final Method EXCEPTION_GETMESSAGE;
|
||||
|
||||
private final Method ITESTBEAN_SETAGE;
|
||||
|
||||
private final Method ITESTBEAN_GETAGE;
|
||||
|
||||
private final Method IOTHER_ABSQUATULATE;
|
||||
|
||||
public MethodMatchersTests() throws Exception {
|
||||
EXCEPTION_GETMESSAGE = Exception.class.getMethod("getMessage", (Class[]) null);
|
||||
ITESTBEAN_GETAGE = ITestBean.class.getMethod("getAge", (Class[]) null);
|
||||
ITESTBEAN_SETAGE = ITestBean.class.getMethod("setAge", new Class[] { int.class });
|
||||
IOTHER_ABSQUATULATE = IOther.class.getMethod("absquatulate", (Class[]) null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultMatchesAll() throws Exception {
|
||||
MethodMatcher defaultMm = MethodMatcher.TRUE;
|
||||
assertTrue(defaultMm.matches(EXCEPTION_GETMESSAGE, Exception.class));
|
||||
assertTrue(defaultMm.matches(ITESTBEAN_SETAGE, TestBean.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMethodMatcherTrueSerializable() throws Exception {
|
||||
assertSame(SerializationTestUtils.serializeAndDeserialize(MethodMatcher.TRUE), MethodMatcher.TRUE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingle() throws Exception {
|
||||
MethodMatcher defaultMm = MethodMatcher.TRUE;
|
||||
assertTrue(defaultMm.matches(EXCEPTION_GETMESSAGE, Exception.class));
|
||||
assertTrue(defaultMm.matches(ITESTBEAN_SETAGE, TestBean.class));
|
||||
defaultMm = MethodMatchers.intersection(defaultMm, new StartsWithMatcher("get"));
|
||||
|
||||
assertTrue(defaultMm.matches(EXCEPTION_GETMESSAGE, Exception.class));
|
||||
assertFalse(defaultMm.matches(ITESTBEAN_SETAGE, TestBean.class));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testDynamicAndStaticMethodMatcherIntersection() throws Exception {
|
||||
MethodMatcher mm1 = MethodMatcher.TRUE;
|
||||
MethodMatcher mm2 = new TestDynamicMethodMatcherWhichMatches();
|
||||
MethodMatcher intersection = MethodMatchers.intersection(mm1, mm2);
|
||||
assertTrue("Intersection is a dynamic matcher", intersection.isRuntime());
|
||||
assertTrue("2Matched setAge method", intersection.matches(ITESTBEAN_SETAGE, TestBean.class));
|
||||
assertTrue("3Matched setAge method", intersection.matches(ITESTBEAN_SETAGE, TestBean.class, new Object[] { new Integer(5) }));
|
||||
// Knock out dynamic part
|
||||
intersection = MethodMatchers.intersection(intersection, new TestDynamicMethodMatcherWhichDoesNotMatch());
|
||||
assertTrue("Intersection is a dynamic matcher", intersection.isRuntime());
|
||||
assertTrue("2Matched setAge method", intersection.matches(ITESTBEAN_SETAGE, TestBean.class));
|
||||
assertFalse("3 - not Matched setAge method", intersection.matches(ITESTBEAN_SETAGE, TestBean.class, new Object[] { new Integer(5) }));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStaticMethodMatcherUnion() throws Exception {
|
||||
MethodMatcher getterMatcher = new StartsWithMatcher("get");
|
||||
MethodMatcher setterMatcher = new StartsWithMatcher("set");
|
||||
MethodMatcher union = MethodMatchers.union(getterMatcher, setterMatcher);
|
||||
|
||||
assertFalse("Union is a static matcher", union.isRuntime());
|
||||
assertTrue("Matched setAge method", union.matches(ITESTBEAN_SETAGE, TestBean.class));
|
||||
assertTrue("Matched getAge method", union.matches(ITESTBEAN_GETAGE, TestBean.class));
|
||||
assertFalse("Didn't matched absquatulate method", union.matches(IOTHER_ABSQUATULATE, TestBean.class));
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static class StartsWithMatcher extends StaticMethodMatcher {
|
||||
private String prefix;
|
||||
public StartsWithMatcher(String s) {
|
||||
this.prefix = s;
|
||||
}
|
||||
public boolean matches(Method m, Class<?> targetClass) {
|
||||
return m.getName().startsWith(prefix);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class TestDynamicMethodMatcherWhichMatches extends DynamicMethodMatcher {
|
||||
public boolean matches(Method m, Class<?> targetClass, Object[] args) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private static class TestDynamicMethodMatcherWhichDoesNotMatch extends DynamicMethodMatcher {
|
||||
public boolean matches(Method m, Class<?> targetClass, Object[] args) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.support;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.aop.framework.Advised;
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
|
||||
import test.aop.NopInterceptor;
|
||||
import test.aop.SerializableNopInterceptor;
|
||||
import test.beans.Person;
|
||||
import test.beans.SerializablePerson;
|
||||
import test.util.SerializationTestUtils;
|
||||
|
||||
/**
|
||||
* @author Rod Johnson
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public final class NameMatchMethodPointcutTests {
|
||||
|
||||
protected NameMatchMethodPointcut pc;
|
||||
|
||||
protected Person proxied;
|
||||
|
||||
protected SerializableNopInterceptor nop;
|
||||
|
||||
/**
|
||||
* Create an empty pointcut, populating instance variables.
|
||||
*/
|
||||
@Before
|
||||
public void setUp() {
|
||||
ProxyFactory pf = new ProxyFactory(new SerializablePerson());
|
||||
nop = new SerializableNopInterceptor();
|
||||
pc = new NameMatchMethodPointcut();
|
||||
pf.addAdvisor(new DefaultPointcutAdvisor(pc, nop));
|
||||
proxied = (Person) pf.getProxy();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchingOnly() {
|
||||
// Can't do exact matching through isMatch
|
||||
assertTrue(pc.isMatch("echo", "ech*"));
|
||||
assertTrue(pc.isMatch("setName", "setN*"));
|
||||
assertTrue(pc.isMatch("setName", "set*"));
|
||||
assertFalse(pc.isMatch("getName", "set*"));
|
||||
assertFalse(pc.isMatch("setName", "set"));
|
||||
assertTrue(pc.isMatch("testing", "*ing"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmpty() throws Throwable {
|
||||
assertEquals(0, nop.getCount());
|
||||
proxied.getName();
|
||||
proxied.setName("");
|
||||
proxied.echo(null);
|
||||
assertEquals(0, nop.getCount());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testMatchOneMethod() throws Throwable {
|
||||
pc.addMethodName("echo");
|
||||
pc.addMethodName("set*");
|
||||
assertEquals(0, nop.getCount());
|
||||
proxied.getName();
|
||||
proxied.getName();
|
||||
assertEquals(0, nop.getCount());
|
||||
proxied.echo(null);
|
||||
assertEquals(1, nop.getCount());
|
||||
|
||||
proxied.setName("");
|
||||
assertEquals(2, nop.getCount());
|
||||
proxied.setAge(25);
|
||||
assertEquals(25, proxied.getAge());
|
||||
assertEquals(3, nop.getCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSets() throws Throwable {
|
||||
pc.setMappedNames(new String[] { "set*", "echo" });
|
||||
assertEquals(0, nop.getCount());
|
||||
proxied.getName();
|
||||
proxied.setName("");
|
||||
assertEquals(1, nop.getCount());
|
||||
proxied.echo(null);
|
||||
assertEquals(2, nop.getCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSerializable() throws Throwable {
|
||||
testSets();
|
||||
// Count is now 2
|
||||
Person p2 = (Person) SerializationTestUtils.serializeAndDeserialize(proxied);
|
||||
NopInterceptor nop2 = (NopInterceptor) ((Advised) p2).getAdvisors()[0].getAdvice();
|
||||
p2.getName();
|
||||
assertEquals(2, nop2.getCount());
|
||||
p2.echo(null);
|
||||
assertEquals(3, nop2.getCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEqualsAndHashCode() throws Exception {
|
||||
NameMatchMethodPointcut pc1 = new NameMatchMethodPointcut();
|
||||
NameMatchMethodPointcut pc2 = new NameMatchMethodPointcut();
|
||||
|
||||
String foo = "foo";
|
||||
|
||||
assertEquals(pc1, pc2);
|
||||
assertEquals(pc1.hashCode(), pc2.hashCode());
|
||||
|
||||
pc1.setMappedName(foo);
|
||||
assertFalse(pc1.equals(pc2));
|
||||
assertTrue(pc1.hashCode() != pc2.hashCode());
|
||||
|
||||
pc2.setMappedName(foo);
|
||||
assertEquals(pc1, pc2);
|
||||
assertEquals(pc1.hashCode(), pc2.hashCode());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,244 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.support;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.aop.ClassFilter;
|
||||
import org.springframework.aop.Pointcut;
|
||||
|
||||
import test.beans.TestBean;
|
||||
|
||||
/**
|
||||
* @author Rod Johnson
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public final class PointcutsTests {
|
||||
|
||||
public static Method TEST_BEAN_SET_AGE;
|
||||
public static Method TEST_BEAN_GET_AGE;
|
||||
public static Method TEST_BEAN_GET_NAME;
|
||||
public static Method TEST_BEAN_ABSQUATULATE;
|
||||
|
||||
static {
|
||||
try {
|
||||
TEST_BEAN_SET_AGE = TestBean.class.getMethod("setAge", new Class[] { int.class });
|
||||
TEST_BEAN_GET_AGE = TestBean.class.getMethod("getAge", (Class[]) null);
|
||||
TEST_BEAN_GET_NAME = TestBean.class.getMethod("getName", (Class[]) null);
|
||||
TEST_BEAN_ABSQUATULATE = TestBean.class.getMethod("absquatulate", (Class[]) null);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new RuntimeException("Shouldn't happen: error in test suite");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Matches only TestBean class, not subclasses
|
||||
*/
|
||||
public static Pointcut allTestBeanMethodsPointcut = new StaticMethodMatcherPointcut() {
|
||||
public ClassFilter getClassFilter() {
|
||||
return new ClassFilter() {
|
||||
public boolean matches(Class<?> clazz) {
|
||||
return clazz.equals(TestBean.class);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public boolean matches(Method m, Class<?> targetClass) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
public static Pointcut allClassSetterPointcut = Pointcuts.SETTERS;
|
||||
|
||||
// Subclass used for matching
|
||||
public static class MyTestBean extends TestBean {
|
||||
}
|
||||
|
||||
public static Pointcut myTestBeanSetterPointcut = new StaticMethodMatcherPointcut() {
|
||||
public ClassFilter getClassFilter() {
|
||||
return new RootClassFilter(MyTestBean.class);
|
||||
}
|
||||
|
||||
public boolean matches(Method m, Class<?> targetClass) {
|
||||
return m.getName().startsWith("set");
|
||||
}
|
||||
};
|
||||
|
||||
// Will match MyTestBeanSubclass
|
||||
public static Pointcut myTestBeanGetterPointcut = new StaticMethodMatcherPointcut() {
|
||||
public ClassFilter getClassFilter() {
|
||||
return new RootClassFilter(MyTestBean.class);
|
||||
}
|
||||
|
||||
public boolean matches(Method m, Class<?> targetClass) {
|
||||
return m.getName().startsWith("get");
|
||||
}
|
||||
};
|
||||
|
||||
// Still more specific class
|
||||
public static class MyTestBeanSubclass extends MyTestBean {
|
||||
}
|
||||
|
||||
public static Pointcut myTestBeanSubclassGetterPointcut = new StaticMethodMatcherPointcut() {
|
||||
public ClassFilter getClassFilter() {
|
||||
return new RootClassFilter(MyTestBeanSubclass.class);
|
||||
}
|
||||
|
||||
public boolean matches(Method m, Class<?> targetClass) {
|
||||
return m.getName().startsWith("get");
|
||||
}
|
||||
};
|
||||
|
||||
public static Pointcut allClassGetterPointcut = Pointcuts.GETTERS;
|
||||
|
||||
public static Pointcut allClassGetAgePointcut = new NameMatchMethodPointcut().addMethodName("getAge");
|
||||
|
||||
public static Pointcut allClassGetNamePointcut = new NameMatchMethodPointcut().addMethodName("getName");
|
||||
|
||||
|
||||
@Test
|
||||
public void testTrue() {
|
||||
assertTrue(Pointcuts.matches(Pointcut.TRUE, TEST_BEAN_SET_AGE, TestBean.class, new Object[] { new Integer(6)}));
|
||||
assertTrue(Pointcuts.matches(Pointcut.TRUE, TEST_BEAN_GET_AGE, TestBean.class, null));
|
||||
assertTrue(Pointcuts.matches(Pointcut.TRUE, TEST_BEAN_ABSQUATULATE, TestBean.class, null));
|
||||
assertTrue(Pointcuts.matches(Pointcut.TRUE, TEST_BEAN_SET_AGE, TestBean.class, new Object[] { new Integer(6)}));
|
||||
assertTrue(Pointcuts.matches(Pointcut.TRUE, TEST_BEAN_GET_AGE, TestBean.class, null));
|
||||
assertTrue(Pointcuts.matches(Pointcut.TRUE, TEST_BEAN_ABSQUATULATE, TestBean.class, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatches() {
|
||||
assertTrue(Pointcuts.matches(allClassSetterPointcut, TEST_BEAN_SET_AGE, TestBean.class, new Object[] { new Integer(6)}));
|
||||
assertFalse(Pointcuts.matches(allClassSetterPointcut, TEST_BEAN_GET_AGE, TestBean.class, null));
|
||||
assertFalse(Pointcuts.matches(allClassSetterPointcut, TEST_BEAN_ABSQUATULATE, TestBean.class, null));
|
||||
assertFalse(Pointcuts.matches(allClassGetterPointcut, TEST_BEAN_SET_AGE, TestBean.class, new Object[] { new Integer(6)}));
|
||||
assertTrue(Pointcuts.matches(allClassGetterPointcut, TEST_BEAN_GET_AGE, TestBean.class, null));
|
||||
assertFalse(Pointcuts.matches(allClassGetterPointcut, TEST_BEAN_ABSQUATULATE, TestBean.class, null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Should match all setters and getters on any class
|
||||
*/
|
||||
@Test
|
||||
public void testUnionOfSettersAndGetters() {
|
||||
Pointcut union = Pointcuts.union(allClassGetterPointcut, allClassSetterPointcut);
|
||||
assertTrue(Pointcuts.matches(union, TEST_BEAN_SET_AGE, TestBean.class, new Object[] { new Integer(6)}));
|
||||
assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_AGE, TestBean.class, null));
|
||||
assertFalse(Pointcuts.matches(union, TEST_BEAN_ABSQUATULATE, TestBean.class, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnionOfSpecificGetters() {
|
||||
Pointcut union = Pointcuts.union(allClassGetAgePointcut, allClassGetNamePointcut);
|
||||
assertFalse(Pointcuts.matches(union, TEST_BEAN_SET_AGE, TestBean.class, new Object[] { new Integer(6)}));
|
||||
assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_AGE, TestBean.class, null));
|
||||
assertFalse(Pointcuts.matches(allClassGetAgePointcut, TEST_BEAN_GET_NAME, TestBean.class, null));
|
||||
assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_NAME, TestBean.class, null));
|
||||
assertFalse(Pointcuts.matches(union, TEST_BEAN_ABSQUATULATE, TestBean.class, null));
|
||||
|
||||
// Union with all setters
|
||||
union = Pointcuts.union(union, allClassSetterPointcut);
|
||||
assertTrue(Pointcuts.matches(union, TEST_BEAN_SET_AGE, TestBean.class, new Object[] { new Integer(6)}));
|
||||
assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_AGE, TestBean.class, null));
|
||||
assertFalse(Pointcuts.matches(allClassGetAgePointcut, TEST_BEAN_GET_NAME, TestBean.class, null));
|
||||
assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_NAME, TestBean.class, null));
|
||||
assertFalse(Pointcuts.matches(union, TEST_BEAN_ABSQUATULATE, TestBean.class, null));
|
||||
|
||||
assertTrue(Pointcuts.matches(union, TEST_BEAN_SET_AGE, TestBean.class, new Object[] { new Integer(6)}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests vertical composition. First pointcut matches all setters.
|
||||
* Second one matches all getters in the MyTestBean class. TestBean getters shouldn't pass.
|
||||
*/
|
||||
@Test
|
||||
public void testUnionOfAllSettersAndSubclassSetters() {
|
||||
assertFalse(Pointcuts.matches(myTestBeanSetterPointcut, TEST_BEAN_SET_AGE, TestBean.class, new Object[] { new Integer(6)}));
|
||||
assertTrue(Pointcuts.matches(myTestBeanSetterPointcut, TEST_BEAN_SET_AGE, MyTestBean.class, new Object[] { new Integer(6)}));
|
||||
assertFalse(Pointcuts.matches(myTestBeanSetterPointcut, TEST_BEAN_GET_AGE, TestBean.class, null));
|
||||
|
||||
Pointcut union = Pointcuts.union(myTestBeanSetterPointcut, allClassGetterPointcut);
|
||||
assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_AGE, TestBean.class, null));
|
||||
assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_AGE, MyTestBean.class, null));
|
||||
// Still doesn't match superclass setter
|
||||
assertTrue(Pointcuts.matches(union, TEST_BEAN_SET_AGE, MyTestBean.class, new Object[] { new Integer(6)}));
|
||||
assertFalse(Pointcuts.matches(union, TEST_BEAN_SET_AGE, TestBean.class, new Object[] { new Integer(6)}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Intersection should be MyTestBean getAge() only:
|
||||
* it's the union of allClassGetAge and subclass getters
|
||||
*/
|
||||
@Test
|
||||
public void testIntersectionOfSpecificGettersAndSubclassGetters() {
|
||||
assertTrue(Pointcuts.matches(allClassGetAgePointcut, TEST_BEAN_GET_AGE, TestBean.class, null));
|
||||
assertTrue(Pointcuts.matches(allClassGetAgePointcut, TEST_BEAN_GET_AGE, MyTestBean.class, null));
|
||||
assertFalse(Pointcuts.matches(myTestBeanGetterPointcut, TEST_BEAN_GET_NAME, TestBean.class, null));
|
||||
assertFalse(Pointcuts.matches(myTestBeanGetterPointcut, TEST_BEAN_GET_AGE, TestBean.class, null));
|
||||
assertTrue(Pointcuts.matches(myTestBeanGetterPointcut, TEST_BEAN_GET_NAME, MyTestBean.class, null));
|
||||
assertTrue(Pointcuts.matches(myTestBeanGetterPointcut, TEST_BEAN_GET_AGE, MyTestBean.class, null));
|
||||
|
||||
Pointcut intersection = Pointcuts.intersection(allClassGetAgePointcut, myTestBeanGetterPointcut);
|
||||
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_NAME, TestBean.class, null));
|
||||
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_AGE, TestBean.class, null));
|
||||
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_NAME, MyTestBean.class, null));
|
||||
assertTrue(Pointcuts.matches(intersection, TEST_BEAN_GET_AGE, MyTestBean.class, null));
|
||||
// Matches subclass of MyTestBean
|
||||
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_NAME, MyTestBeanSubclass.class, null));
|
||||
assertTrue(Pointcuts.matches(intersection, TEST_BEAN_GET_AGE, MyTestBeanSubclass.class, null));
|
||||
|
||||
// Now intersection with MyTestBeanSubclass getters should eliminate MyTestBean target
|
||||
intersection = Pointcuts.intersection(intersection, myTestBeanSubclassGetterPointcut);
|
||||
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_NAME, TestBean.class, null));
|
||||
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_AGE, TestBean.class, null));
|
||||
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_NAME, MyTestBean.class, null));
|
||||
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_AGE, MyTestBean.class, null));
|
||||
// Still matches subclass of MyTestBean
|
||||
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_NAME, MyTestBeanSubclass.class, null));
|
||||
assertTrue(Pointcuts.matches(intersection, TEST_BEAN_GET_AGE, MyTestBeanSubclass.class, null));
|
||||
|
||||
// Now union with all TestBean methods
|
||||
Pointcut union = Pointcuts.union(intersection, allTestBeanMethodsPointcut);
|
||||
assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_NAME, TestBean.class, null));
|
||||
assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_AGE, TestBean.class, null));
|
||||
assertFalse(Pointcuts.matches(union, TEST_BEAN_GET_NAME, MyTestBean.class, null));
|
||||
assertFalse(Pointcuts.matches(union, TEST_BEAN_GET_AGE, MyTestBean.class, null));
|
||||
// Still matches subclass of MyTestBean
|
||||
assertFalse(Pointcuts.matches(union, TEST_BEAN_GET_NAME, MyTestBeanSubclass.class, null));
|
||||
assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_AGE, MyTestBeanSubclass.class, null));
|
||||
|
||||
assertTrue(Pointcuts.matches(union, TEST_BEAN_ABSQUATULATE, TestBean.class, null));
|
||||
assertFalse(Pointcuts.matches(union, TEST_BEAN_ABSQUATULATE, MyTestBean.class, null));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The intersection of these two pointcuts leaves nothing.
|
||||
*/
|
||||
@Test
|
||||
public void testSimpleIntersection() {
|
||||
Pointcut intersection = Pointcuts.intersection(allClassGetterPointcut, allClassSetterPointcut);
|
||||
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_SET_AGE, TestBean.class, new Object[] { new Integer(6)}));
|
||||
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_AGE, TestBean.class, null));
|
||||
assertFalse(Pointcuts.matches(intersection, TEST_BEAN_ABSQUATULATE, TestBean.class, null));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
|
||||
|
||||
<beans>
|
||||
|
||||
<!-- Simple target -->
|
||||
<bean id="test" class="test.beans.TestBean">
|
||||
<property name="name"><value>custom</value></property>
|
||||
<property name="age"><value>666</value></property>
|
||||
</bean>
|
||||
|
||||
<bean id="nopInterceptor" class="test.aop.SerializableNopInterceptor"/>
|
||||
|
||||
<bean id="settersAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
|
||||
<property name="advice"><ref local="nopInterceptor"/></property>
|
||||
<property name="pattern">
|
||||
<value>
|
||||
.*set.*
|
||||
</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="settersAdvised" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||
<property name="proxyInterfaces"><value>test.beans.ITestBean</value></property>
|
||||
<property name="target"><ref local="test"/></property>
|
||||
<property name="interceptorNames"><value>settersAdvisor</value></property>
|
||||
</bean>
|
||||
|
||||
<bean id="serializableSettersAdvised" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||
<property name="proxyInterfaces"><value>test.beans.Person</value></property>
|
||||
<property name="target">
|
||||
<bean class="test.beans.SerializablePerson">
|
||||
<property name="name"><value>serializableSettersAdvised</value></property>
|
||||
</bean>
|
||||
</property>
|
||||
<property name="interceptorNames"><value>settersAdvisor</value></property>
|
||||
</bean>
|
||||
|
||||
<!-- Illustrates use of multiple patterns -->
|
||||
<bean id="settersAndAbsquatulateAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
|
||||
<property name="advice"><ref local="nopInterceptor"/></property>
|
||||
<property name="patterns">
|
||||
<list>
|
||||
<value>.*get.*</value>
|
||||
<value>.*absquatulate</value>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="settersAndAbsquatulateAdvised" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||
<property name="proxyInterfaces"><value>test.beans.ITestBean</value></property>
|
||||
<!-- Force CGLIB so we can cast to TestBean -->
|
||||
<property name="proxyTargetClass"><value>true</value></property>
|
||||
<property name="target"><ref local="test"/></property>
|
||||
<property name="interceptorNames"><value>settersAndAbsquatulateAdvisor</value></property>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.support;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static test.util.TestResourceUtils.qualifiedResource;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.aop.framework.Advised;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.xml.XmlBeanFactory;
|
||||
import org.springframework.core.io.Resource;
|
||||
|
||||
import test.aop.NopInterceptor;
|
||||
import test.aop.SerializableNopInterceptor;
|
||||
import test.beans.ITestBean;
|
||||
import test.beans.Person;
|
||||
import test.beans.TestBean;
|
||||
import test.util.SerializationTestUtils;
|
||||
|
||||
/**
|
||||
* @author Rod Johnson
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public final class RegexpMethodPointcutAdvisorIntegrationTests {
|
||||
|
||||
private static final Resource CONTEXT =
|
||||
qualifiedResource(RegexpMethodPointcutAdvisorIntegrationTests.class, "context.xml");
|
||||
|
||||
@Test
|
||||
public void testSinglePattern() throws Throwable {
|
||||
BeanFactory bf = new XmlBeanFactory(CONTEXT);
|
||||
ITestBean advised = (ITestBean) bf.getBean("settersAdvised");
|
||||
// Interceptor behind regexp advisor
|
||||
NopInterceptor nop = (NopInterceptor) bf.getBean("nopInterceptor");
|
||||
assertEquals(0, nop.getCount());
|
||||
|
||||
int newAge = 12;
|
||||
// Not advised
|
||||
advised.exceptional(null);
|
||||
assertEquals(0, nop.getCount());
|
||||
advised.setAge(newAge);
|
||||
assertEquals(newAge, advised.getAge());
|
||||
// Only setter fired
|
||||
assertEquals(1, nop.getCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultiplePatterns() throws Throwable {
|
||||
BeanFactory bf = new XmlBeanFactory(CONTEXT);
|
||||
// This is a CGLIB proxy, so we can proxy it to the target class
|
||||
TestBean advised = (TestBean) bf.getBean("settersAndAbsquatulateAdvised");
|
||||
// Interceptor behind regexp advisor
|
||||
NopInterceptor nop = (NopInterceptor) bf.getBean("nopInterceptor");
|
||||
assertEquals(0, nop.getCount());
|
||||
|
||||
int newAge = 12;
|
||||
// Not advised
|
||||
advised.exceptional(null);
|
||||
assertEquals(0, nop.getCount());
|
||||
|
||||
// This is proxied
|
||||
advised.absquatulate();
|
||||
assertEquals(1, nop.getCount());
|
||||
advised.setAge(newAge);
|
||||
assertEquals(newAge, advised.getAge());
|
||||
// Only setter fired
|
||||
assertEquals(2, nop.getCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSerialization() throws Throwable {
|
||||
BeanFactory bf = new XmlBeanFactory(CONTEXT);
|
||||
// This is a CGLIB proxy, so we can proxy it to the target class
|
||||
Person p = (Person) bf.getBean("serializableSettersAdvised");
|
||||
// Interceptor behind regexp advisor
|
||||
NopInterceptor nop = (NopInterceptor) bf.getBean("nopInterceptor");
|
||||
assertEquals(0, nop.getCount());
|
||||
|
||||
int newAge = 12;
|
||||
// Not advised
|
||||
assertEquals(0, p.getAge());
|
||||
assertEquals(0, nop.getCount());
|
||||
|
||||
// This is proxied
|
||||
p.setAge(newAge);
|
||||
assertEquals(1, nop.getCount());
|
||||
p.setAge(newAge);
|
||||
assertEquals(newAge, p.getAge());
|
||||
// Only setter fired
|
||||
assertEquals(2, nop.getCount());
|
||||
|
||||
// Serialize and continue...
|
||||
p = (Person) SerializationTestUtils.serializeAndDeserialize(p);
|
||||
assertEquals(newAge, p.getAge());
|
||||
// Remembers count, but we need to get a new reference to nop...
|
||||
nop = (SerializableNopInterceptor) ((Advised) p).getAdvisors()[0].getAdvice();
|
||||
assertEquals(2, nop.getCount());
|
||||
assertEquals("serializableSettersAdvised", p.getName());
|
||||
p.setAge(newAge + 1);
|
||||
assertEquals(3, nop.getCount());
|
||||
assertEquals(newAge + 1, p.getAge());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
|
||||
|
||||
<beans>
|
||||
|
||||
<bean id="testBeanTarget" class="test.beans.TestBean" scope="prototype"/>
|
||||
|
||||
<bean id="targetSource" class="org.springframework.aop.target.CommonsPoolTargetSource">
|
||||
<property name="targetBeanName" value="testBeanTarget"/>
|
||||
</bean>
|
||||
|
||||
<bean id="testBean" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||
<property name="targetSource" ref="targetSource"/>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.target;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static test.util.TestResourceUtils.qualifiedResource;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
|
||||
import org.springframework.core.io.Resource;
|
||||
|
||||
import test.beans.ITestBean;
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
* @author Chris Beams
|
||||
* @since 2.0
|
||||
*/
|
||||
public final class CommonsPoolTargetSourceProxyTests {
|
||||
|
||||
private static final Resource CONTEXT =
|
||||
qualifiedResource(CommonsPoolTargetSourceProxyTests.class, "context.xml");
|
||||
|
||||
@Test
|
||||
public void testProxy() throws Exception {
|
||||
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
||||
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
|
||||
reader.loadBeanDefinitions(CONTEXT);
|
||||
beanFactory.preInstantiateSingletons();
|
||||
ITestBean bean = (ITestBean)beanFactory.getBean("testBean");
|
||||
assertTrue(AopUtils.isAopProxy(bean));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
|
||||
|
||||
<beans>
|
||||
|
||||
<!-- Simple target -->
|
||||
<bean id="target1" class="test.beans.SideEffectBean">
|
||||
<property name="count"><value>10</value></property>
|
||||
</bean>
|
||||
|
||||
<bean id="target2" class="test.beans.SideEffectBean" scope="singleton">
|
||||
<property name="count"><value>20</value></property>
|
||||
</bean>
|
||||
|
||||
<!--
|
||||
Hot swappable target source. Note the use of Type 3 IoC.
|
||||
-->
|
||||
<bean id="swapper" class="org.springframework.aop.target.HotSwappableTargetSource">
|
||||
<constructor-arg><ref local="target1"/></constructor-arg>
|
||||
</bean>
|
||||
|
||||
<bean id="swappable" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||
<property name="targetSource"><ref local="swapper"/></property>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
|
||||
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.target;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static test.util.TestResourceUtils.qualifiedResource;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.aop.framework.Advised;
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.aop.support.DefaultPointcutAdvisor;
|
||||
import org.springframework.beans.factory.xml.XmlBeanFactory;
|
||||
import org.springframework.core.io.Resource;
|
||||
|
||||
import test.aop.SerializableNopInterceptor;
|
||||
import test.beans.Person;
|
||||
import test.beans.SerializablePerson;
|
||||
import test.beans.SideEffectBean;
|
||||
import test.util.SerializationTestUtils;
|
||||
|
||||
|
||||
/**
|
||||
* @author Rod Johnson
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public final class HotSwappableTargetSourceTests {
|
||||
|
||||
private static final Resource CONTEXT = qualifiedResource(HotSwappableTargetSourceTests.class, "context.xml");
|
||||
|
||||
/** Initial count value set in bean factory XML */
|
||||
private static final int INITIAL_COUNT = 10;
|
||||
|
||||
private XmlBeanFactory beanFactory;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
this.beanFactory = new XmlBeanFactory(CONTEXT);
|
||||
}
|
||||
|
||||
/**
|
||||
* We must simulate container shutdown, which should clear threads.
|
||||
*/
|
||||
@After
|
||||
public void tearDown() {
|
||||
// Will call pool.close()
|
||||
this.beanFactory.destroySingletons();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check it works like a normal invoker
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testBasicFunctionality() {
|
||||
SideEffectBean proxied = (SideEffectBean) beanFactory.getBean("swappable");
|
||||
assertEquals(INITIAL_COUNT, proxied.getCount() );
|
||||
proxied.doWork();
|
||||
assertEquals(INITIAL_COUNT + 1, proxied.getCount() );
|
||||
|
||||
proxied = (SideEffectBean) beanFactory.getBean("swappable");
|
||||
proxied.doWork();
|
||||
assertEquals(INITIAL_COUNT + 2, proxied.getCount() );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidSwaps() {
|
||||
SideEffectBean target1 = (SideEffectBean) beanFactory.getBean("target1");
|
||||
SideEffectBean target2 = (SideEffectBean) beanFactory.getBean("target2");
|
||||
|
||||
SideEffectBean proxied = (SideEffectBean) beanFactory.getBean("swappable");
|
||||
assertEquals(target1.getCount(), proxied.getCount() );
|
||||
proxied.doWork();
|
||||
assertEquals(INITIAL_COUNT + 1, proxied.getCount() );
|
||||
|
||||
HotSwappableTargetSource swapper = (HotSwappableTargetSource) beanFactory.getBean("swapper");
|
||||
Object old = swapper.swap(target2);
|
||||
assertEquals("Correct old target was returned", target1, old);
|
||||
|
||||
// TODO should be able to make this assertion: need to fix target handling
|
||||
// in AdvisedSupport
|
||||
//assertEquals(target2, ((Advised) proxied).getTarget());
|
||||
|
||||
assertEquals(20, proxied.getCount());
|
||||
proxied.doWork();
|
||||
assertEquals(21, target2.getCount());
|
||||
|
||||
// Swap it back
|
||||
swapper.swap(target1);
|
||||
assertEquals(target1.getCount(), proxied.getCount());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param invalid
|
||||
* @return the message
|
||||
*/
|
||||
private IllegalArgumentException testRejectsSwapToInvalidValue(Object invalid) {
|
||||
HotSwappableTargetSource swapper = (HotSwappableTargetSource) beanFactory.getBean("swapper");
|
||||
IllegalArgumentException aopex = null;
|
||||
try {
|
||||
swapper.swap(invalid);
|
||||
fail("Shouldn't be able to swap to invalid value [" + invalid + "]");
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
// Ok
|
||||
aopex = ex;
|
||||
}
|
||||
|
||||
// It shouldn't be corrupted, it should still work
|
||||
testBasicFunctionality();
|
||||
return aopex;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRejectsSwapToNull() {
|
||||
IllegalArgumentException ex = testRejectsSwapToInvalidValue(null);
|
||||
assertTrue(ex.getMessage().indexOf("null") != -1);
|
||||
}
|
||||
|
||||
// TODO test reject swap to wrong interface or class?
|
||||
// how to decide what's valid?
|
||||
|
||||
|
||||
@Test
|
||||
public void testSerialization() throws Exception {
|
||||
SerializablePerson sp1 = new SerializablePerson();
|
||||
sp1.setName("Tony");
|
||||
SerializablePerson sp2 = new SerializablePerson();
|
||||
sp1.setName("Gordon");
|
||||
|
||||
HotSwappableTargetSource hts = new HotSwappableTargetSource(sp1);
|
||||
ProxyFactory pf = new ProxyFactory();
|
||||
pf.addInterface(Person.class);
|
||||
pf.setTargetSource(hts);
|
||||
pf.addAdvisor(new DefaultPointcutAdvisor(new SerializableNopInterceptor()));
|
||||
Person p = (Person) pf.getProxy();
|
||||
|
||||
assertEquals(sp1.getName(), p.getName());
|
||||
hts.swap(sp2);
|
||||
assertEquals(sp2.getName(), p.getName());
|
||||
|
||||
p = (Person) SerializationTestUtils.serializeAndDeserialize(p);
|
||||
// We need to get a reference to the client-side targetsource
|
||||
hts = (HotSwappableTargetSource) ((Advised) p).getTargetSource();
|
||||
assertEquals(sp2.getName(), p.getName());
|
||||
hts.swap(sp1);
|
||||
assertEquals(sp1.getName(), p.getName());
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.target;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.aop.TargetSource;
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
* @author Juergen Hoeller
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public final class LazyCreationTargetSourceTests {
|
||||
|
||||
@Test
|
||||
public void testCreateLazy() {
|
||||
TargetSource targetSource = new AbstractLazyCreationTargetSource() {
|
||||
protected Object createObject() {
|
||||
return new InitCountingBean();
|
||||
}
|
||||
public Class<?> getTargetClass() {
|
||||
return InitCountingBean.class;
|
||||
}
|
||||
};
|
||||
|
||||
InitCountingBean proxy = (InitCountingBean) ProxyFactory.getProxy(targetSource);
|
||||
assertEquals("Init count should be 0", 0, InitCountingBean.initCount);
|
||||
assertEquals("Target class incorrect", InitCountingBean.class, targetSource.getTargetClass());
|
||||
assertEquals("Init count should still be 0 after getTargetClass()", 0, InitCountingBean.initCount);
|
||||
|
||||
proxy.doSomething();
|
||||
assertEquals("Init count should now be 1", 1, InitCountingBean.initCount);
|
||||
|
||||
proxy.doSomething();
|
||||
assertEquals("Init count should still be 1", 1, InitCountingBean.initCount);
|
||||
}
|
||||
|
||||
|
||||
private static class InitCountingBean {
|
||||
|
||||
public static int initCount;
|
||||
|
||||
public InitCountingBean() {
|
||||
if (InitCountingBean.class.equals(getClass())) {
|
||||
// only increment when creating the actual target - not the proxy
|
||||
initCount++;
|
||||
}
|
||||
}
|
||||
|
||||
public void doSomething() {
|
||||
//no-op
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
|
||||
|
||||
<beans>
|
||||
|
||||
<bean id="target" class="test.beans.TestBean" lazy-init="true">
|
||||
<property name="age"><value>10</value></property>
|
||||
</bean>
|
||||
|
||||
<!--
|
||||
This will create a proxy that lazily fetches its target bean (with name "target").
|
||||
-->
|
||||
<bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||
<property name="targetSource">
|
||||
<bean class="org.springframework.aop.target.LazyInitTargetSourceTests$CustomLazyInitTargetSource">
|
||||
<property name="targetBeanName"><idref local="target"/></property>
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,47 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
|
||||
|
||||
<beans>
|
||||
|
||||
<bean id="target1" class="org.springframework.beans.factory.config.SetFactoryBean" lazy-init="true">
|
||||
<property name="sourceSet">
|
||||
<set>
|
||||
<value>10</value>
|
||||
</set>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!--
|
||||
This will create a proxy that lazily fetches its target bean (with name "target").
|
||||
-->
|
||||
<bean id="proxy1" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||
<property name="proxyInterfaces" value="java.util.Set"/>
|
||||
<property name="targetSource">
|
||||
<bean class="org.springframework.aop.target.LazyInitTargetSource">
|
||||
<property name="targetBeanName" value="target1"/>
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="target2" class="org.springframework.beans.factory.config.SetFactoryBean" lazy-init="true">
|
||||
<property name="sourceSet">
|
||||
<set>
|
||||
<value>20</value>
|
||||
</set>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!--
|
||||
This will create a proxy that lazily fetches its target bean (with name "target").
|
||||
-->
|
||||
<bean id="proxy2" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||
<property name="autodetectInterfaces" value="true"/>
|
||||
<property name="targetSource">
|
||||
<bean class="org.springframework.aop.target.LazyInitTargetSource">
|
||||
<property name="targetBeanName" value="target2"/>
|
||||
<property name="targetClass" value="java.util.Set"/>
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
|
||||
|
||||
<beans>
|
||||
|
||||
<bean id="target" class="test.beans.TestBean" lazy-init="true">
|
||||
<property name="age"><value>10</value></property>
|
||||
</bean>
|
||||
|
||||
<!--
|
||||
This will create a proxy that lazily fetches its target bean (with name "target").
|
||||
-->
|
||||
<bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||
<property name="targetSource">
|
||||
<bean class="org.springframework.aop.target.LazyInitTargetSource">
|
||||
<property name="targetBeanName"><idref local="target"/></property>
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.target;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static test.util.TestResourceUtils.qualifiedResource;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.xml.XmlBeanFactory;
|
||||
import org.springframework.core.io.Resource;
|
||||
|
||||
import test.beans.ITestBean;
|
||||
|
||||
/**
|
||||
* @author Juergen Hoeller
|
||||
* @author Rob Harrop
|
||||
* @author Chris Beams
|
||||
* @since 07.01.2005
|
||||
*/
|
||||
public final class LazyInitTargetSourceTests {
|
||||
|
||||
private static final Class<?> CLASS = LazyInitTargetSourceTests.class;
|
||||
|
||||
private static final Resource SINGLETON_CONTEXT = qualifiedResource(CLASS, "singleton.xml");
|
||||
private static final Resource CUSTOM_TARGET_CONTEXT = qualifiedResource(CLASS, "customTarget.xml");
|
||||
private static final Resource FACTORY_BEAN_CONTEXT = qualifiedResource(CLASS, "factoryBean.xml");
|
||||
|
||||
@Test
|
||||
public void testLazyInitSingletonTargetSource() {
|
||||
XmlBeanFactory bf = new XmlBeanFactory(SINGLETON_CONTEXT);
|
||||
bf.preInstantiateSingletons();
|
||||
|
||||
ITestBean tb = (ITestBean) bf.getBean("proxy");
|
||||
assertFalse(bf.containsSingleton("target"));
|
||||
assertEquals(10, tb.getAge());
|
||||
assertTrue(bf.containsSingleton("target"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCustomLazyInitSingletonTargetSource() {
|
||||
XmlBeanFactory bf = new XmlBeanFactory(CUSTOM_TARGET_CONTEXT);
|
||||
bf.preInstantiateSingletons();
|
||||
|
||||
ITestBean tb = (ITestBean) bf.getBean("proxy");
|
||||
assertFalse(bf.containsSingleton("target"));
|
||||
assertEquals("Rob Harrop", tb.getName());
|
||||
assertTrue(bf.containsSingleton("target"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLazyInitFactoryBeanTargetSource() {
|
||||
XmlBeanFactory bf = new XmlBeanFactory(FACTORY_BEAN_CONTEXT);
|
||||
bf.preInstantiateSingletons();
|
||||
|
||||
Set<?> set1 = (Set<?>) bf.getBean("proxy1");
|
||||
assertFalse(bf.containsSingleton("target1"));
|
||||
assertTrue(set1.contains("10"));
|
||||
assertTrue(bf.containsSingleton("target1"));
|
||||
|
||||
Set<?> set2 = (Set<?>) bf.getBean("proxy2");
|
||||
assertFalse(bf.containsSingleton("target2"));
|
||||
assertTrue(set2.contains("20"));
|
||||
assertTrue(bf.containsSingleton("target2"));
|
||||
}
|
||||
|
||||
|
||||
public static class CustomLazyInitTargetSource extends LazyInitTargetSource {
|
||||
|
||||
protected void postProcessTargetObject(Object targetObject) {
|
||||
((ITestBean) targetObject).setName("Rob Harrop");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.target;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.aop.TargetSource;
|
||||
import org.springframework.beans.MutablePropertyValues;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
|
||||
import test.beans.SerializablePerson;
|
||||
import test.beans.TestBean;
|
||||
import test.util.SerializationTestUtils;
|
||||
|
||||
/**
|
||||
* Unit tests relating to the abstract {@link AbstractPrototypeBasedTargetSource}
|
||||
* and not subclasses.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public final class PrototypeBasedTargetSourceTests {
|
||||
|
||||
@Test
|
||||
public void testSerializability() throws Exception {
|
||||
MutablePropertyValues tsPvs = new MutablePropertyValues();
|
||||
tsPvs.add("targetBeanName", "person");
|
||||
RootBeanDefinition tsBd = new RootBeanDefinition(TestTargetSource.class, tsPvs);
|
||||
|
||||
MutablePropertyValues pvs = new MutablePropertyValues();
|
||||
RootBeanDefinition bd = new RootBeanDefinition(SerializablePerson.class, pvs);
|
||||
bd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
|
||||
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
bf.registerBeanDefinition("ts", tsBd);
|
||||
bf.registerBeanDefinition("person", bd);
|
||||
|
||||
TestTargetSource cpts = (TestTargetSource) bf.getBean("ts");
|
||||
TargetSource serialized = (TargetSource) SerializationTestUtils.serializeAndDeserialize(cpts);
|
||||
assertTrue("Changed to SingletonTargetSource on deserialization",
|
||||
serialized instanceof SingletonTargetSource);
|
||||
SingletonTargetSource sts = (SingletonTargetSource) serialized;
|
||||
assertNotNull(sts.getTarget());
|
||||
}
|
||||
|
||||
|
||||
private static class TestTargetSource extends AbstractPrototypeBasedTargetSource {
|
||||
|
||||
/**
|
||||
* Nonserializable test field to check that subclass
|
||||
* state can't prevent serialization from working
|
||||
*/
|
||||
private TestBean thisFieldIsNotSerializable = new TestBean();
|
||||
|
||||
public Object getTarget() throws Exception {
|
||||
return newPrototypeInstance();
|
||||
}
|
||||
|
||||
public void releaseTarget(Object target) throws Exception {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
|
||||
|
||||
<beans>
|
||||
|
||||
<!-- Simple target -->
|
||||
<bean id="test" class="test.beans.SideEffectBean">
|
||||
<property name="count"><value>10</value></property>
|
||||
</bean>
|
||||
|
||||
<bean id="prototypeTest" class="test.beans.SideEffectBean" scope="prototype">
|
||||
<property name="count"><value>10</value></property>
|
||||
</bean>
|
||||
|
||||
<bean id="prototypeTargetSource" class="org.springframework.aop.target.PrototypeTargetSource">
|
||||
<property name="targetBeanName"><value>prototypeTest</value></property>
|
||||
</bean>
|
||||
|
||||
<bean id="debugInterceptor" class="test.aop.NopInterceptor" />
|
||||
|
||||
<bean id="singleton" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||
<property name="interceptorNames"><value>debugInterceptor,test</value></property>
|
||||
</bean>
|
||||
|
||||
<!--
|
||||
This will create a bean that creates a new target on each invocation.
|
||||
-->
|
||||
<bean id="prototype" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||
<property name="targetSource"><ref local="prototypeTargetSource"/></property>
|
||||
<property name="interceptorNames"><value>debugInterceptor</value></property>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.target;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static test.util.TestResourceUtils.qualifiedResource;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.xml.XmlBeanFactory;
|
||||
import org.springframework.core.io.Resource;
|
||||
|
||||
import test.beans.SideEffectBean;
|
||||
|
||||
|
||||
/**
|
||||
* @author Rod Johnson
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public final class PrototypeTargetSourceTests {
|
||||
|
||||
private static final Resource CONTEXT = qualifiedResource(PrototypeTargetSourceTests.class, "context.xml");
|
||||
|
||||
/** Initial count value set in bean factory XML */
|
||||
private static final int INITIAL_COUNT = 10;
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
this.beanFactory = new XmlBeanFactory(CONTEXT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that multiple invocations of the prototype bean will result
|
||||
* in no change to visible state, as a new instance is used.
|
||||
* With the singleton, there will be change.
|
||||
*/
|
||||
@Test
|
||||
public void testPrototypeAndSingletonBehaveDifferently() {
|
||||
SideEffectBean singleton = (SideEffectBean) beanFactory.getBean("singleton");
|
||||
assertEquals(INITIAL_COUNT, singleton.getCount() );
|
||||
singleton.doWork();
|
||||
assertEquals(INITIAL_COUNT + 1, singleton.getCount() );
|
||||
|
||||
SideEffectBean prototype = (SideEffectBean) beanFactory.getBean("prototype");
|
||||
assertEquals(INITIAL_COUNT, prototype.getCount() );
|
||||
prototype.doWork();
|
||||
assertEquals(INITIAL_COUNT, prototype.getCount() );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
|
||||
|
||||
<beans>
|
||||
|
||||
<bean id="prototypeTest" class="test.beans.SideEffectBean" scope="prototype">
|
||||
<property name="count"><value>10</value></property>
|
||||
</bean>
|
||||
|
||||
<bean id="threadLocalTs" class="org.springframework.aop.target.ThreadLocalTargetSource">
|
||||
<property name="targetBeanName"><value>prototypeTest</value></property>
|
||||
</bean>
|
||||
|
||||
<bean id="debugInterceptor" class="test.aop.NopInterceptor" />
|
||||
|
||||
<!--
|
||||
We want to invoke the getStatsMixin method on our ThreadLocal invoker
|
||||
-->
|
||||
<bean id="statsAdvisor" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
|
||||
<property name="targetObject"><ref local="threadLocalTs" /></property>
|
||||
<property name="targetMethod"><value>getStatsMixin</value></property>
|
||||
</bean>
|
||||
|
||||
<!--
|
||||
This will create a bean for each thread ("apartment")
|
||||
-->
|
||||
<bean id="apartment" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||
<property name="interceptorNames"><value>debugInterceptor,statsAdvisor</value></property>
|
||||
<property name="targetSource"><ref local="threadLocalTs"/></property>
|
||||
<!-- Necessary as have a mixin and want to avoid losing the class,
|
||||
because there's no target interface -->
|
||||
<property name="proxyTargetClass"><value>true</value></property>
|
||||
</bean>
|
||||
|
||||
<!-- ================ Definitions for second ThreadLocalTargetSource ====== -->
|
||||
|
||||
<bean id="test" class="test.beans.TestBean" scope="prototype">
|
||||
<property name="name"><value>Rod</value></property>
|
||||
<property name="spouse"><ref local="wife"/></property>
|
||||
</bean>
|
||||
|
||||
<bean id="wife" class="test.beans.TestBean">
|
||||
<property name="name"><value>Kerry</value></property>
|
||||
</bean>
|
||||
|
||||
<bean id="threadLocalTs2" class="org.springframework.aop.target.ThreadLocalTargetSource">
|
||||
<property name="targetBeanName"><value>test</value></property>
|
||||
</bean>
|
||||
|
||||
<bean id="threadLocal2" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||
<property name="targetSource"><ref local="threadLocalTs2"/></property>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* 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.target;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static test.util.TestResourceUtils.qualifiedResource;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.xml.XmlBeanFactory;
|
||||
import org.springframework.core.io.Resource;
|
||||
|
||||
import test.beans.ITestBean;
|
||||
import test.beans.SideEffectBean;
|
||||
|
||||
|
||||
/**
|
||||
* @author Rod Johnson
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public class ThreadLocalTargetSourceTests {
|
||||
|
||||
private static final Resource CONTEXT = qualifiedResource(ThreadLocalTargetSourceTests.class, "context.xml");
|
||||
|
||||
/** Initial count value set in bean factory XML */
|
||||
private static final int INITIAL_COUNT = 10;
|
||||
|
||||
private XmlBeanFactory beanFactory;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
this.beanFactory = new XmlBeanFactory(CONTEXT);
|
||||
}
|
||||
|
||||
/**
|
||||
* We must simulate container shutdown, which should clear threads.
|
||||
*/
|
||||
protected void tearDown() {
|
||||
this.beanFactory.destroySingletons();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check we can use two different ThreadLocalTargetSources
|
||||
* managing objects of different types without them interfering
|
||||
* with one another.
|
||||
*/
|
||||
@Test
|
||||
public void testUseDifferentManagedInstancesInSameThread() {
|
||||
SideEffectBean apartment = (SideEffectBean) beanFactory.getBean("apartment");
|
||||
assertEquals(INITIAL_COUNT, apartment.getCount() );
|
||||
apartment.doWork();
|
||||
assertEquals(INITIAL_COUNT + 1, apartment.getCount() );
|
||||
|
||||
ITestBean test = (ITestBean) beanFactory.getBean("threadLocal2");
|
||||
assertEquals("Rod", test.getName());
|
||||
assertEquals("Kerry", test.getSpouse().getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReuseInSameThread() {
|
||||
SideEffectBean apartment = (SideEffectBean) beanFactory.getBean("apartment");
|
||||
assertEquals(INITIAL_COUNT, apartment.getCount() );
|
||||
apartment.doWork();
|
||||
assertEquals(INITIAL_COUNT + 1, apartment.getCount() );
|
||||
|
||||
apartment = (SideEffectBean) beanFactory.getBean("apartment");
|
||||
assertEquals(INITIAL_COUNT + 1, apartment.getCount() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Relies on introduction.
|
||||
*/
|
||||
@Test
|
||||
public void testCanGetStatsViaMixin() {
|
||||
ThreadLocalTargetSourceStats stats = (ThreadLocalTargetSourceStats) beanFactory.getBean("apartment");
|
||||
// +1 because creating target for stats call counts
|
||||
assertEquals(1, stats.getInvocationCount());
|
||||
SideEffectBean apartment = (SideEffectBean) beanFactory.getBean("apartment");
|
||||
apartment.doWork();
|
||||
// +1 again
|
||||
assertEquals(3, stats.getInvocationCount());
|
||||
// + 1 for states call!
|
||||
assertEquals(3, stats.getHitCount());
|
||||
apartment.doWork();
|
||||
assertEquals(6, stats.getInvocationCount());
|
||||
assertEquals(6, stats.getHitCount());
|
||||
// Only one thread so only one object can have been bound
|
||||
assertEquals(1, stats.getObjectCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNewThreadHasOwnInstance() throws InterruptedException {
|
||||
SideEffectBean apartment = (SideEffectBean) beanFactory.getBean("apartment");
|
||||
assertEquals(INITIAL_COUNT, apartment.getCount() );
|
||||
apartment.doWork();
|
||||
apartment.doWork();
|
||||
apartment.doWork();
|
||||
assertEquals(INITIAL_COUNT + 3, apartment.getCount() );
|
||||
|
||||
class Runner implements Runnable {
|
||||
public SideEffectBean mine;
|
||||
public void run() {
|
||||
this.mine = (SideEffectBean) beanFactory.getBean("apartment");
|
||||
assertEquals(INITIAL_COUNT, mine.getCount() );
|
||||
mine.doWork();
|
||||
assertEquals(INITIAL_COUNT + 1, mine.getCount() );
|
||||
}
|
||||
}
|
||||
Runner r = new Runner();
|
||||
Thread t = new Thread(r);
|
||||
t.start();
|
||||
t.join();
|
||||
|
||||
assertNotNull(r);
|
||||
|
||||
// Check it didn't affect the other thread's copy
|
||||
assertEquals(INITIAL_COUNT + 3, apartment.getCount() );
|
||||
|
||||
// When we use other thread's copy in this thread
|
||||
// it should behave like ours
|
||||
assertEquals(INITIAL_COUNT + 3, r.mine.getCount() );
|
||||
|
||||
// Bound to two threads
|
||||
assertEquals(2, ((ThreadLocalTargetSourceStats) apartment).getObjectCount());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for SPR-1442. Destroyed target should re-associated with thread and not throw NPE
|
||||
*/
|
||||
@Test
|
||||
public void testReuseDestroyedTarget() {
|
||||
ThreadLocalTargetSource source = (ThreadLocalTargetSource)this.beanFactory.getBean("threadLocalTs");
|
||||
|
||||
// try first time
|
||||
source.getTarget();
|
||||
source.destroy();
|
||||
|
||||
// try second time
|
||||
try {
|
||||
source.getTarget();
|
||||
} catch(NullPointerException ex) {
|
||||
fail("Should not throw NPE");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.target.dynamic;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public final class RefreshableTargetSourceTests {
|
||||
|
||||
/**
|
||||
* Test what happens when checking for refresh but not refreshing object.
|
||||
*/
|
||||
@Test
|
||||
public void testRefreshCheckWithNonRefresh() throws Exception {
|
||||
CountingRefreshableTargetSource ts = new CountingRefreshableTargetSource();
|
||||
ts.setRefreshCheckDelay(0);
|
||||
|
||||
Object a = ts.getTarget();
|
||||
Thread.sleep(1);
|
||||
Object b = ts.getTarget();
|
||||
|
||||
assertEquals("Should be one call to freshTarget to get initial target", 1, ts.getCallCount());
|
||||
assertSame("Returned objects should be the same - no refresh should occur", a, b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test what happens when checking for refresh and refresh occurs.
|
||||
*/
|
||||
@Test
|
||||
public void testRefreshCheckWithRefresh() throws Exception {
|
||||
CountingRefreshableTargetSource ts = new CountingRefreshableTargetSource(true);
|
||||
ts.setRefreshCheckDelay(0);
|
||||
|
||||
Object a = ts.getTarget();
|
||||
Thread.sleep(100);
|
||||
Object b = ts.getTarget();
|
||||
|
||||
assertEquals("Should have called freshTarget twice", 2, ts.getCallCount());
|
||||
assertNotSame("Should be different objects", a, b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test what happens when no refresh occurs.
|
||||
*/
|
||||
@Test
|
||||
public void testWithNoRefreshCheck() throws Exception {
|
||||
CountingRefreshableTargetSource ts = new CountingRefreshableTargetSource(true);
|
||||
ts.setRefreshCheckDelay(-1);
|
||||
|
||||
Object a = ts.getTarget();
|
||||
Object b = ts.getTarget();
|
||||
|
||||
assertEquals("Refresh target should only be called once", 1, ts.getCallCount());
|
||||
assertSame("Objects should be the same - refresh check delay not elapsed", a, b);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRefreshOverTime() throws Exception {
|
||||
CountingRefreshableTargetSource ts = new CountingRefreshableTargetSource(true);
|
||||
ts.setRefreshCheckDelay(100);
|
||||
|
||||
Object a = ts.getTarget();
|
||||
Object b = ts.getTarget();
|
||||
assertEquals("Objects should be same", a, b);
|
||||
|
||||
Thread.sleep(50);
|
||||
|
||||
Object c = ts.getTarget();
|
||||
assertEquals("A and C should be same", a, c);
|
||||
|
||||
Thread.sleep(60);
|
||||
|
||||
Object d = ts.getTarget();
|
||||
assertNotNull("D should not be null", d);
|
||||
assertFalse("A and D should not be equal", a.equals(d));
|
||||
|
||||
Object e = ts.getTarget();
|
||||
assertEquals("D and E should be equal", d, e);
|
||||
|
||||
Thread.sleep(110);
|
||||
|
||||
Object f = ts.getTarget();
|
||||
assertFalse("E and F should be different", e.equals(f));
|
||||
}
|
||||
|
||||
|
||||
private static class CountingRefreshableTargetSource extends AbstractRefreshableTargetSource {
|
||||
|
||||
private int callCount;
|
||||
|
||||
private boolean requiresRefresh;
|
||||
|
||||
public CountingRefreshableTargetSource() {
|
||||
}
|
||||
|
||||
public CountingRefreshableTargetSource(boolean requiresRefresh) {
|
||||
this.requiresRefresh = requiresRefresh;
|
||||
}
|
||||
|
||||
protected Object freshTarget() {
|
||||
this.callCount++;
|
||||
return new Object();
|
||||
}
|
||||
|
||||
public int getCallCount() {
|
||||
return this.callCount;
|
||||
}
|
||||
|
||||
protected boolean requiresRefresh() {
|
||||
return this.requiresRefresh;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user