gpt4 book ai didi

spring - 如何使用 Camel 2.9 定义自定义 CamelBeanPostProcessor

转载 作者:行者123 更新时间:2023-12-05 00:01:16 24 4
gpt4 key购买 nike

Camel 使用 CamelBeanPostProcessor支持使用注释将 Camel 端点、生产者模板等 Autowiring 到 bean 中的类。

该类的文档说:

If you use the element in your Spring XML then one of these bean post processors is implicitly installed and configured for you. So you should never have to explicitly create or configure one of these instances.

但没有提及如何实际提供自定义实现。

我使用 Spring 和 <camelContext...>配置 Camel 的方式。我如何提供自己的 CamelBeanPostProcessor 实现?原因是我想覆盖 canPostProcessBean排除几个 bean 类型的方法,因为对它们进行后期处理会给我们带来问题。它们永远不会有任何 Camel 特征,所以这不是问题。

最佳答案

我认为解决方案是定义您自己的 BeanPostProcessor。正如 javadoc 所述:

ApplicationContexts can autodetect BeanPostProcessor beans in their bean definitions and apply them to any beans subsequently created. Plain bean factories allow for programmatic registration of post-processors, applying to all beans created through this factory.

所以,如果你像这样使用 camel xml:

<camel:beanPostProcessor/>

只需替换为:

<bean id="camel:beanPostProcessor"
class="org.mael.sample.camel.postprocessor.CustomCamelBeanPostProcessor" />

这样你就不会使用xml注册的CamelBeanPostProcessor,而是你自己的BeanPostProcessor实现。

但是如果您想扩展 CamelBeanPostProcessor 类,请注意,我已经看到了 source它使用 org.apache.camel.impl.DefaultCamelBeanPostProcessor 的一个实例作为委托(delegate)并扩展后者会导致一些错误,因为抛出的异常与 Spring 接口(interface)中声明的异常不匹配。

最好的选择是在您自己的实现中也使用一个委托(delegate),并且只覆盖您想要的方法,即 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;
}

}

关于spring - 如何使用 Camel 2.9 定义自定义 CamelBeanPostProcessor,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13021332/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com