You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@struts.apache.org by lu...@apache.org on 2017/06/05 06:49:17 UTC
struts git commit: WW-4800 Executes aspects when chaining AOPed
actions
Repository: struts
Updated Branches:
refs/heads/master 2fb431d97 -> 8e9f9fb89
WW-4800 Executes aspects when chaining AOPed actions
Project: http://git-wip-us.apache.org/repos/asf/struts/repo
Commit: http://git-wip-us.apache.org/repos/asf/struts/commit/8e9f9fb8
Tree: http://git-wip-us.apache.org/repos/asf/struts/tree/8e9f9fb8
Diff: http://git-wip-us.apache.org/repos/asf/struts/diff/8e9f9fb8
Branch: refs/heads/master
Commit: 8e9f9fb89ff84e3f383d0aef73443af919c271d7
Parents: 2fb431d
Author: Yasser Zamani <ya...@live.com>
Authored: Mon May 29 18:56:10 2017 +0430
Committer: Yasser Zamani <ya...@live.com>
Committed: Mon May 29 18:56:10 2017 +0430
----------------------------------------------------------------------
.../xwork2/interceptor/ChainingInterceptor.java | 5 +-
.../xwork2/ognl/OgnlReflectionProvider.java | 7 ++-
.../com/opensymphony/xwork2/ognl/OgnlUtil.java | 25 +++++++-
.../com/opensymphony/xwork2/util/ProxyUtil.java | 61 +++++++++++++-------
.../util/reflection/ReflectionProvider.java | 18 +++++-
.../opensymphony/xwork2/ognl/OgnlUtilTest.java | 26 +++++++++
.../xwork2/spring/ActionsFromSpringTest.java | 20 ++++---
.../xwork2/spring/SpringProxyUtilTest.java | 32 +++++-----
.../opensymphony/xwork2/spring/TestAspect.java | 46 +++++++++++++++
.../xwork2/spring/actionContext-spring.xml | 16 +++--
10 files changed, 204 insertions(+), 52 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/struts/blob/8e9f9fb8/core/src/main/java/com/opensymphony/xwork2/interceptor/ChainingInterceptor.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/ChainingInterceptor.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/ChainingInterceptor.java
index 59b1d88..430edcc 100644
--- a/core/src/main/java/com/opensymphony/xwork2/interceptor/ChainingInterceptor.java
+++ b/core/src/main/java/com/opensymphony/xwork2/interceptor/ChainingInterceptor.java
@@ -163,10 +163,11 @@ public class ChainingInterceptor extends AbstractInterceptor {
for (Object object : list) {
if (shouldCopy(object)) {
Object action = invocation.getAction();
+ Class<?> editable = null;
if(ProxyUtil.isSpringAopProxy(action)) {
- action = ProxyUtil.getSpringUltimateTargetObject(action);
+ editable = ProxyUtil.springUltimateTargetClass(action);
}
- reflectionProvider.copy(object, action, ctxMap, prepareExcludes(), includes);
+ reflectionProvider.copy(object, action, ctxMap, prepareExcludes(), includes, editable);
}
}
}
http://git-wip-us.apache.org/repos/asf/struts/blob/8e9f9fb8/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlReflectionProvider.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlReflectionProvider.java b/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlReflectionProvider.java
index 34f3043..b1cd339 100644
--- a/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlReflectionProvider.java
+++ b/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlReflectionProvider.java
@@ -70,7 +70,12 @@ public class OgnlReflectionProvider implements ReflectionProvider {
public void copy(Object from, Object to, Map<String, Object> context,
Collection<String> exclusions, Collection<String> inclusions) {
- ognlUtil.copy(from, to, context, exclusions, inclusions);
+ copy(from, to, context, exclusions, inclusions, null);
+ }
+
+ public void copy(Object from, Object to, Map<String, Object> context,
+ Collection<String> exclusions, Collection<String> inclusions, Class<?> editable) {
+ ognlUtil.copy(from, to, context, exclusions, inclusions, editable);
}
public Object getRealTarget(String property, Map<String, Object> context, Object root)
http://git-wip-us.apache.org/repos/asf/struts/blob/8e9f9fb8/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java b/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java
index fe64d8f..ced8eff 100644
--- a/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java
+++ b/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java
@@ -450,6 +450,24 @@ public class OgnlUtil {
* note if exclusions AND inclusions are supplied and not null nothing will get copied.
*/
public void copy(final Object from, final Object to, final Map<String, Object> context, Collection<String> exclusions, Collection<String> inclusions) {
+ copy(from, to, context, exclusions, inclusions, null);
+ }
+
+ /**
+ * Copies the properties in the object "from" and sets them in the object "to"
+ * only setting properties defined in the given "editable" class (or interface)
+ * using specified type converter, or {@link com.opensymphony.xwork2.conversion.impl.XWorkConverter} if none
+ * is specified.
+ *
+ * @param from the source object
+ * @param to the target object
+ * @param context the action context we're running under
+ * @param exclusions collection of method names to excluded from copying ( can be null)
+ * @param inclusions collection of method names to included copying (can be null)
+ * note if exclusions AND inclusions are supplied and not null nothing will get copied.
+ * @param editable the class (or interface) to restrict property setting to
+ */
+ public void copy(final Object from, final Object to, final Map<String, Object> context, Collection<String> exclusions, Collection<String> inclusions, Class<?> editable) {
if (from == null || to == null) {
LOG.warn("Attempting to copy from or to a null source. This is illegal and is bein skipped. This may be due to an error in an OGNL expression, action chaining, or some other event.");
return;
@@ -466,7 +484,12 @@ public class OgnlUtil {
try {
fromPds = getPropertyDescriptors(from);
- toPds = getPropertyDescriptors(to);
+ if (editable != null) {
+ toPds = getPropertyDescriptors(editable);
+ }
+ else {
+ toPds = getPropertyDescriptors(to);
+ }
} catch (IntrospectionException e) {
LOG.error("An error occurred", e);
return;
http://git-wip-us.apache.org/repos/asf/struts/blob/8e9f9fb8/core/src/main/java/com/opensymphony/xwork2/util/ProxyUtil.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/com/opensymphony/xwork2/util/ProxyUtil.java b/core/src/main/java/com/opensymphony/xwork2/util/ProxyUtil.java
index 6a8ac53..a3f8740 100644
--- a/core/src/main/java/com/opensymphony/xwork2/util/ProxyUtil.java
+++ b/core/src/main/java/com/opensymphony/xwork2/util/ProxyUtil.java
@@ -29,31 +29,32 @@ import java.lang.reflect.Proxy;
public class ProxyUtil {
private static final String SPRING_ADVISED_CLASS_NAME = "org.springframework.aop.framework.Advised";
private static final String SPRING_SPRINGPROXY_CLASS_NAME = "org.springframework.aop.SpringProxy";
+ private static final String SPRING_SINGLETONTARGETSOURCE_CLASS_NAME = "org.springframework.aop.target.SingletonTargetSource";
+ private static final String SPRING_TARGETCLASSAWARE_CLASS_NAME = "org.springframework.aop.TargetClassAware";
/**
- * Get the ultimate <em>target</em> object of the supplied {@code candidate}
- * object, unwrapping not only a top-level proxy but also any number of
- * nested proxies.
- * <p>If the supplied {@code candidate} is a Spring proxy, the ultimate target of all
- * nested proxies will be returned; otherwise, the {@code candidate}
- * will be returned <em>as is</em>.
- * @param candidate the instance to check (potentially a Spring AOP proxy;
- * never {@code null})
- * @return the target object or the {@code candidate} (never {@code null})
- * @throws IllegalStateException if an error occurs while unwrapping a proxy
+ * Determine the ultimate target class of the given spring bean instance, traversing
+ * not only a top-level spring proxy but any number of nested spring proxies as well —
+ * as long as possible without side effects, that is, just for singleton targets.
+ * @param candidate the instance to check (might be a spring AOP proxy)
+ * @return the ultimate target class (or the plain class of the given
+ * object as fallback; never {@code null})
*/
- public static <T> T getSpringUltimateTargetObject(Object candidate) {
- try {
- if (isSpringAopProxy(candidate) && implementsInterface(candidate.getClass(), SPRING_ADVISED_CLASS_NAME)) {
- Object targetSource = MethodUtils.invokeMethod(candidate, "getTargetSource");
- Object target = MethodUtils.invokeMethod(targetSource, "getTarget");
- return getSpringUltimateTargetObject(target);
+ public static Class<?> springUltimateTargetClass(Object candidate) {
+ Object current = candidate;
+ Class<?> result = null;
+ while (null != current && implementsInterface(current.getClass(), SPRING_TARGETCLASSAWARE_CLASS_NAME)) {
+ try {
+ result = (Class<?>) MethodUtils.invokeMethod(current, "getTargetClass");
+ } catch (Throwable ignored) {
}
+ current = getSingletonTarget(current);
}
- catch (Throwable ex) {
- throw new IllegalStateException("Failed to unwrap proxied object", ex);
+ if (result == null) {
+ Class<?> clazz = candidate.getClass();
+ result = (isCglibProxyClass(clazz) ? clazz.getSuperclass() : candidate.getClass());
}
- return (T) candidate;
+ return result;
}
/**
@@ -67,6 +68,26 @@ public class ProxyUtil {
}
/**
+ * Obtain the singleton target object behind the given spring proxy, if any.
+ * @param candidate the (potential) spring proxy to check
+ * @return the singleton target object, or {@code null} in any other case
+ * (not a spring proxy, not an existing singleton target)
+ */
+ private static Object getSingletonTarget(Object candidate) {
+ try {
+ if (implementsInterface(candidate.getClass(), SPRING_ADVISED_CLASS_NAME)) {
+ Object targetSource = MethodUtils.invokeMethod(candidate, "getTargetSource");
+ if (implementsInterface(targetSource.getClass(), SPRING_SINGLETONTARGETSOURCE_CLASS_NAME)) {
+ return MethodUtils.invokeMethod(targetSource, "getTarget");
+ }
+ }
+ } catch (Throwable ignored) {
+ }
+
+ return null;
+ }
+
+ /**
* Check whether the specified class is a CGLIB-generated class.
* @param clazz the class to check
*/
@@ -81,7 +102,7 @@ public class ProxyUtil {
*/
private static boolean implementsInterface(Class<?> clazz, String ifaceClassName) {
try {
- Class ifaceClass = ClassLoaderUtil.loadClass(ifaceClassName, ProxyUtil.class);
+ Class<?> ifaceClass = ClassLoaderUtil.loadClass(ifaceClassName, ProxyUtil.class);
return ifaceClass.isAssignableFrom(clazz);
} catch (ClassNotFoundException e) {
return false;
http://git-wip-us.apache.org/repos/asf/struts/blob/8e9f9fb8/core/src/main/java/com/opensymphony/xwork2/util/reflection/ReflectionProvider.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/com/opensymphony/xwork2/util/reflection/ReflectionProvider.java b/core/src/main/java/com/opensymphony/xwork2/util/reflection/ReflectionProvider.java
index 029163e..72211ec 100644
--- a/core/src/main/java/com/opensymphony/xwork2/util/reflection/ReflectionProvider.java
+++ b/core/src/main/java/com/opensymphony/xwork2/util/reflection/ReflectionProvider.java
@@ -72,7 +72,23 @@ public interface ReflectionProvider {
* note if exclusions AND inclusions are supplied and not null nothing will get copied.
*/
void copy(Object from, Object to, Map<String, Object> context, Collection<String> exclusions, Collection<String> inclusions);
-
+
+ /**
+ * Copies the properties in the object "from" and sets them in the object "to"
+ * only setting properties defined in the given "editable" class (or interface)
+ * using specified type converter, or {@link com.opensymphony.xwork2.conversion.impl.XWorkConverter} if none
+ * is specified.
+ *
+ * @param from the source object
+ * @param to the target object
+ * @param context the action context we're running under
+ * @param exclusions collection of method names to excluded from copying ( can be null)
+ * @param inclusions collection of method names to included copying (can be null)
+ * note if exclusions AND inclusions are supplied and not null nothing will get copied.
+ * @param editable the class (or interface) to restrict property setting to
+ */
+ void copy(Object from, Object to, Map<String, Object> context, Collection<String> exclusions, Collection<String> inclusions, Class<?> editable);
+
/**
* Looks for the real target with the specified property given a root Object which may be a
* CompoundRoot.
http://git-wip-us.apache.org/repos/asf/struts/blob/8e9f9fb8/core/src/test/java/com/opensymphony/xwork2/ognl/OgnlUtilTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/com/opensymphony/xwork2/ognl/OgnlUtilTest.java b/core/src/test/java/com/opensymphony/xwork2/ognl/OgnlUtilTest.java
index a8bc7da..c0b0107 100644
--- a/core/src/test/java/com/opensymphony/xwork2/ognl/OgnlUtilTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/ognl/OgnlUtilTest.java
@@ -209,6 +209,32 @@ public class OgnlUtilTest extends XWorkTestCase {
}
+ public void testCopyEditable() {
+ Foo foo1 = new Foo();
+ Foo foo2 = new Foo();
+
+ Map<String, Object> context = ognlUtil.createDefaultContext(foo1);
+
+ Calendar cal = Calendar.getInstance();
+ cal.clear();
+ cal.set(Calendar.MONTH, Calendar.MAY);
+ cal.set(Calendar.DAY_OF_MONTH, 29);
+ cal.set(Calendar.YEAR, 2017);
+
+ foo1.setTitle("blah");
+ foo1.setNumber(1);
+ foo1.setPoints(new long[]{1, 2, 3});
+ foo1.setBirthday(cal.getTime());
+ foo1.setUseful(false);
+
+ ognlUtil.copy(foo1, foo2, context, null, null, Bar.class);
+
+ assertEquals(foo1.getTitle(), foo2.getTitle());
+ assertEquals(0, foo2.getNumber());
+ assertNull(foo2.getPoints());
+ assertNull(foo2.getBirthday());
+ }
+
public void testCopyUnevenObjects() {
Foo foo = new Foo();
http://git-wip-us.apache.org/repos/asf/struts/blob/8e9f9fb8/core/src/test/java/com/opensymphony/xwork2/spring/ActionsFromSpringTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/com/opensymphony/xwork2/spring/ActionsFromSpringTest.java b/core/src/test/java/com/opensymphony/xwork2/spring/ActionsFromSpringTest.java
index 4bbe429..f31a614 100644
--- a/core/src/test/java/com/opensymphony/xwork2/spring/ActionsFromSpringTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/spring/ActionsFromSpringTest.java
@@ -84,14 +84,20 @@ public class ActionsFromSpringTest extends XWorkTestCase {
proxy.execute();
- TestSubBean chaintoAOPedAction = (TestSubBean) appContext.getBean("pointcutted-test-sub-bean");
- TestSubBean aspectState = (TestSubBean) appContext.getBean("aspected-test-sub-bean");
+ // check if AOP works
+ TestAspect aspectState = (TestAspect) appContext.getBean("test-aspect");
+ // chainedAction.actionMethodName sets name then chainedAction.getCount sets count
+ // then chaintoAction.setCount sets count2 then chainedAction.getName sets name again
+ // then chaintoAction.actionMethodName sets issueId of the aspect object.
+ assertEquals("setName(WW-4105)-setCount(1)-setCount2(1)-setName(WW-4105)-setIssueId(WW-4105)-", aspectState.log);
+ assertEquals(aspectState.getName(), aspectState.getIssueId());
+ assertEquals("WW-4105", aspectState.getIssueId());
+ assertEquals(aspectState.getCount(), aspectState.getCount2());
+ assertEquals(1, aspectState.getCount());
- assertEquals(1, chaintoAOPedAction.getCount()); //check if chain
+ // check if chain works
+ TestSubBean chaintoAOPedAction = (TestSubBean) appContext.getBean("pointcutted-test-sub-bean");
+ assertEquals(1, chaintoAOPedAction.getCount());
assertEquals("WW-4105", chaintoAOPedAction.getName());
- assertNotNull(aspectState.getIssueId()); //and AOP proxied actions
- assertNotNull(aspectState.getName());
- assertEquals(aspectState.getName(), aspectState.getIssueId());
- assertEquals("WW-4105", aspectState.getIssueId()); //work together without any problem
}
}
http://git-wip-us.apache.org/repos/asf/struts/blob/8e9f9fb8/core/src/test/java/com/opensymphony/xwork2/spring/SpringProxyUtilTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/com/opensymphony/xwork2/spring/SpringProxyUtilTest.java b/core/src/test/java/com/opensymphony/xwork2/spring/SpringProxyUtilTest.java
index 9c047b8..7ae9883 100644
--- a/core/src/test/java/com/opensymphony/xwork2/spring/SpringProxyUtilTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/spring/SpringProxyUtilTest.java
@@ -53,33 +53,33 @@ public class SpringProxyUtilTest extends XWorkTestCase {
Object pointcuttedTestSubBean = appContext.getBean("pointcutted-test-sub-bean");
assertTrue(ProxyUtil.isSpringAopProxy(pointcuttedTestSubBean));
- Object aspectedTestSubBean = appContext.getBean("aspected-test-sub-bean");
- assertFalse(ProxyUtil.isSpringAopProxy(aspectedTestSubBean));
+ Object testAspect = appContext.getBean("test-aspect");
+ assertFalse(ProxyUtil.isSpringAopProxy(testAspect));
}
- public void testGetSpringUltimateTargetObject() throws Exception {
+ public void testSpringUltimateTargetClass() throws Exception {
Object simpleAction = appContext.getBean("simple-action");
- Object simpleActionUltimateTargetObject = ProxyUtil.getSpringUltimateTargetObject(simpleAction);
- assertEquals(simpleAction, simpleActionUltimateTargetObject);
+ Class<?> simpleActionUltimateTargetClass = ProxyUtil.springUltimateTargetClass(simpleAction);
+ assertEquals(SimpleAction.class, simpleActionUltimateTargetClass);
Object proxiedAction = appContext.getBean("proxied-action");
- Object proxiedActionUltimateTargetObject = ProxyUtil.getSpringUltimateTargetObject(proxiedAction);
- assertEquals(SimpleAction.class, proxiedActionUltimateTargetObject.getClass());
+ Class<?> proxiedActionUltimateTargetClass = ProxyUtil.springUltimateTargetClass(proxiedAction);
+ assertEquals(SimpleAction.class, proxiedActionUltimateTargetClass);
Object autoProxiedAction = appContext.getBean("auto-proxied-action");
- Object autoProxiedActionUltimateTargetObject = ProxyUtil.getSpringUltimateTargetObject(autoProxiedAction);
- assertEquals(SimpleAction.class, autoProxiedActionUltimateTargetObject.getClass());
+ Class<?> autoProxiedActionUltimateTargetClass = ProxyUtil.springUltimateTargetClass(autoProxiedAction);
+ assertEquals(SimpleAction.class, autoProxiedActionUltimateTargetClass);
Object pointcuttedTestBean = appContext.getBean("pointcutted-test-bean");
- Object pointcuttedTestBeanUltimateTargetObject = ProxyUtil.getSpringUltimateTargetObject(pointcuttedTestBean);
- assertEquals(TestBean.class, pointcuttedTestBeanUltimateTargetObject.getClass());
+ Class<?> pointcuttedTestBeanUltimateTargetClass = ProxyUtil.springUltimateTargetClass(pointcuttedTestBean);
+ assertEquals(TestBean.class, pointcuttedTestBeanUltimateTargetClass);
Object pointcuttedTestSubBean = appContext.getBean("pointcutted-test-sub-bean");
- Object pointcuttedTestSubBeanUltimateTargetObject = ProxyUtil.getSpringUltimateTargetObject(pointcuttedTestSubBean);
- assertEquals(TestSubBean.class, pointcuttedTestSubBeanUltimateTargetObject.getClass());
+ Class<?> pointcuttedTestSubBeanUltimateTargetClass = ProxyUtil.springUltimateTargetClass(pointcuttedTestSubBean);
+ assertEquals(TestSubBean.class, pointcuttedTestSubBeanUltimateTargetClass);
- Object aspectedTestSubBean = appContext.getBean("aspected-test-sub-bean");
- Object aspectedTestSubBeanUltimateTargetObject = ProxyUtil.getSpringUltimateTargetObject(aspectedTestSubBean);
- assertEquals(aspectedTestSubBean, aspectedTestSubBeanUltimateTargetObject);
+ Object testAspect = appContext.getBean("test-aspect");
+ Class<?> testAspectUltimateTargetClass = ProxyUtil.springUltimateTargetClass(testAspect);
+ assertEquals(TestAspect.class, testAspectUltimateTargetClass);
}
}
http://git-wip-us.apache.org/repos/asf/struts/blob/8e9f9fb8/core/src/test/java/com/opensymphony/xwork2/spring/TestAspect.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/com/opensymphony/xwork2/spring/TestAspect.java b/core/src/test/java/com/opensymphony/xwork2/spring/TestAspect.java
new file mode 100644
index 0000000..a428c65
--- /dev/null
+++ b/core/src/test/java/com/opensymphony/xwork2/spring/TestAspect.java
@@ -0,0 +1,46 @@
+package com.opensymphony.xwork2.spring;
+
+public class TestAspect {
+ protected String log = "";
+
+ private String issueId;
+ private int count;
+ private String name;
+ private int count2;
+
+ String getIssueId() {
+ return issueId;
+ }
+
+ public void setIssueId(String issueId) {
+ log = log + "setIssueId(" + issueId + ")-";
+ this.issueId = issueId;
+ }
+
+ public int getCount() {
+ return count;
+ }
+
+ public void setCount(int count) {
+ log = log + "setCount(" + count + ")-";
+ this.count = count;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ log = log + "setName(" + name + ")-";
+ this.name = name;
+ }
+
+ int getCount2() {
+ return count2;
+ }
+
+ public void setCount2(int count2) {
+ log = log + "setCount2(" + count2 + ")-";
+ this.count2 = count2;
+ }
+}
http://git-wip-us.apache.org/repos/asf/struts/blob/8e9f9fb8/core/src/test/resources/com/opensymphony/xwork2/spring/actionContext-spring.xml
----------------------------------------------------------------------
diff --git a/core/src/test/resources/com/opensymphony/xwork2/spring/actionContext-spring.xml b/core/src/test/resources/com/opensymphony/xwork2/spring/actionContext-spring.xml
index 5c18f6e..078107e 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/spring/actionContext-spring.xml
+++ b/core/src/test/resources/com/opensymphony/xwork2/spring/actionContext-spring.xml
@@ -51,17 +51,25 @@
<bean id="pointcutted-test-sub-bean" class="com.opensymphony.xwork2.TestSubBean">
<property name="issueId"><value>WW-4105</value></property>
</bean>
- <bean id="aspected-test-sub-bean" class="com.opensymphony.xwork2.TestSubBean" />
+ <bean id="test-aspect" class="com.opensymphony.xwork2.spring.TestAspect" />
<aop:config>
- <aop:aspect id="myAspect" ref="aspected-test-sub-bean">
+ <aop:aspect id="myAspect" ref="test-aspect">
<aop:pointcut id="testBeanGetName"
expression="execution(String com.opensymphony.xwork2.TestBean.getName()) and bean(pointcutted-test-bean)" />
<aop:after-returning pointcut-ref="testBeanGetName"
- method="setIssueId" returning="issueId" />
+ method="setName" returning="name" />
+ <aop:pointcut id="testBeanGetCount"
+ expression="execution(int com.opensymphony.xwork2.TestBean.getCount()) and bean(pointcutted-test-bean)" />
+ <aop:after-returning pointcut-ref="testBeanGetCount"
+ method="setCount" returning="count" />
<aop:pointcut id="testSubBeanGetIssueId"
expression="execution(String com.opensymphony.xwork2.TestSubBean.getIssueId()) and bean(pointcutted-test-sub-bean)" />
<aop:after-returning pointcut-ref="testSubBeanGetIssueId"
- method="setName" returning="name" />
+ method="setIssueId" returning="issueId" />
+ <aop:pointcut id="testBeanSetCount"
+ expression="execution(void com.opensymphony.xwork2.TestBean.setCount(int)) and args(count2) and bean(pointcutted-test-sub-bean)" />
+ <aop:before pointcut-ref="testBeanSetCount"
+ method="setCount2" arg-names="count2"/>
</aop:aspect>
</aop:config>
</beans>