BATCH-1118:
*Moved more logic from Job/StepListenerFactoryBean to AbstractListenerFactoryBean *Renamed AbstractListenerMetaData to ListenerMetaData
This commit is contained in:
@@ -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;
|
||||
* <li>Interface implementation: By implementing any of the subclasses of a
|
||||
* listener interface, methods on said interface will be called
|
||||
* <li>Annotations: Annotating a method will result in registration.
|
||||
* <li>String name of the method to be called, which is tied to an
|
||||
* {@link AbstractListenerMetaData} in the metaDatMap.
|
||||
* <li>String name of the method to be called, which is tied to a
|
||||
* {@link ListenerMetaData} value in the metaDataMap.
|
||||
* </ul>
|
||||
*
|
||||
* 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<Class<?>> listenerInterfaces = new HashSet<Class<?>>();
|
||||
|
||||
// For every entry in the map, try and find a method by interface, name,
|
||||
// or annotation. If the same
|
||||
Map<String, Set<MethodInvoker>> invokerMap = new HashMap<String, Set<MethodInvoker>>();
|
||||
for (Entry<String, String> entry : metaDataMap.entrySet()) {
|
||||
final ListenerMetaData metaData = this.getMetaDataFromPropertyName(entry.getKey());
|
||||
Set<MethodInvoker> invokers = new NullIgnoringSet<MethodInvoker>();
|
||||
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<String, String> 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;
|
||||
}
|
||||
|
||||
@@ -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<String, String> metaDataMap) {
|
||||
|
||||
// For every entry in the map, try and find a method by interface, name,
|
||||
// or annotation. If the same
|
||||
Map<String, Set<MethodInvoker>> invokerMap = new HashMap<String, Set<MethodInvoker>>();
|
||||
for (Entry<String, String> entry : metaDataMap.entrySet()) {
|
||||
JobListenerMetaData metaData = JobListenerMetaData.fromPropertyName(entry.getKey());
|
||||
Set<MethodInvoker> invokers = new NullIgnoringSet<MethodInvoker>();
|
||||
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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
@@ -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<String, String> metaDataMap) {
|
||||
|
||||
Set<Class<?>> listenerInterfaces = new HashSet<Class<?>>();
|
||||
|
||||
// For every entry in the map, try and find a method by interface, name,
|
||||
// or annotation. If the same
|
||||
Map<String, Set<MethodInvoker>> invokerMap = new HashMap<String, Set<MethodInvoker>>();
|
||||
for (Entry<String, String> entry : metaDataMap.entrySet()) {
|
||||
final StepListenerMetaData metaData = StepListenerMetaData.fromPropertyName(entry.getKey());
|
||||
Set<MethodInvoker> invokers = new NullIgnoringSet<MethodInvoker>();
|
||||
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());
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user