Skip to content

Instantly share code, notes, and snippets.

@garyrussell
Last active December 16, 2015 03:59
Show Gist options
  • Save garyrussell/5374267 to your computer and use it in GitHub Desktop.
Save garyrussell/5374267 to your computer and use it in GitHub Desktop.
BeanPostProcessor To Apply a Handler Advice
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<int:channel id="input">
<int:queue/>
</int:channel>
<int:channel id="output">
<int:queue/>
</int:channel>
<int:service-activator id="myService" input-channel="input" output-channel="output">
<bean class="org.springframework.integration.aop.AdvisePolledFlow$Service" />
<int:poller fixed-rate="500" />
</int:service-activator>
<bean class="org.springframework.integration.aop.AdvisePolledFlow$ApplyAdviceToHandler">
<constructor-arg value="myService.handler" />
</bean>
</beans>
/*
* Copyright 2002-2013 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.aop;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.aop.framework.Advised;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.AopUtils;
import org.springframework.aop.support.NameMatchMethodPointcutAdvisor;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.integration.Message;
import org.springframework.integration.MessageChannel;
import org.springframework.integration.core.MessageHandler;
import org.springframework.integration.core.PollableChannel;
import org.springframework.integration.message.GenericMessage;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.util.Assert;
/**
* @author Gary Russell
*
*/
@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
public class AdvisePolledFlow {
private static Object received;
@Autowired
private MessageChannel input;
@Autowired
private PollableChannel output;
@Test
public void test() {
input.send(new GenericMessage<String>("foo"));
assertNotNull(output.receive(1000));
assertNotNull(received);
assertEquals("foo", ((Message<?>) received).getPayload());
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* B(F)PP that applies an advice to the handler embedded in an endpoint.
*
* @author Gary Russell
*
*/
public static class ApplyAdviceToHandler implements BeanFactoryPostProcessor, BeanPostProcessor, BeanClassLoaderAware {
private String beanName;
private ClassLoader beanClassLoader;
public ApplyAdviceToHandler(String beanName) {
Assert.notNull(beanName);
this.beanName = beanName;
}
/**
* Convert the 'endpoint.handler' alias to the actual bean name
*/
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
String[] aliases = beanFactory.getAliases(this.beanName);
if (aliases.length > 0) {
this.beanName = aliases[0];
}
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (!(bean instanceof FactoryBean) && beanName.equals(this.beanName)) {
if (AopUtils.isAopProxy(bean) && bean instanceof Advised) {
Class<?> targetClass = AopUtils.getTargetClass(bean);
MyAdvice advice = new MyAdvice();
NameMatchMethodPointcutAdvisor handlerAdvice = new NameMatchMethodPointcutAdvisor(advice);
handlerAdvice.addMethodName("handleMessage");
if (AopUtils.canApply(handlerAdvice.getPointcut(), targetClass)) {
((Advised) bean).addAdvice(advice);
}
}
else {
Assert.isInstanceOf(MessageHandler.class, bean, "Can only advise message handlers");
ProxyFactory proxyFactory = new ProxyFactory(bean);
proxyFactory.addAdvice(new MyAdvice());
return proxyFactory.getProxy(this.beanClassLoader);
}
}
return bean;
}
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
this.beanClassLoader = classLoader;
}
}
/**
* Test advice
* @author Gary Russell
*
*/
public static class MyAdvice implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
received = invocation.getArguments()[0];
return invocation.proceed();
}
}
/**
* Test Service.
* @author Gary Russell
*
*/
public static class Service {
public String handleMessage(String msg) {
return msg;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment