gongstring技术博客
最新文章
源码解读
软件安装
常见问题
大数据
常用工具
鸡汤文
备案号:鄂ICP备15015839号-1
鄂公网安备 42010202001692号
Apache Camel使用加载路由源码(扫描包路径方式)分析及注意事项
2018-05-16 14:46:01
作者: gongstring
源码解读
/
Apache Camel使用加载路由源码(扫描包路径方式)分析及注意事项
## 1.添加依赖包 gradle依赖: ``` compile 'org.apache.camel:camel-spring:2.20.3' ``` ## 2.添加Spring配置信息 spring-camel.xml ```
com.chz.apps.esb.camel.routes
**.*Excluded*
**.*
``` com.chz.apps.esb.camel.routes包是用于存放camel的路由类 ## 3.编写路由类(错误的类) 此处使用本地文件往ftp自动上传文件为例: ``` package com.chz.apps.esb.camel.routes;import org.apache.camel.builder.RouteBuilder;import org.springframework.stereotype.Component;/** * 本地文件往服务器自动同步机制 */@Componentpublic class FileTransFtpRouteBuilder extends RouteBuilder { @Override public void configure() { from("file:D:\\tmp\\camel") .to("ftp:ftpUsername:ftpPassword@192.168.9.175"); } } ``` ## 4.问题描述 上面的builder是参考《Apache Camel Deve》第23页实例编写。每次启动的时候,会发现创建的route并没有添加到Camel的CamelContext中,也就是说路由并没有生效。 经过源码分析,Apache Camel在于Spring进行集成的时候,使用CamelContextFactoryBean进行相关Bean实例的统一管理。而使用packageScan进行启动时,需要调用如下方法: ``` @Override protected void findRouteBuildersByPackageScan(String[] packages, PackageScanFilter filter, List
builders) throws Exception { // add filter to class resolver which then will filter getContext().getPackageScanClassResolver().addFilter(filter); PackageScanRouteBuilderFinder finder = new PackageScanRouteBuilderFinder(getContext(), packages, getContextClassLoaderOnStart(), getBeanPostProcessor(), getContext().getPackageScanClassResolver()); finder.appendBuilders(builders); // and remove the filter getContext().getPackageScanClassResolver().removeFilter(filter); } ``` finder.appendBuilders(builders);此方法用于扫描包路径下面所有类,如果不是Spring的bean,则使用路由初始化方法,加载到Camel容器中。而书中提到使用Component注解后,会导致此处自动过滤掉: 在dubug的时候,日志如下: ``` [MI TCP Connection(3)-127.0.0.1] efaultPackageScanClassResolver DEBUG Searching for implementations of org.apache.camel.RoutesBuilder in packages: [com.chz.apps.esb.camel.routes] [MI TCP Connection(3)-127.0.0.1] efaultPackageScanClassResolver DEBUG Found: [class com.chz.apps.esb.camel.routes.FileTransFtpRouteBuilder][MI TCP Connection(3)-127.0.0.1] DefaultListableBeanFactory DEBUG Returning cached instance of singleton bean 'fileTransFtpRouteBuilder'[MI TCP Connection(3)-127.0.0.1] PackageScanRouteBuilderFinder DEBUG Ignoring RouteBuilder class: class com.chz.apps.esb.camel.routes.FileTransFtpRouteBuilder ``` 通过分析源码(PackageScanRouteBuilderFinder.shouldIgnoreBean方法),只要是Spring已经加载的bean,此处不会做任何处理。所以正确的方式应该是去掉Component注解。 ``` /** * Appends all the {@link org.apache.camel.builder.RouteBuilder} instances that can be found on the classpath */ public void appendBuilders(List
list) throws IllegalAccessException, InstantiationException { Set
> classes = resolver.findImplementations(RoutesBuilder.class, packages); for (Class> aClass : classes) { LOG.trace("Found RouteBuilder class: {}", aClass); // certain beans should be ignored if (shouldIgnoreBean(aClass)) { LOG.debug("Ignoring RouteBuilder class: {}", aClass); continue; } if (!isValidClass(aClass)) { LOG.debug("Ignoring invalid RouteBuilder class: {}", aClass); continue; } // type is valid so create and instantiate the builder @SuppressWarnings("unchecked") RoutesBuilder builder = instantiateBuilder((Class extends RoutesBuilder>) aClass); if (beanPostProcessor != null) { // Inject the annotated resource beanPostProcessor.postProcessBeforeInitialization(builder, builder.toString()); } LOG.debug("Adding instantiated RouteBuilder: {}", builder); list.add(builder); } } protected boolean shouldIgnoreBean(Class> type) { Map
beans = applicationContext.getBeansOfType(type, true, true); if (beans == null || beans.isEmpty()) { return false; } return true; } ``` ## 5.编写路由类(正确的类) ``` package com.chz.apps.esb.camel.routes;import org.apache.camel.builder.RouteBuilder;/** * 本地文件往服务器自动同步机制 */public class FileTransFtpRouteBuilder extends RouteBuilder { @Override public void configure() { from("file:D:\\tmp\\camel") .to("ftp:ftpUsername:ftpPassword@192.168.9.175"); } } ```