diff --git a/org.springframework.aop/src/test/java/org/springframework/aop/aspectj/AspectJAdviceParameterNameDiscoverAnnotationTests.java b/org.springframework.aop/src/test/java/org/springframework/aop/aspectj/AspectJAdviceParameterNameDiscoverAnnotationTests.java
index 523d2e8b8a5..3bc43af6576 100644
--- a/org.springframework.aop/src/test/java/org/springframework/aop/aspectj/AspectJAdviceParameterNameDiscoverAnnotationTests.java
+++ b/org.springframework.aop/src/test/java/org/springframework/aop/aspectj/AspectJAdviceParameterNameDiscoverAnnotationTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2007 the original author or authors.
+ * 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.
@@ -20,6 +20,7 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import org.aspectj.lang.ProceedingJoinPoint;
+import org.junit.Test;
/**
@@ -28,14 +29,17 @@ import org.aspectj.lang.ProceedingJoinPoint;
* doesn't matter in the grand scheme of things...
*
* @author Adrian Colyer
+ * @author Chris Beams
*/
-public class AspectJAdviceParameterNameDiscoverAnnotationTests extends AspectJAdviceParameterNameDiscovererTests {
+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)",
diff --git a/org.springframework.aop/src/test/java/org/springframework/aop/aspectj/AspectJAdviceParameterNameDiscovererTests.java b/org.springframework.aop/src/test/java/org/springframework/aop/aspectj/AspectJAdviceParameterNameDiscovererTests.java
index 13042e1786b..f135239fe09 100644
--- a/org.springframework.aop/src/test/java/org/springframework/aop/aspectj/AspectJAdviceParameterNameDiscovererTests.java
+++ b/org.springframework.aop/src/test/java/org/springframework/aop/aspectj/AspectJAdviceParameterNameDiscovererTests.java
@@ -25,11 +25,12 @@ import java.lang.reflect.Method;
/**
* Unit tests for the {@link AspectJAdviceParameterNameDiscoverer} class.
- *
- *
See also TigerAspectJAdviceParameterNameDiscovererTests in
+ *
+ *
See also {@link TigerAspectJAdviceParameterNameDiscovererTests} in
* the 'tiger' tree for tests relating to annotations.
*
* @author Adrian Colyer
+ * @author Chris Beams
*/
public class AspectJAdviceParameterNameDiscovererTests {
diff --git a/org.springframework.aop/src/test/java/org/springframework/aop/aspectj/AspectJExpressionPointcutTests.java b/org.springframework.aop/src/test/java/org/springframework/aop/aspectj/AspectJExpressionPointcutTests.java
index a050e5bf342..8b47fede6a2 100644
--- a/org.springframework.aop/src/test/java/org/springframework/aop/aspectj/AspectJExpressionPointcutTests.java
+++ b/org.springframework.aop/src/test/java/org/springframework/aop/aspectj/AspectJExpressionPointcutTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2005 the original author or authors.
+ * 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.
@@ -16,17 +16,20 @@
package org.springframework.aop.aspectj;
+import static org.junit.Assert.*;
+
import java.lang.reflect.Method;
-import junit.framework.TestCase;
-
+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.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.beans.IOther;
@@ -38,8 +41,9 @@ import org.springframework.beans.factory.support.DefaultListableBeanFactory;
/**
* @author Rob Harrop
* @author Rod Johnson
+ * @author Chris Beams
*/
-public class AspectJExpressionPointcutTests extends TestCase {
+public final class AspectJExpressionPointcutTests {
public static final String MATCH_ALL_METHODS = "execution(* *(..))";
@@ -51,6 +55,16 @@ public class AspectJExpressionPointcutTests extends TestCase {
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 org.springframework.beans.TestBean.getAge())";
@@ -68,16 +82,7 @@ public class AspectJExpressionPointcutTests extends TestCase {
assertFalse("Expression should match setAge() method", methodMatcher.matches(setAge, TestBean.class));
}
-
- public void setUp() throws NoSuchMethodException {
- getAge = TestBean.class.getMethod("getAge", 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 testMatchWithTypePattern() throws Exception {
String expression = "execution(* *..TestBean.*Age(..))";
@@ -96,10 +101,12 @@ public class AspectJExpressionPointcutTests extends TestCase {
}
+ @Test
public void testThis() throws SecurityException, NoSuchMethodException{
testThisOrTarget("this");
}
+ @Test
public void testTarget() throws SecurityException, NoSuchMethodException {
testThisOrTarget("target");
}
@@ -130,17 +137,19 @@ public class AspectJExpressionPointcutTests extends TestCase {
assertTrue(testBeanPc.matches(TestBean.class));
assertTrue(testBeanPc.matches(getAge, TestBean.class));
- assertTrue(iOtherPc.matches(OtherIOther.class.getMethod("absquatulate", null),
+ assertTrue(iOtherPc.matches(OtherIOther.class.getMethod("absquatulate", (Class>[])null),
OtherIOther.class));
- assertFalse(testBeanPc.matches(OtherIOther.class.getMethod("absquatulate", null),
+ 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);
}
@@ -159,13 +168,14 @@ public class AspectJExpressionPointcutTests extends TestCase {
assertTrue(withinBeansPc.matches(getAge, TestBean.class));
assertEquals(matchSubpackages, withinBeansPc.matches(BeanFactory.class));
assertEquals(matchSubpackages, withinBeansPc.matches(
- DefaultListableBeanFactory.class.getMethod("getBeanDefinitionCount", null),
+ DefaultListableBeanFactory.class.getMethod("getBeanDefinitionCount", (Class>[])null),
DefaultListableBeanFactory.class));
assertFalse(withinBeansPc.matches(String.class));
- assertFalse(withinBeansPc.matches(OtherIOther.class.getMethod("absquatulate", null),
+ assertFalse(withinBeansPc.matches(OtherIOther.class.getMethod("absquatulate", (Class>[])null),
OtherIOther.class));
}
+ @Test
public void testFriendlyErrorOnNoLocationClassMatching() {
AspectJExpressionPointcut pc = new AspectJExpressionPointcut();
try {
@@ -177,6 +187,7 @@ public class AspectJExpressionPointcutTests extends TestCase {
}
}
+ @Test
public void testFriendlyErrorOnNoLocation2ArgMatching() {
AspectJExpressionPointcut pc = new AspectJExpressionPointcut();
try {
@@ -188,6 +199,7 @@ public class AspectJExpressionPointcutTests extends TestCase {
}
}
+ @Test
public void testFriendlyErrorOnNoLocation3ArgMatching() {
AspectJExpressionPointcut pc = new AspectJExpressionPointcut();
try {
@@ -200,6 +212,7 @@ public class AspectJExpressionPointcutTests extends TestCase {
}
+ @Test
public void testMatchWithArgs() throws Exception {
String expression = "execution(void org.springframework.beans.TestBean.setSomeNumber(Number)) && args(Double)";
@@ -220,6 +233,7 @@ public class AspectJExpressionPointcutTests extends TestCase {
assertTrue("Should be a runtime match", methodMatcher.isRuntime());
}
+ @Test
public void testSimpleAdvice() {
String expression = "execution(int org.springframework.beans.TestBean.getAge())";
@@ -238,6 +252,7 @@ public class AspectJExpressionPointcutTests extends TestCase {
assertEquals("Calls should still be 1", 1, interceptor.getCount());
}
+ @Test
public void testDynamicMatchingProxy() {
String expression = "execution(void org.springframework.beans.TestBean.setSomeNumber(Number)) && args(Double)";
@@ -256,6 +271,7 @@ public class AspectJExpressionPointcutTests extends TestCase {
assertEquals("Calls should be 1", 1, interceptor.getCount());
}
+ @Test
public void testInvalidExpression() {
String expression = "execution(void org.springframework.beans.TestBean.setSomeNumber(Number) && args(Double)";
@@ -297,6 +313,7 @@ public class AspectJExpressionPointcutTests extends TestCase {
assertFalse("Expression should not match String class", classFilter.matches(String.class));
}
+ @Test
public void testWithUnsupportedPointcutPrimitive() throws Exception {
String expression = "call(int org.springframework.beans.TestBean.getAge())";
@@ -310,6 +327,7 @@ public class AspectJExpressionPointcutTests extends TestCase {
}
+ @Test
public void testAndSubstitution() {
Pointcut pc = getPointcut("execution(* *(..)) and args(String)");
PointcutExpression expr =
@@ -317,6 +335,7 @@ public class AspectJExpressionPointcutTests extends TestCase {
assertEquals("execution(* *(..)) && args(String)",expr.getPointcutExpression());
}
+ @Test
public void testMultipleAndSubstitutions() {
Pointcut pc = getPointcut("execution(* *(..)) and args(String) and this(Object)");
PointcutExpression expr =
@@ -330,3 +349,23 @@ public class AspectJExpressionPointcutTests extends TestCase {
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;
+ }
+
+}
\ No newline at end of file
diff --git a/org.springframework.aop/src/test/java/org/springframework/aop/aspectj/BeanNamePointcutMatchingTests.java b/org.springframework.aop/src/test/java/org/springframework/aop/aspectj/BeanNamePointcutMatchingTests.java
index f48d633e8f3..9120b02cc3a 100644
--- a/org.springframework.aop/src/test/java/org/springframework/aop/aspectj/BeanNamePointcutMatchingTests.java
+++ b/org.springframework.aop/src/test/java/org/springframework/aop/aspectj/BeanNamePointcutMatchingTests.java
@@ -27,7 +27,7 @@ import org.springframework.beans.TestBean;
* @author Ramnivas Laddad
* @author Chris Beams
*/
-public class BeanNamePointcutMatchingTests {
+public final class BeanNamePointcutMatchingTests {
@Test
public void testMatchingPointcuts() {
diff --git a/org.springframework.aop/src/test/java/org/springframework/aop/aspectj/CallCountingInterceptor.java b/org.springframework.aop/src/test/java/org/springframework/aop/aspectj/CallCountingInterceptor.java
deleted file mode 100644
index aa5eb61eddc..00000000000
--- a/org.springframework.aop/src/test/java/org/springframework/aop/aspectj/CallCountingInterceptor.java
+++ /dev/null
@@ -1,26 +0,0 @@
-
-package org.springframework.aop.aspectj;
-
-import org.aopalliance.intercept.MethodInterceptor;
-import org.aopalliance.intercept.MethodInvocation;
-
-/**
- * @author robh
- */
-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;
- }
-}
diff --git a/org.springframework.aop/src/test/java/org/springframework/aop/aspectj/MethodInvocationProceedingJoinPointTests.java b/org.springframework.aop/src/test/java/org/springframework/aop/aspectj/MethodInvocationProceedingJoinPointTests.java
index 75e1e047f1e..d77649f2843 100644
--- a/org.springframework.aop/src/test/java/org/springframework/aop/aspectj/MethodInvocationProceedingJoinPointTests.java
+++ b/org.springframework.aop/src/test/java/org/springframework/aop/aspectj/MethodInvocationProceedingJoinPointTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2006 the original author or authors.
+ * 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.
@@ -41,7 +41,7 @@ import org.springframework.beans.TestBean;
* @author Chris Beams
* @since 2.0
*/
-public class MethodInvocationProceedingJoinPointTests {
+public final class MethodInvocationProceedingJoinPointTests {
@Test
public void testingBindingWithJoinPoint() {
diff --git a/org.springframework.aop/src/test/java/org/springframework/aop/aspectj/TigerAspectJAdviceParameterNameDiscovererTests.java b/org.springframework.aop/src/test/java/org/springframework/aop/aspectj/TigerAspectJAdviceParameterNameDiscovererTests.java
index 26268b115c5..824f51433b6 100644
--- a/org.springframework.aop/src/test/java/org/springframework/aop/aspectj/TigerAspectJAdviceParameterNameDiscovererTests.java
+++ b/org.springframework.aop/src/test/java/org/springframework/aop/aspectj/TigerAspectJAdviceParameterNameDiscovererTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2006 the original author or authors.
+ * 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.
@@ -16,50 +16,62 @@
package org.springframework.aop.aspectj;
+import org.junit.Test;
import org.springframework.aop.aspectj.AspectJAdviceParameterNameDiscoverer.AmbiguousBindingException;
/**
- * Tests just the annotation binding part of AspectJAdviceParameterNameDiscoverer;
+ * Tests just the annotation binding part of {@link AspectJAdviceParameterNameDiscoverer};
* see supertype for remaining tests.
*
* @author Adrian Colyer
+ * @author Chris Beams
*/
-public class TigerAspectJAdviceParameterNameDiscovererTests extends AspectJAdviceParameterNameDiscovererTests {
+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"});
@@ -72,7 +84,6 @@ public class TigerAspectJAdviceParameterNameDiscovererTests extends AspectJAdvic
public void annotationMedley(Throwable t, Object foo, int x, MyAnnotation ma) {}
-
@interface MyAnnotation {}
}
diff --git a/org.springframework.aop/src/test/java/org/springframework/aop/aspectj/TigerAspectJExpressionPointcutTests.java b/org.springframework.aop/src/test/java/org/springframework/aop/aspectj/TigerAspectJExpressionPointcutTests.java
index 79931bd682e..83ee0227908 100644
--- a/org.springframework.aop/src/test/java/org/springframework/aop/aspectj/TigerAspectJExpressionPointcutTests.java
+++ b/org.springframework.aop/src/test/java/org/springframework/aop/aspectj/TigerAspectJExpressionPointcutTests.java
@@ -33,12 +33,12 @@ import test.annotation.transaction.Tx;
/**
- * Java5-specific AspectJExpressionPointcutTests.
+ * Java5-specific {@link AspectJExpressionPointcutTests}.
*
* @author Rod Johnson
* @author Chris Beams
*/
-public class TigerAspectJExpressionPointcutTests {
+public final class TigerAspectJExpressionPointcutTests {
// TODO factor into static in AspectJExpressionPointcut
private Method getAge;
diff --git a/org.springframework.aop/src/test/java/org/springframework/aop/aspectj/TypePatternClassFilterTests.java b/org.springframework.aop/src/test/java/org/springframework/aop/aspectj/TypePatternClassFilterTests.java
index 5a9a35b84eb..b01447ed5e7 100644
--- a/org.springframework.aop/src/test/java/org/springframework/aop/aspectj/TypePatternClassFilterTests.java
+++ b/org.springframework.aop/src/test/java/org/springframework/aop/aspectj/TypePatternClassFilterTests.java
@@ -35,14 +35,10 @@ import org.springframework.beans.factory.support.DefaultListableBeanFactory;
*/
public final class TypePatternClassFilterTests {
- @Test
+ @Test(expected=IllegalArgumentException.class)
public void testInvalidPattern() {
- try {
- new TypePatternClassFilter("-");
- fail("Pattern must be recognized as invalid.");
- }
- catch (IllegalArgumentException expected) {
- }
+ // should throw - pattern must be recognized as invalid
+ new TypePatternClassFilter("-");
}
@Test
diff --git a/org.springframework.aop/src/test/java/org/springframework/aop/aspectj/annotation/AbstractAspectJAdvisorFactoryTests.java b/org.springframework.aop/src/test/java/org/springframework/aop/aspectj/annotation/AbstractAspectJAdvisorFactoryTests.java
index e895c12b164..5c09f2956cc 100644
--- a/org.springframework.aop/src/test/java/org/springframework/aop/aspectj/annotation/AbstractAspectJAdvisorFactoryTests.java
+++ b/org.springframework.aop/src/test/java/org/springframework/aop/aspectj/annotation/AbstractAspectJAdvisorFactoryTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2007 the original author or authors.
+ * 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.
@@ -18,12 +18,14 @@ package org.springframework.aop.aspectj.annotation;
import static org.junit.Assert.*;
import java.io.FileNotFoundException;
+import java.lang.reflect.Method;
import java.lang.reflect.UndeclaredThrowableException;
import java.rmi.RemoteException;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
+import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
@@ -31,14 +33,16 @@ import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
+import org.aspectj.lang.annotation.DeclareParents;
import org.aspectj.lang.annotation.DeclarePrecedence;
import org.aspectj.lang.annotation.Pointcut;
+import org.aspectj.lang.reflect.MethodSignature;
import org.junit.Test;
-
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory.SyntheticInstantiationAdvisor;
import org.springframework.aop.framework.Advised;
import org.springframework.aop.framework.AopConfigException;
+import org.springframework.aop.framework.DefaultLockable;
import org.springframework.aop.framework.Lockable;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.interceptor.ExposeInvocationInterceptor;
@@ -48,16 +52,17 @@ import org.springframework.beans.TestBean;
import org.springframework.core.OrderComparator;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
+import org.springframework.util.ObjectUtils;
import test.aspect.PerTargetAspect;
import test.aspect.TwoAdviceAspect;
-
/**
* Abstract tests for AspectJAdvisorFactory.
* See subclasses for tests of concrete factories.
*
* @author Rod Johnson
+ * @author Chris Beams
*/
public abstract class AbstractAspectJAdvisorFactoryTests {
@@ -861,3 +866,198 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
}
}
+
+
+/**
+ * Add a DeclareParents field in concrete subclasses, to identify
+ * the type pattern to apply the introduction to.
+ *
+ * @author Rod Johnson
+ * @since 2.0
+ */
+@Aspect
+abstract class AbstractMakeModifiable {
+
+ public interface MutableModifable extends Modifiable {
+ void markDirty();
+ }
+
+ public static class ModifiableImpl implements MutableModifable {
+ private boolean modified;
+
+ public void acceptChanges() {
+ modified = false;
+ }
+
+ public boolean isModified() {
+ return modified;
+ }
+
+ public void markDirty() {
+ this.modified = true;
+ }
+ }
+
+ @Before(value="execution(void set*(*)) && this(modifiable) && args(newValue)",
+ argNames="modifiable,newValue")
+ public void recordModificationIfSetterArgumentDiffersFromOldValue(JoinPoint jp,
+ MutableModifable mixin, Object newValue) {
+
+ /*
+ * We use the mixin to check and, if necessary, change,
+ * modification status. We need the JoinPoint to get the
+ * setter method. We use newValue for comparison.
+ * We try to invoke the getter if possible.
+ */
+
+ if (mixin.isModified()) {
+ // Already changed, don't need to change again
+ //System.out.println("changed");
+ return;
+ }
+
+ // Find the current raw value, by invoking the corresponding setter
+ Method correspondingGetter = getGetterFromSetter(((MethodSignature) jp.getSignature()).getMethod());
+ boolean modified = true;
+ if (correspondingGetter != null) {
+ try {
+ Object oldValue = correspondingGetter.invoke(jp.getTarget());
+ //System.out.println("Old value=" + oldValue + "; new=" + newValue);
+ modified = !ObjectUtils.nullSafeEquals(oldValue, newValue);
+ }
+ catch (Exception ex) {
+ ex.printStackTrace();
+ // Don't sweat on exceptions; assume value was modified
+ }
+ }
+ else {
+ //System.out.println("cannot get getter for " + jp);
+ }
+ if (modified) {
+ mixin.markDirty();
+ }
+ }
+
+ private Method getGetterFromSetter(Method setter) {
+ String getterName = setter.getName().replaceFirst("set", "get");
+ try {
+ return setter.getDeclaringClass().getMethod(getterName, (Class[]) null);
+ }
+ catch (NoSuchMethodException ex) {
+ // must be write only
+ return null;
+ }
+ }
+
+}
+
+
+/**
+ * Adds a declare parents pointcut.
+ * @author Rod Johnson
+ * @since 2.0
+ */
+@Aspect
+class MakeITestBeanModifiable extends AbstractMakeModifiable {
+
+ @DeclareParents(value = "org.springframework.beans.ITestBean+",
+ defaultImpl=ModifiableImpl.class)
+ public static MutableModifable mixin;
+
+}
+
+
+/**
+ * Demonstrates introductions, AspectJ annotation style.
+ */
+@Aspect
+class MakeLockable {
+
+ @DeclareParents(value = "org.springframework..*",
+ defaultImpl=DefaultLockable.class)
+ public static Lockable mixin;
+
+ @Before(value="execution(void set*(*)) && this(mixin)", argNames="mixin")
+ public void checkNotLocked(
+ Lockable mixin) // Bind to arg
+ {
+ // Can also obtain the mixin (this) this way
+ //Lockable mixin = (Lockable) jp.getThis();
+ if (mixin.locked()) {
+ throw new IllegalStateException();
+ }
+ }
+
+}
+
+
+class CannotBeUnlocked implements Lockable, Comparable