diff --git a/org.springframework.integration/src/main/java/org/springframework/integration/aop/PublisherAnnotationBeanPostProcessor.java b/org.springframework.integration/src/main/java/org/springframework/integration/aop/PublisherAnnotationBeanPostProcessor.java index 503dd5dce9..8f0a18482e 100644 --- a/org.springframework.integration/src/main/java/org/springframework/integration/aop/PublisherAnnotationBeanPostProcessor.java +++ b/org.springframework.integration/src/main/java/org/springframework/integration/aop/PublisherAnnotationBeanPostProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-2009 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. @@ -13,96 +13,101 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.integration.aop; -import java.lang.annotation.Annotation; -import java.lang.reflect.Method; - +import org.springframework.aop.framework.Advised; +import org.springframework.aop.framework.ProxyConfig; import org.springframework.aop.framework.ProxyFactory; +import org.springframework.aop.support.AopUtils; import org.springframework.beans.BeansException; +import org.springframework.beans.factory.BeanClassLoaderAware; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.config.BeanPostProcessor; -import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.core.Ordered; import org.springframework.integration.core.MessageChannel; +import org.springframework.util.ClassUtils; /** - * Will post process beans that contain @{@link Publisher} annotation. + * Post-processes beans that contain the method-level @{@link Publisher} annotation. * * @author Oleg Zhurakousky + * @author Mark Fisher * @since 2.0 - * */ -public class PublisherAnnotationBeanPostProcessor implements BeanPostProcessor, BeanFactoryAware, InitializingBean { +public class PublisherAnnotationBeanPostProcessor extends ProxyConfig + implements BeanPostProcessor, BeanClassLoaderAware, BeanFactoryAware, InitializingBean, Ordered { + + private volatile MessageChannel defaultChannel; + + private volatile PublisherAnnotationAdvisor advisor; + + private volatile int order = Ordered.LOWEST_PRECEDENCE; + + private volatile BeanFactory beanFactory; + + private volatile ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader(); + - private BeanFactory beanFactory; - private MessageChannel defaultChannel; - private PublisherAnnotationAdvisor advisor; /** - * + * Set the default channel where Messages should be sent if the annotation + * itself does not provide a channel. */ - public PublisherAnnotationBeanPostProcessor(){} - /** - * - * @param defaultChannel - */ - public PublisherAnnotationBeanPostProcessor(MessageChannel defaultChannel){ + public void setDefaultChannel(MessageChannel defaultChannel){ this.defaultChannel = defaultChannel; } - /** - * - */ - public Object postProcessAfterInitialization(Object bean, String beanName) - throws BeansException { - if (this.containsPublisherAnnotations(bean)){ - ProxyFactory pf = new ProxyFactory(bean); - pf.addAdvisor(advisor); - bean = pf.getProxy(); - } - return bean; - } - /** - * - */ - public Object postProcessBeforeInitialization(Object bean, String beanName) - throws BeansException { - return bean; - } - /** - * - * @return - */ - public BeanFactory getBeanFactory() { - return beanFactory; - } - /** - * - */ + public void setBeanFactory(BeanFactory beanFactory) { this.beanFactory = beanFactory; } - /** - * - */ + + public void setBeanClassLoader(ClassLoader classLoader) { + this.beanClassLoader = classLoader; + } + + public void setOrder(int order) { + this.order = order; + } + + public int getOrder() { + return this.order; + } + public void afterPropertiesSet(){ advisor = new PublisherAnnotationAdvisor(); advisor.setBeanFactory(beanFactory); advisor.setDefaultChannel(defaultChannel); } - /** - * - * @param bean - * @return - */ - private boolean containsPublisherAnnotations(Object bean){ - Method[] methods = bean.getClass().getMethods(); - for (Method method : methods) { - Annotation publisher = AnnotationUtils.findAnnotation(method, Publisher.class); - if (publisher != null){ - return true; + + public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { + return bean; + } + + public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { + Class targetClass = AopUtils.getTargetClass(bean); + if (targetClass == null) { + return bean; + } + + if (AopUtils.canApply(this.advisor, targetClass)) { + if (bean instanceof Advised) { + ((Advised) bean).addAdvisor(this.advisor); + return bean; + } + else { + ProxyFactory proxyFactory = new ProxyFactory(bean); + // Copy our properties (proxyTargetClass etc) inherited from ProxyConfig. + proxyFactory.copyFrom(this); + proxyFactory.addAdvisor(this.advisor); + return proxyFactory.getProxy(this.beanClassLoader); } } - return false; + else { + // cannot apply advisor + return bean; + } } + } diff --git a/org.springframework.integration/src/test/java/org/springframework/integration/aop/MessagePublishingAnnotationUsageTest-context.xml b/org.springframework.integration/src/test/java/org/springframework/integration/aop/MessagePublishingAnnotationUsageTests-context.xml similarity index 96% rename from org.springframework.integration/src/test/java/org/springframework/integration/aop/MessagePublishingAnnotationUsageTest-context.xml rename to org.springframework.integration/src/test/java/org/springframework/integration/aop/MessagePublishingAnnotationUsageTests-context.xml index 9deece9d0c..b02bc7f49f 100644 --- a/org.springframework.integration/src/test/java/org/springframework/integration/aop/MessagePublishingAnnotationUsageTest-context.xml +++ b/org.springframework.integration/src/test/java/org/springframework/integration/aop/MessagePublishingAnnotationUsageTests-context.xml @@ -6,9 +6,9 @@ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd" xmlns:si="http://www.springframework.org/schema/integration"> - + + class="org.springframework.integration.aop.MessagePublishingAnnotationUsageTests$TestBean" /> diff --git a/org.springframework.integration/src/test/java/org/springframework/integration/aop/MessagePublishingAnnotationUsageTest.java b/org.springframework.integration/src/test/java/org/springframework/integration/aop/MessagePublishingAnnotationUsageTests.java similarity index 87% rename from org.springframework.integration/src/test/java/org/springframework/integration/aop/MessagePublishingAnnotationUsageTest.java rename to org.springframework.integration/src/test/java/org/springframework/integration/aop/MessagePublishingAnnotationUsageTests.java index 52abdf2058..db5df2b0a6 100644 --- a/org.springframework.integration/src/test/java/org/springframework/integration/aop/MessagePublishingAnnotationUsageTest.java +++ b/org.springframework.integration/src/test/java/org/springframework/integration/aop/MessagePublishingAnnotationUsageTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-2009 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. @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.integration.aop; import junit.framework.Assert; @@ -31,26 +32,31 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; */ @ContextConfiguration @RunWith(SpringJUnit4ClassRunner.class) -public class MessagePublishingAnnotationUsageTest { +public class MessagePublishingAnnotationUsageTests { + @Autowired private TestBean testBean; + @Autowired private QueueChannel channel; + @Test - public void demoMessagePublishingInterceptor(){ + public void demoMessagePublishingInterceptor() { String name = testBean.setName("John", "Doe"); Assert.assertNotNull(name); - Message message = channel.receive(); + Message message = channel.receive(1000); Assert.assertNotNull(message); Assert.assertEquals("John Doe", message.getPayload()); Assert.assertEquals("123", message.getHeaders().get("bar")); } - public static class TestBean{ + public static class TestBean { + @Publisher(value="#return", channel="testChannel", headers="bar='123'") public String setName(String fname, String lname){ return fname + " " + lname; } } + } diff --git a/org.springframework.integration/src/test/java/org/springframework/integration/aop/MessagePublishingInterceptorUsageTest-context.xml b/org.springframework.integration/src/test/java/org/springframework/integration/aop/MessagePublishingInterceptorUsageTests-context.xml similarity index 98% rename from org.springframework.integration/src/test/java/org/springframework/integration/aop/MessagePublishingInterceptorUsageTest-context.xml rename to org.springframework.integration/src/test/java/org/springframework/integration/aop/MessagePublishingInterceptorUsageTests-context.xml index e8b36ef8de..e92249b89e 100644 --- a/org.springframework.integration/src/test/java/org/springframework/integration/aop/MessagePublishingInterceptorUsageTest-context.xml +++ b/org.springframework.integration/src/test/java/org/springframework/integration/aop/MessagePublishingInterceptorUsageTests-context.xml @@ -8,7 +8,7 @@ xmlns:si="http://www.springframework.org/schema/integration"> + class="org.springframework.integration.aop.MessagePublishingInterceptorUsageTests$TestBean" /> diff --git a/org.springframework.integration/src/test/java/org/springframework/integration/aop/MessagePublishingInterceptorUsageTest.java b/org.springframework.integration/src/test/java/org/springframework/integration/aop/MessagePublishingInterceptorUsageTests.java similarity index 89% rename from org.springframework.integration/src/test/java/org/springframework/integration/aop/MessagePublishingInterceptorUsageTest.java rename to org.springframework.integration/src/test/java/org/springframework/integration/aop/MessagePublishingInterceptorUsageTests.java index 9d921dca00..d1eecc24e1 100644 --- a/org.springframework.integration/src/test/java/org/springframework/integration/aop/MessagePublishingInterceptorUsageTest.java +++ b/org.springframework.integration/src/test/java/org/springframework/integration/aop/MessagePublishingInterceptorUsageTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-2009 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. @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.integration.aop; import junit.framework.Assert; @@ -28,29 +29,33 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** * @author Oleg Zhurakousky * @since 2.0 - * */ @ContextConfiguration @RunWith(SpringJUnit4ClassRunner.class) -public class MessagePublishingInterceptorUsageTest { +public class MessagePublishingInterceptorUsageTests { + @Autowired private TestBean testBean; + @Autowired private QueueChannel channel; + @Test public void demoMessagePublishingInterceptor(){ String name = testBean.setName("John", "Doe"); Assert.assertNotNull(name); - Message message = channel.receive(); + Message message = channel.receive(1000); Assert.assertNotNull(message); Assert.assertEquals("John Doe", message.getPayload()); Assert.assertEquals("bar", message.getHeaders().get("foo")); } - - public static class TestBean{ + + public static class TestBean { + public String setName(String fname, String lname){ return fname + " " + lname; } } + }