我认为解决方案是定义自己的 BeanPostProcessor。正如javadoc所述:
ApplicationContexts 可以在它们的 bean 定义中自动检测 BeanPostProcessor bean,并将它们应用于随后创建的任何 bean。普通 bean 工厂允许后处理器的编程注册,适用于通过该工厂创建的所有 bean。
因此,如果您像这样使用骆驼 xml:
<camel:beanPostProcessor/>
只需替换为:
<bean id="camel:beanPostProcessor"
class="org.mael.sample.camel.postprocessor.CustomCamelBeanPostProcessor" />
这样你就不会使用xml注册的CamelBeanPostProcessor,而是你自己的BeanPostProcessor实现。
但要注意,如果你想扩展 CamelBeanPostProcessor 类,我已经看到了源代码,它使用org.apache.camel.impl.DefaultCamelBeanPostProcessor的实例作为委托,扩展后者会导致一些错误,因为抛出的异常与Spring 接口中声明的异常。
最好的选择是在你自己的实现中也使用一个委托,并覆盖你想要的方法,即canPostProcessBean
编辑:
这是我做的事情,检查TODO
评论以应用您的功能,还有pastebin:
package org.mike.sample.camel.postprocessor;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import javax.xml.bind.annotation.XmlTransient;
import org.apache.camel.CamelContext;
import org.apache.camel.Endpoint;
import org.apache.camel.Service;
import org.apache.camel.core.xml.CamelJMXAgentDefinition;
import org.apache.camel.impl.CamelPostProcessorHelper;
import org.apache.camel.impl.DefaultCamelBeanPostProcessor;
import org.apache.camel.spring.GenericBeansException;
import org.apache.camel.util.ServiceHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanInstantiationException;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
public class CustomCamelBeanPostProcessor implements BeanPostProcessor,
ApplicationContextAware {
private static final transient Logger LOG = LoggerFactory
.getLogger(CustomCamelBeanPostProcessor.class);
@XmlTransient
Set<String> prototypeBeans = new LinkedHashSet<String>();
@XmlTransient
private CamelContext camelContext;
@XmlTransient
private ApplicationContext applicationContext;
@XmlTransient
private String camelId;
// must use a delegate, as we cannot extend DefaultCamelBeanPostProcessor,
// as this will cause the
// XSD schema generator to include the DefaultCamelBeanPostProcessor as a
// type, which we do not want to
@XmlTransient
private final DefaultCamelBeanPostProcessor delegate = new DefaultCamelBeanPostProcessor() {
@Override
public CamelContext getOrLookupCamelContext() {
if (camelContext == null) {
if (camelId != null) {
LOG.trace(
"Looking up CamelContext by id: {} from Spring ApplicationContext: {}",
camelId, applicationContext);
camelContext = applicationContext.getBean(camelId,
CamelContext.class);
} else {
// lookup by type and grab the single CamelContext if exists
LOG.trace(
"Looking up CamelContext by type from Spring ApplicationContext: {}",
applicationContext);
Map<String, CamelContext> contexts = applicationContext
.getBeansOfType(CamelContext.class);
if (contexts != null && contexts.size() == 1) {
camelContext = contexts.values().iterator().next();
}
}
}
return camelContext;
}
@Override
public boolean canPostProcessBean(Object bean, String beanName) {
// the JMXAgent is a bit strange and causes Spring issues if we let
// it being
// post processed by this one. It does not need it anyway so we are
// good to go.
// We should also avoid to process the null object bean (in Spring
// 2.5.x)
// TODO - DO YOUR STUFF HERE STRELOK
if (bean == null || bean instanceof CamelJMXAgentDefinition) {
return false;
}
return super.canPostProcessBean(bean, beanName);
}
@Override
public CamelPostProcessorHelper getPostProcessorHelper() {
// lets lazily create the post processor
if (camelPostProcessorHelper == null) {
camelPostProcessorHelper = new CamelPostProcessorHelper() {
@Override
public CamelContext getCamelContext() {
// lets lazily lookup the camel context here
// as doing this will cause this context to be started
// immediately
// breaking the lifecycle ordering of different camel
// contexts
// so we only want to do this on demand
return delegate.getOrLookupCamelContext();
}
@Override
protected RuntimeException createProxyInstantiationRuntimeException(
Class<?> type, Endpoint endpoint, Exception e) {
return new BeanInstantiationException(type,
"Could not instantiate proxy of type "
+ type.getName() + " on endpoint "
+ endpoint, e);
}
protected boolean isSingleton(Object bean, String beanName) {
// no application context has been injected which means
// the bean
// has not been enlisted in Spring application context
if (applicationContext == null || beanName == null) {
return super.isSingleton(bean, beanName);
} else {
return applicationContext.isSingleton(beanName);
}
}
protected void startService(Service service, Object bean,
String beanName) throws Exception {
if (isSingleton(bean, beanName)) {
getCamelContext().addService(service);
} else {
// only start service and do not add it to
// CamelContext
ServiceHelper.startService(service);
if (prototypeBeans.add(beanName)) {
// do not spam the log with WARN so do this only
// once per bean name
CustomCamelBeanPostProcessor.LOG
.warn("The bean with id ["
+ beanName
+ "] is prototype scoped and cannot stop the injected service when bean is destroyed: "
+ service
+ ". You may want to stop the service manually from the bean.");
}
}
}
};
}
return camelPostProcessorHelper;
}
};
public CustomCamelBeanPostProcessor() {
}
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
try {
return delegate.postProcessBeforeInitialization(bean, beanName);
} catch (Exception e) {
// do not wrap already beans exceptions
if (e instanceof BeansException) {
throw (BeansException) e;
}
throw new GenericBeansException("Error post processing bean: "
+ beanName, e);
}
}
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
try {
return delegate.postProcessAfterInitialization(bean, beanName);
} catch (Exception e) {
// do not wrap already beans exceptions
if (e instanceof BeansException) {
throw (BeansException) e;
}
throw new GenericBeansException("Error post processing bean: "
+ beanName, e);
}
}
// Properties
// -------------------------------------------------------------------------
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.applicationContext = applicationContext;
}
public CamelContext getCamelContext() {
return camelContext;
}
public void setCamelContext(CamelContext camelContext) {
this.camelContext = camelContext;
}
public String getCamelId() {
return camelId;
}
public void setCamelId(String camelId) {
this.camelId = camelId;
}
}