diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepListenerParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepListenerParserTests.java index b9a199c1c..c8a873112 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepListenerParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepListenerParserTests.java @@ -67,7 +67,7 @@ public class StepListenerParserTests { } @Test - public void testInheritListeners_NoMerge() throws Exception { + public void testInheritListenersNoMerge() throws Exception { ConfigurableApplicationContext ctx = new ClassPathXmlApplicationContext( "org/springframework/batch/core/configuration/xml/StepListenerParserTests-context.xml"); List list = getListeners("s2", ctx); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/listener/StepListenerFactoryBeanTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/listener/StepListenerFactoryBeanTests.java index 31de6f3a1..e868d8832 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/listener/StepListenerFactoryBeanTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/listener/StepListenerFactoryBeanTests.java @@ -241,7 +241,9 @@ public class StepListenerFactoryBeanTests { } }; ProxyFactory factory = new ProxyFactory(delegate); - assertTrue(StepListenerFactoryBean.isListener(factory.getProxy())); + Object proxy = factory.getProxy(); + assertTrue(StepListenerFactoryBean.isListener(proxy)); + ((StepExecutionListener) StepListenerFactoryBean.getListener(proxy)).beforeStep(null); } @Test diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/SimpleMethodInvoker.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/SimpleMethodInvoker.java index 8d4ec66e6..e23766710 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/SimpleMethodInvoker.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/SimpleMethodInvoker.java @@ -35,13 +35,15 @@ import java.lang.reflect.Method; import java.util.Arrays; import org.apache.commons.lang.builder.HashCodeBuilder; +import org.springframework.aop.framework.Advised; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; /** - * Simple implementation of the {@link MethodInvoker} interface that invokes a method on an - * object. If the method has no arguments, but arguments are provided, they are ignored and the method - * is invoked anyway. If there are more arguments than there are provided, then an exception is thrown. + * Simple implementation of the {@link MethodInvoker} interface that invokes a + * method on an object. If the method has no arguments, but arguments are + * provided, they are ignored and the method is invoked anyway. If there are + * more arguments than there are provided, then an exception is thrown. * * @author Lucas Ward * @since 2.0 @@ -49,69 +51,98 @@ import org.springframework.util.ClassUtils; public class SimpleMethodInvoker implements MethodInvoker { private final Object object; + private Method method; - + public SimpleMethodInvoker(Object object, Method method) { Assert.notNull(object, "Object to invoke must not be null"); Assert.notNull(method, "Method to invoke must not be null"); - this.object = object; this.method = method; - } - - public SimpleMethodInvoker(Object object, String methodName, Class... paramTypes){ - Assert.notNull(object, "Object to invoke must not be null"); this.object = object; - this.method = ClassUtils.getMethodIfAvailable(object.getClass(), methodName, paramTypes); - if(this.method == null){ - //try with no params - this.method = ClassUtils.getMethodIfAvailable(object.getClass(), methodName, new Class[]{}); - } - if(this.method == null){ - throw new IllegalArgumentException("No methods found for name: [" + methodName + "] in class: [" + - object.getClass() + "] with arguments of type: [" + Arrays.toString(paramTypes) + "]"); - } } - - /* (non-Javadoc) - * @see org.springframework.batch.core.configuration.util.MethodInvoker#invokeMethod(java.lang.Object[]) + + public SimpleMethodInvoker(Object object, String methodName, Class... paramTypes) { + Assert.notNull(object, "Object to invoke must not be null"); + this.method = ClassUtils.getMethodIfAvailable(object.getClass(), methodName, paramTypes); + if (this.method == null) { + // try with no params + this.method = ClassUtils.getMethodIfAvailable(object.getClass(), methodName, new Class[] {}); + } + if (this.method == null) { + throw new IllegalArgumentException("No methods found for name: [" + methodName + "] in class: [" + + object.getClass() + "] with arguments of type: [" + Arrays.toString(paramTypes) + "]"); + } + this.object = object; + } + + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.core.configuration.util.MethodInvoker#invokeMethod + * (java.lang.Object[]) */ public Object invokeMethod(Object... args) { - + Class[] parameterTypes = method.getParameterTypes(); Object[] invokeArgs; - if(parameterTypes.length == 0){ - invokeArgs = new Object[]{}; + if (parameterTypes.length == 0) { + invokeArgs = new Object[] {}; } - else if(parameterTypes.length != args.length){ - throw new IllegalArgumentException("Wrong number of arguments, expected no more than: [" + parameterTypes.length + "]"); + else if (parameterTypes.length != args.length) { + throw new IllegalArgumentException("Wrong number of arguments, expected no more than: [" + + parameterTypes.length + "]"); } - else{ + else { invokeArgs = args; } - + method.setAccessible(true); - + try { - return method.invoke(object, invokeArgs); - } catch (Exception e) { - throw new IllegalArgumentException("Unable to invoke method: [" + method + "] on object: [" + - object + "] with arguments: [" + Arrays.toString(args) + "]", e); - } + // Extract the target from an Advised as late as possible + // in case it contains a lazy initialization + Object target = extractTarget(object, method); + return method.invoke(target, invokeArgs); + } + catch (Exception e) { + throw new IllegalArgumentException("Unable to invoke method: [" + method + "] on object: [" + object + + "] with arguments: [" + Arrays.toString(args) + "]", e); + } } - + + private Object extractTarget(Object target, Method method) { + if (target instanceof Advised) { + Object source; + try { + source = ((Advised) target).getTargetSource().getTarget(); + } + catch (Exception e) { + throw new IllegalStateException("Could not extract target from proxy", e); + } + if (source instanceof Advised) { + source = extractTarget(source, method); + } + if (method.getDeclaringClass().isAssignableFrom(source.getClass())) { + target = source; + } + } + return target; + } + @Override public boolean equals(Object obj) { - if(!(obj instanceof SimpleMethodInvoker)){ + if (!(obj instanceof SimpleMethodInvoker)) { return false; } - - if(obj == this){ + + if (obj == this) { return true; } SimpleMethodInvoker rhs = (SimpleMethodInvoker) obj; return (rhs.method.equals(this.method)) && (rhs.object.equals(this.object)); } - + @Override public int hashCode() { return new HashCodeBuilder(25, 37).append(object.hashCode()).append(method.hashCode()).toHashCode(); diff --git a/spring-batch-samples/src/main/resources/jobs/partitionJob.xml b/spring-batch-samples/src/main/resources/jobs/partitionJob.xml index a91bcf92c..a3d46571c 100644 --- a/spring-batch-samples/src/main/resources/jobs/partitionJob.xml +++ b/spring-batch-samples/src/main/resources/jobs/partitionJob.xml @@ -45,7 +45,7 @@ - +