博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

Camel运行原理分析

Posted on 2016-07-27 19:24  FG度  阅读(3912)  评论(1编辑  收藏  举报

Camel运行原理分析

以一个简单的例子说明一下camel的运行原理,例子本身很简单,目的就是将一个目录下的文件搬运到另一个文件夹,处理器只是将文件(限于文本文件)的内容打印到控制台,首先代码如下:

public static void main(String[] args) throws Exception {  

    //创建Camel上下文  

    DefaultCamelContext camelContext = new DefaultCamelContext();  

    //添加一个路由,参数为路由建造者  

    camelContext.addRoutes(new RouteBuilder() {  

        @Override  

        public void configure() throws Exception {  

            this.from("file:D:/temp/in").process(new Processor() {  

                @Override  

                public void process(Exchange exchange) throws Exception {  

                    GenericFile<File> gf = exchange.getIn().getBody(GenericFile.class);  

                    File file = gf.getFile();  

                    PrintStream ps = new PrintStream(System.out);  

                    BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file)));  

                    String line = null;  

                    while((line=br.readLine())!=null) {  

                        ps.println(line);  

                    }  

                    ps.close();  

                    br.close();  

                }  

            }).to("file:D:/temp/out");  

        }  

    });  

    //启动上下文  

    camelContext.start();  

    //防止主线程退出  

    Object object = new Object();  

    synchronized (object) {  

        object.wait();  

    }  

}

 

对于camel来说,其原理核心的部分主要包含路由信息的构建、组件查找、和路由启动过程三方面,下面结合以上简单例子对三个方面来对camel的源码进行分析:

一、路由的构建

其实这里说的路由构建其实是构建路由定义,对应Camel中的RouteDefinition类,一个RouteDefinition对象规定了或者说指定了一个消息从哪里产生,中间要经过什么样的处理,最后路由到什么地方。RouteDefinitionRouteBuilder进行构建,再具体点就是调用RouteBuilderconfigure()方法,构建完成后再添加到CamelContext中,那么该路由定义就可以运行了。RouteBuilderconfigure()方法是一个抽象方法,所以该方法要由开发者进行实现,其实就是在进行路由定义的构建过程。

首先,调用RouteBuilderfrom方法获取RouteDefinition,并且根据from传入的参数将一个FromDefinition类型的实例设置给RouteDefinition的inputs(输入)列表,然后调用RouteDefinition的process()to()方法,分别生成ProcessDefinition和ToDefinition对象,因为ProcessDefinition和ToDefinition都继承自ProcessorDefinition,所以都可以看出输出放到RouteDefinition的outputs(输出)列表中,至此,整个路由定义就构建完成了,其实该路由定义最重要的就是输入与输出,输入与输出都可以有多个,默认情况下,在路由运行后,Camel会依赖调用这些输出处理器并最终将消息路由到指定目的地。

二、组件查找方式

Camel的运行是由组件(component)进行组织的,我们前面的调用from()方法传个字符串,camel是要根据uri来查找到对应的组件,即要维护uri到组件之间的映射关系,查找组件的过程是调用DefaultCamelContext中的getComponent(String name)方法来完成的,是在DefaultCamelContext启动的时候调用,获取相应的组件,生成对应的endPoint,组件的查找是从DefaultCamelContext上下文缓存的components中去找,如果没有找到,就会去根据uri前缀生成一个component,生成的代码大致如下:

// 先在注册表中查找

        Object bean = null;

        try {

            bean = context.getRegistry().lookupByName(name);

            getLog().debug("Found component: {} in registry: {}", name, bean);

        } catch (Exception e) {

            getLog().debug("Ignored error looking up bean: " + name, e);

        }

    //省略了一部分代码....

  // 注册表中没有时,使用Component工厂创建一个

        Class<?> type;

        try {

            type = findComponent(name, context);

            if (type == null) {

                // not found

                return null;

            }

        } catch (NoFactoryAvailableException e) {

            return null;

        } catch (Exception e) {

            throw new IllegalArgumentException("Invalid URI, no Component registered for scheme: " + name, e);

        }

   // 创建Component

        if (Component.class.isAssignableFrom(type)) {

            return (Component) context.getInjector().newInstance(type);

        } else {

            throw new IllegalArgumentException("Type is not a Component implementation. Found: " + type.getName());

        }

 

其中的findComponent方法是在camel包中默认路径META-INF/services/org/apache/camel/component/+uri前缀名

找对应的Properties(不带.properties后缀)文件,文件中有Component组件实例化的类名,找到后通过反射机制生成一个component组件,放到缓存中。我们自己也可以按照这个规则来拓展自己的component。

三、路由的启动原理

 

 

Camel启动原理图

四、路由的运行原理

 

 

图一

 

 

图二