diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/AbstractListenerFactoryBean.java b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/AbstractListenerFactoryBean.java
index ae797c384..a61f1ded6 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/AbstractListenerFactoryBean.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/AbstractListenerFactoryBean.java
@@ -15,6 +15,7 @@
*/
package org.springframework.batch.core.listener;
+import static org.springframework.batch.support.MethodInvokerUtils.getMethodInvokerForInterface;
import static org.springframework.batch.support.MethodInvokerUtils.getParamTypesString;
import java.lang.annotation.Annotation;
@@ -22,14 +23,19 @@ import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
+import java.util.Set;
+import java.util.Map.Entry;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.aop.framework.Advised;
+import org.springframework.aop.framework.ProxyFactory;
+import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.batch.support.MethodInvoker;
import org.springframework.batch.support.MethodInvokerUtils;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
+import org.springframework.core.Ordered;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
@@ -43,8 +49,8 @@ import org.springframework.util.ReflectionUtils;
*
Interface implementation: By implementing any of the subclasses of a
* listener interface, methods on said interface will be called
* Annotations: Annotating a method will result in registration.
- * String name of the method to be called, which is tied to an
- * {@link AbstractListenerMetaData} in the metaDatMap.
+ * String name of the method to be called, which is tied to a
+ * {@link ListenerMetaData} value in the metaDataMap.
*
*
* It should be noted that methods obtained by name or annotation that don't
@@ -59,11 +65,11 @@ import org.springframework.util.ReflectionUtils;
* @author Lucas Ward
* @author Dan Garrette
* @since 2.0
- * @see StepListenerMetaData
+ * @see ListenerMetaData
*/
public abstract class AbstractListenerFactoryBean implements FactoryBean, InitializingBean {
- private static Log logger = LogFactory.getLog(StepListenerFactoryBean.class);
+ private static Log logger = LogFactory.getLog(AbstractListenerFactoryBean.class);
private Object delegate;
@@ -77,19 +83,56 @@ public abstract class AbstractListenerFactoryBean implements FactoryBean, Initia
// Because all annotations and interfaces should be checked for, make
// sure that each meta data
// entry is represented.
- for (AbstractListenerMetaData metaData : this.getMetaDataValues()) {
+ for (ListenerMetaData metaData : this.getMetaDataValues()) {
if (!metaDataMap.containsKey(metaData.getPropertyName())) {
// put null so that the annotation and interface is checked
metaDataMap.put(metaData.getPropertyName(), null);
}
}
- return this.doGetObject(delegate, metaDataMap);
+ Set> listenerInterfaces = new HashSet>();
+
+ // For every entry in the map, try and find a method by interface, name,
+ // or annotation. If the same
+ Map> invokerMap = new HashMap>();
+ for (Entry entry : metaDataMap.entrySet()) {
+ final ListenerMetaData metaData = this.getMetaDataFromPropertyName(entry.getKey());
+ Set invokers = new NullIgnoringSet();
+ invokers.add(getMethodInvokerByName(entry.getValue(), delegate, metaData.getParamTypes()));
+ invokers.add(getMethodInvokerForInterface(metaData.getListenerInterface(), metaData.getMethodName(),
+ delegate, metaData.getParamTypes()));
+ invokers.add(getMethodInvokerByAnnotation(metaData));
+ if (!invokers.isEmpty()) {
+ invokerMap.put(metaData.getMethodName(), invokers);
+ listenerInterfaces.add(metaData.getListenerInterface());
+ }
+ }
+
+ if (listenerInterfaces.isEmpty()) {
+ listenerInterfaces.add(this.getDefaultListenerClass());
+ }
+
+ boolean ordered = false;
+ if (delegate instanceof Ordered) {
+ ordered = true;
+ listenerInterfaces.add(Ordered.class);
+ }
+
+ // create a proxy listener for only the interfaces that have methods to
+ // be called
+ ProxyFactory proxyFactory = new ProxyFactory();
+ proxyFactory.setTarget(delegate);
+ proxyFactory.setInterfaces(listenerInterfaces.toArray(new Class[0]));
+ proxyFactory.addAdvisor(new DefaultPointcutAdvisor(new MethodInvokerMethodInterceptor(invokerMap, ordered)));
+ return proxyFactory.getProxy();
+
}
- protected abstract Object doGetObject(Object delegate, Map metaDataMap);
-
- protected abstract AbstractListenerMetaData[] getMetaDataValues();
+ protected abstract ListenerMetaData getMetaDataFromPropertyName(String propertyName);
+
+ protected abstract ListenerMetaData[] getMetaDataValues();
+
+ protected abstract Class> getDefaultListenerClass();
/**
* Create a MethodInvoker from the delegate based on the annotationType.
@@ -98,7 +141,7 @@ public abstract class AbstractListenerFactoryBean implements FactoryBean, Initia
* @param metaData
* @return a MethodInvoker
*/
- protected MethodInvoker getMethodInvokerByAnnotation(final AbstractListenerMetaData metaData) {
+ protected MethodInvoker getMethodInvokerByAnnotation(final ListenerMetaData metaData) {
final Class extends Annotation> annotationType = metaData.getAnnotation();
MethodInvoker mi = MethodInvokerUtils.getMethodInvokerByAnnotation(annotationType, delegate);
if (mi != null) {
@@ -186,7 +229,7 @@ public abstract class AbstractListenerFactoryBean implements FactoryBean, Initia
* @return true if the delegate is an instance of any of the listener
* interface, or contains the marker annotations
*/
- public static boolean isListener(Object delegate, Class> listenerType, AbstractListenerMetaData[] metaDataValues) {
+ public static boolean isListener(Object delegate, Class> listenerType, ListenerMetaData[] metaDataValues) {
if (listenerType.isInstance(delegate)) {
return true;
}
@@ -198,7 +241,7 @@ public abstract class AbstractListenerFactoryBean implements FactoryBean, Initia
return false;
}
}
- for (AbstractListenerMetaData metaData : metaDataValues) {
+ for (ListenerMetaData metaData : metaDataValues) {
if (MethodInvokerUtils.getMethodInvokerByAnnotation(metaData.getAnnotation(), delegate) != null) {
return true;
}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/JobListenerFactoryBean.java b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/JobListenerFactoryBean.java
index d7f4a83e1..6393a58df 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/JobListenerFactoryBean.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/JobListenerFactoryBean.java
@@ -15,20 +15,7 @@
*/
package org.springframework.batch.core.listener;
-import static org.springframework.batch.support.MethodInvokerUtils.getMethodInvokerForInterface;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-import java.util.Map.Entry;
-
-import org.springframework.aop.framework.ProxyFactory;
-import org.springframework.aop.support.DefaultPointcutAdvisor;
-import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobExecutionListener;
-import org.springframework.batch.support.MethodInvoker;
-import org.springframework.core.Ordered;
-import org.springframework.batch.core.listener.MethodInvokerMethodInterceptor;
/**
* This {@link AbstractListenerFactoryBean} implementation is used to create a
@@ -42,43 +29,18 @@ import org.springframework.batch.core.listener.MethodInvokerMethodInterceptor;
*/
public class JobListenerFactoryBean extends AbstractListenerFactoryBean {
- public Object doGetObject(Object delegate, Map metaDataMap) {
-
- // For every entry in the map, try and find a method by interface, name,
- // or annotation. If the same
- Map> invokerMap = new HashMap>();
- for (Entry entry : metaDataMap.entrySet()) {
- JobListenerMetaData metaData = JobListenerMetaData.fromPropertyName(entry.getKey());
- Set invokers = new NullIgnoringSet();
- invokers.add(getMethodInvokerByName(entry.getValue(), delegate, metaData.getParamTypes()));
- invokers.add(getMethodInvokerForInterface(JobExecutionListener.class, metaData.getMethodName(), delegate,
- JobExecution.class));
- invokers.add(getMethodInvokerByAnnotation(metaData));
- if (!invokers.isEmpty()) {
- invokerMap.put(metaData.getMethodName(), invokers);
- }
- }
-
- // create a proxy listener for only the interfaces that have methods to
- // be called
- ProxyFactory proxyFactory = new ProxyFactory();
- proxyFactory.setTarget(delegate);
-
- boolean ordered = false;
- if (delegate instanceof Ordered) {
- ordered = true;
- proxyFactory.addInterface(Ordered.class);
- }
-
- proxyFactory.addInterface(JobExecutionListener.class);
- proxyFactory.addAdvisor(new DefaultPointcutAdvisor(new MethodInvokerMethodInterceptor(invokerMap, ordered)));
- return proxyFactory.getProxy();
+ protected ListenerMetaData getMetaDataFromPropertyName(String propertyName) {
+ return JobListenerMetaData.fromPropertyName(propertyName);
}
- protected AbstractListenerMetaData[] getMetaDataValues() {
+ protected ListenerMetaData[] getMetaDataValues() {
return JobListenerMetaData.values();
}
+ protected Class> getDefaultListenerClass() {
+ return JobExecutionListener.class;
+ }
+
@SuppressWarnings("unchecked")
public Class getObjectType() {
return JobExecutionListener.class;
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/JobListenerMetaData.java b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/JobListenerMetaData.java
index dfb1645ec..078faccf1 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/JobListenerMetaData.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/JobListenerMetaData.java
@@ -32,7 +32,7 @@ import org.springframework.batch.core.annotation.BeforeJob;
* @since 2.0
* @see JobListenerFactoryBean
*/
-public enum JobListenerMetaData implements AbstractListenerMetaData {
+public enum JobListenerMetaData implements ListenerMetaData {
BEFORE_JOB("beforeJob", "before-job-method", BeforeJob.class),
AFTER_JOB("afterJob", "after-job-method", AfterJob.class);
@@ -64,6 +64,10 @@ public enum JobListenerMetaData implements AbstractListenerMetaData {
return annotation;
}
+ public Class> getListenerInterface() {
+ return JobExecutionListener.class;
+ }
+
public String getPropertyName() {
return propertyName;
}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/AbstractListenerMetaData.java b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/ListenerMetaData.java
similarity index 87%
rename from spring-batch-core/src/main/java/org/springframework/batch/core/listener/AbstractListenerMetaData.java
rename to spring-batch-core/src/main/java/org/springframework/batch/core/listener/ListenerMetaData.java
index 359a89359..73e80600a 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/AbstractListenerMetaData.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/ListenerMetaData.java
@@ -18,19 +18,21 @@ package org.springframework.batch.core.listener;
import java.lang.annotation.Annotation;
/**
- * A common interface for ListenerMetaData enumerations.
+ * A common interface for listener meta data enumerations.
*
* @author Dan Garrette
* @since 2.0
* @see JobListenerMetaData
* @see StepListenerMetaData
*/
-public interface AbstractListenerMetaData {
+public interface ListenerMetaData {
public String getMethodName();
public Class extends Annotation> getAnnotation();
+ public Class> getListenerInterface();
+
public String getPropertyName();
public Class>[] getParamTypes();
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/StepListenerFactoryBean.java b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/StepListenerFactoryBean.java
index f4724ff83..70faaee48 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/StepListenerFactoryBean.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/StepListenerFactoryBean.java
@@ -15,19 +15,7 @@
*/
package org.springframework.batch.core.listener;
-import static org.springframework.batch.support.MethodInvokerUtils.getMethodInvokerForInterface;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.Map.Entry;
-
-import org.springframework.aop.framework.ProxyFactory;
-import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.batch.core.StepListener;
-import org.springframework.batch.support.MethodInvoker;
-import org.springframework.core.Ordered;
/**
* This {@link AbstractListenerFactoryBean} implementation is used to create a
@@ -41,49 +29,18 @@ import org.springframework.core.Ordered;
*/
public class StepListenerFactoryBean extends AbstractListenerFactoryBean {
- public Object doGetObject(Object delegate, Map metaDataMap) {
-
- Set> listenerInterfaces = new HashSet>();
-
- // For every entry in the map, try and find a method by interface, name,
- // or annotation. If the same
- Map> invokerMap = new HashMap>();
- for (Entry entry : metaDataMap.entrySet()) {
- final StepListenerMetaData metaData = StepListenerMetaData.fromPropertyName(entry.getKey());
- Set invokers = new NullIgnoringSet();
- invokers.add(getMethodInvokerByName(entry.getValue(), delegate, metaData.getParamTypes()));
- invokers.add(getMethodInvokerForInterface(metaData.getListenerInterface(), metaData.getMethodName(),
- delegate, metaData.getParamTypes()));
- invokers.add(getMethodInvokerByAnnotation(metaData));
- if (!invokers.isEmpty()) {
- invokerMap.put(metaData.getMethodName(), invokers);
- listenerInterfaces.add(metaData.getListenerInterface());
- }
- }
-
- if (listenerInterfaces.isEmpty()) {
- listenerInterfaces.add(StepListener.class);
- }
-
- boolean ordered = false;
- if (delegate instanceof Ordered) {
- ordered = true;
- listenerInterfaces.add(Ordered.class);
- }
-
- // create a proxy listener for only the interfaces that have methods to
- // be called
- ProxyFactory proxyFactory = new ProxyFactory();
- proxyFactory.setTarget(delegate);
- proxyFactory.setInterfaces(listenerInterfaces.toArray(new Class[0]));
- proxyFactory.addAdvisor(new DefaultPointcutAdvisor(new MethodInvokerMethodInterceptor(invokerMap, ordered)));
- return proxyFactory.getProxy();
+ protected ListenerMetaData getMetaDataFromPropertyName(String propertyName) {
+ return StepListenerMetaData.fromPropertyName(propertyName);
}
- protected AbstractListenerMetaData[] getMetaDataValues() {
+ protected ListenerMetaData[] getMetaDataValues() {
return StepListenerMetaData.values();
}
+ protected Class> getDefaultListenerClass() {
+ return StepListener.class;
+ }
+
@SuppressWarnings("unchecked")
public Class getObjectType() {
return StepListener.class;
@@ -108,7 +65,8 @@ public class StepListenerFactoryBean extends AbstractListenerFactoryBean {
*
* @param delegate the object to check
* @return true if the delegate is an instance of any of the
- * {@link StepListener} interfaces, or contains the marker annotations
+ * {@link StepListener} interfaces, or contains the marker
+ * annotations
*/
public static boolean isListener(Object delegate) {
return AbstractListenerFactoryBean.isListener(delegate, StepListener.class, StepListenerMetaData.values());
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/StepListenerMetaData.java b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/StepListenerMetaData.java
index 1acc5683f..0f17510bc 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/StepListenerMetaData.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/StepListenerMetaData.java
@@ -53,7 +53,7 @@ import org.springframework.batch.core.annotation.OnWriteError;
* @since 2.0
* @see StepListenerFactoryBean
*/
-public enum StepListenerMetaData implements AbstractListenerMetaData {
+public enum StepListenerMetaData implements ListenerMetaData {
BEFORE_STEP("beforeStep", "before-step-method", BeforeStep.class, StepExecutionListener.class, StepExecution.class),
AFTER_STEP("afterStep", "after-step-method", AfterStep.class, StepExecutionListener.class, StepExecution.class),
@@ -103,7 +103,7 @@ public enum StepListenerMetaData implements AbstractListenerMetaData {
return annotation;
}
- public Class extends StepListener> getListenerInterface() {
+ public Class> getListenerInterface() {
return listenerInterface;
}