From ab35b61900aa4906d512a08c145b18ac9153697d Mon Sep 17 00:00:00 2001 From: dhgarrette Date: Tue, 10 Mar 2009 20:47:50 +0000 Subject: [PATCH] BATCH-1118: *Moved more logic from Job/StepListenerFactoryBean to AbstractListenerFactoryBean *Renamed AbstractListenerMetaData to ListenerMetaData --- .../listener/AbstractListenerFactoryBean.java | 67 +++++++++++++++---- .../core/listener/JobListenerFactoryBean.java | 52 ++------------ .../core/listener/JobListenerMetaData.java | 6 +- ...nerMetaData.java => ListenerMetaData.java} | 6 +- .../listener/StepListenerFactoryBean.java | 60 +++-------------- .../core/listener/StepListenerMetaData.java | 4 +- 6 files changed, 82 insertions(+), 113 deletions(-) rename spring-batch-core/src/main/java/org/springframework/batch/core/listener/{AbstractListenerMetaData.java => ListenerMetaData.java} (87%) 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 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 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 getListenerInterface() { + public Class getListenerInterface() { return listenerInterface; }