Refactored PublisherAnnotationBeanPostProcessor to implement BeanClassLoaderAware and to use AopUtils.canApply() since the advisor is a pointcut-advisor.

This commit is contained in:
Mark Fisher
2009-10-10 19:21:27 +00:00
parent 3767fddb33
commit 611b2fc325
5 changed files with 92 additions and 76 deletions

View File

@@ -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;
}
}
}

View File

@@ -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">
<bean id="testBean"
class="org.springframework.integration.aop.MessagePublishingAnnotationUsageTest$TestBean" />
class="org.springframework.integration.aop.MessagePublishingAnnotationUsageTests$TestBean" />
<si:channel id="testChannel">
<si:queue />

View File

@@ -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;
}
}
}

View File

@@ -8,7 +8,7 @@
xmlns:si="http://www.springframework.org/schema/integration">
<bean id="testBean"
class="org.springframework.integration.aop.MessagePublishingInterceptorUsageTest$TestBean" />
class="org.springframework.integration.aop.MessagePublishingInterceptorUsageTests$TestBean" />
<si:channel id="testChannel">
<si:queue />

View File

@@ -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;
}
}
}