Spring Boot Camel - Camel组件中的自动装配问题

时间:2017-10-11 06:12:42

标签: java spring spring-boot apache-camel

我正在使用Spring Boot 1.5.7和Apache Camel 2.19.3,使用 spring-boot-starter-camel 提供的Spring Boot AutoConfiguration

这是非常基本的Spring Boot和Camel在他们的tutorial中初始化,所以我们有一个 RouteBuilder 组件就是这样做的。

@Component
public class CIFRoutes extends  RouteBuilder {

  @Override
  public void configure() throws Exception {
  // build routes
  }
}

我们有一个配置,它定义了我们在应用程序中需要的一些bean

@Configuration
public class MyConfiguration {

  @Bean
  public void Map<String, Object> map() {
    return new HashMap<>()
  }
}

最后,我们有一个自定义 InflightRepository 实现,应该通过自动配置扫描并添加到 CamelContext ,它基本上可以工作,但由于某种原因,组件不会不能正确初始化。意味着,它的依赖关系没有被初始化,但bean被实例化并注入我的应用程序。

@Component
public class MyCustomInflightRepository extends DefaultInflightRepository {

  @Autowired
  private Map<String, Object> map;

  @Override
  public void add(Exchange exchange) {
  super.addExchange(exchange);
   // ....
  }
}

现在的问题是 map 仍然是(null),我还尝试添加@PostConstruct初始化方法但不会被调用。

就我能够重构而言,它似乎与 CamelAutoConfiguration 中的过早关联,其中 CamelContext bean被实例化(在私有方法 afterPropertiesSet中完成)

InflightRepository inflightRepository = getSingleBeanOfType(applicationContext, InflightRepository.class);
if (inflightRepository != null) {
     LOG.info("Using custom InflightRepository: {}", inflightRepository);
            camelContext.setInflightRepository(inflightRepository);
}

如果 MyCustomInflightRepository 未实现 InflightRepository ,则会正确初始化bean,但Camel确实无法识别。禁用自动配置时,将注入bean的依赖项。

所以,要么是按照Spring的标准做了不可能的事情,要么是Spring的Camel组件有些可疑。

2 个答案:

答案 0 :(得分:1)

我解决这个问题有点快(我想在两天前发布这个^^),但是一位同事发现了可能出现的问题。

当使用 CamelAutoConfiguration InflightRepository bean(或者实际上Camel尝试获取匹配bean的所有内容)时,在属性解析器完全初始化之前访问上下文导致bean被初始化(并在上下文中缓存),然后才能解析任何自动连线属性。

我不是Spring专家,但我认为这种行为有点问题,因为当您依赖Spring DI作为自定义组件时,未初始化的bean被拉入 CamelContext

可以肯定的是,我会向维护人员提出这个......

顺便说一下,我的简单解决方案是在上下文配置中手动设置正在进行的存储库(如建议的那样)

@Bean
public CamelContextConfiguration camelConfig() {
    return new CamelContextConfiguration() {
        @Override
        public void beforeApplicationStart(CamelContext context) {

            context.setInflightRepository(new MyCustomInflightRepository(/* Dependencies go here */ ));
        }

        @Override
        public void afterApplicationStart(CamelContext camelContext) {

        }
    };
}

在您的项目中使用 camel-http-starter 似乎也是一个问题,不推荐使用,他们声称已弃用。

所以,不要为你的骆驼管理的bean做过DI(无论是通过属性还是构造函数注入),或者跳过那个启动器。

答案 1 :(得分:0)

问题是Map<String,Object>对于Spring来说太模糊了,无法理解你想要的东西;我认为默认行为是它会给你所有按名称键入的bean。

相反,更具体,或者可能提供必要的参数作为构造函数参数,并在@Bean方法中显式配置它们(无论如何总是使用构造函数注入是个好主意。)