Added RouterFactoryBean. MethodInvokingRouter now provides a constructor to accept the 'targetObject' only (without a method or methodName). It will resolve a single method annotated with @Router or else fallback to a single public method (INT-433, INT-434).

This commit is contained in:
Mark Fisher
2008-10-19 23:02:18 +00:00
parent f099083d66
commit 7f7fb10ae5
5 changed files with 176 additions and 4 deletions

View File

@@ -0,0 +1,73 @@
/*
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.config;
import org.springframework.integration.channel.ChannelResolver;
import org.springframework.integration.core.MessageChannel;
import org.springframework.integration.message.MessageConsumer;
import org.springframework.integration.router.AbstractMessageRouter;
import org.springframework.integration.router.MethodInvokingRouter;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* Factory bean for creating a Message Router.
*
* @author Mark Fisher
*/
public class RouterFactoryBean extends AbstractConsumerFactoryBean {
private volatile ChannelResolver channelResolver;
private volatile MessageChannel defaultOutputChannel;
public void setChannelResolver(ChannelResolver channelResolver) {
this.channelResolver = channelResolver;
}
public void setDefaultOutputChannel(MessageChannel defaultOutputChannel) {
this.defaultOutputChannel = defaultOutputChannel;
}
@Override
protected MessageConsumer createConsumer(Object targetObject, String targetMethodName) {
Assert.notNull(targetObject, "target object must not be null");
AbstractMessageRouter router = this.createRouter(targetObject, targetMethodName);
if (this.defaultOutputChannel != null) {
router.setDefaultOutputChannel(this.defaultOutputChannel);
}
return router;
}
private AbstractMessageRouter createRouter(Object targetObject, String targetMethodName) {
if (targetObject instanceof AbstractMessageRouter) {
Assert.isTrue(!StringUtils.hasText(targetMethodName),
"target method should not be provided when the target " +
"object is an implementation of AbstractMessageRouter");
return (AbstractMessageRouter) targetObject;
}
MethodInvokingRouter router = (StringUtils.hasText(targetMethodName))
? new MethodInvokingRouter(targetObject, targetMethodName)
: new MethodInvokingRouter(targetObject);
if (this.channelResolver != null) {
router.setChannelResolver(this.channelResolver);
}
return router;
}
}

View File

@@ -22,7 +22,7 @@ import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.integration.channel.BeanFactoryChannelResolver;
import org.springframework.integration.router.MethodInvokingRouter;
import org.springframework.integration.config.RouterFactoryBean;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@@ -37,11 +37,11 @@ public class RouterParser extends AbstractConsumerEndpointParser {
protected BeanDefinitionBuilder parseConsumer(Element element, ParserContext parserContext) {
String ref = element.getAttribute(REF_ATTRIBUTE);
Assert.hasText(ref, "The '" + REF_ATTRIBUTE + "' attribute is required.");
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MethodInvokingRouter.class);
builder.addConstructorArgReference(ref);
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(RouterFactoryBean.class);
builder.addPropertyReference("targetObject", ref);
if (StringUtils.hasText(element.getAttribute(METHOD_ATTRIBUTE))) {
String method = element.getAttribute(METHOD_ATTRIBUTE);
builder.addConstructorArgValue(method);
builder.addPropertyValue("targetMethodName", method);
}
BeanDefinitionBuilder resolverBuilder = BeanDefinitionBuilder.genericBeanDefinition(BeanFactoryChannelResolver.class);
String resolverBeanName = BeanDefinitionReaderUtils.registerWithGeneratedName(

View File

@@ -23,11 +23,14 @@ import java.util.Collection;
import java.util.List;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.integration.annotation.Router;
import org.springframework.integration.channel.ChannelResolver;
import org.springframework.integration.core.Message;
import org.springframework.integration.core.MessageChannel;
import org.springframework.integration.core.MessagingException;
import org.springframework.integration.message.MessageMappingMethodInvoker;
import org.springframework.integration.util.DefaultMethodResolver;
import org.springframework.integration.util.MethodResolver;
import org.springframework.util.Assert;
/**
@@ -41,6 +44,8 @@ import org.springframework.util.Assert;
*/
public class MethodInvokingRouter extends AbstractMessageRouter implements InitializingBean {
private final MethodResolver methodResolver = new DefaultMethodResolver(Router.class);
private final MessageMappingMethodInvoker invoker;
private volatile ChannelResolver channelResolver;
@@ -54,6 +59,14 @@ public class MethodInvokingRouter extends AbstractMessageRouter implements Initi
this.invoker = new MessageMappingMethodInvoker(object, methodName);
}
public MethodInvokingRouter(Object object) {
Assert.notNull(object, "object must not be null");
Method method = this.methodResolver.findMethod(object);
Assert.notNull(method, "unable to resolve Router method on target class ["
+ object.getClass() + "]");
this.invoker = new MessageMappingMethodInvoker(object, method);
}
/**
* Provide the {@link ChannelResolver} strategy to use for methods that