版本:Camel 1.0
camel-core test:
- org.apache.camel.processor.TransformViaDSLTest
- org.apache.camel.processor.TransformTest
小结:
- Camel解析Route、启动CamelContext、执行发送消息的基本过程
- 使用面向对象的特点解决语言定义、语言执行之间的关系。
- 内部类的使用。
- 职责链设计模式的应用。
配置一个简单的路由:
new RouteBuilder() {
public void configure() {from("direct:start").to("mock:result");
}
- 解析Route
- 在CamelContext增加Routes(调用 addRoutes方法,实质上是增加所有的FromBuilder为起点的Route),RouteBuilder将通过getRouteList()方法解析所有的Route(Returns the routing map from inbound endpoints to processors)。
- 构造FromBuilder:
- 加载direct:start所属于的DirectEndpoint。
- 通过direct模式,加载direct对应的Component;立即尝试启动Component,但DirectComponent。
- 没有实现Service接口(肯定有其他类型的Component需要启动);将加载后的Component设置在CamelContext的成员变量中,下一次将不重复创建DirectComponent。
- 通过DirectComponent创建direct:start EndPoint;立即尝试启动EndPoint,但DirectEndPoint没有实现Service接口(肯定有其他类型的EndPoint需要启动);将加载后的Component设置在CamelContext的成员变量中,下一次将不重复创建direct:start EndPoint。
- 通过DirectEndpoint构造FromBuilder。FromBuilder关键成员变量:
- from:Endpoint,即direct:start
- processors:此时为空
- processFactories:此时为空,下一步的ToBuilder为其成员
- 加载direct:start所属于的DirectEndpoint。
- 通过FromBuilder的to方法,构造ToBuilder;to方法返回ProcessorFactory
- 加载mock:result所属于的MockEndpoint,过程同上。
- 通过MockEndpoint构造ToBuilder。ToBuilder的关键成员变量:
- destination:Endpoint:即mock:result
- 将ToBuilder加入到FromBuilder的processFactories之中。
- 构造FromBuilder:
- 遍历RouteBuilder中的FromBuilder并createRoute(),并增加到RoutBuilder的routes中
- 遍历调用FromBuilder的processFactories,创建processor;
- 此时processFactories为ToBuilder将创建SendProcessor,其中SendProcessor的destination为mock:result;
- 为SendProcessor包装error handler:通过DeadLetterChannelBuilder创建processor为RecipientList(log:org.apache.camel.DeadLetterChannel:error);最终的包装为DeadLetterChannel。
- 如果processFactories产生多个processor,则构造CompositeProcessor,此时只有一个SendProcessor;
- 通过direct:start以及DeadLetterChannel构造EventDrivenConsumerRoute,返回。
- 遍历调用FromBuilder的processFactories,创建processor;
- 在CamelContext增加Routes(调用 addRoutes方法,实质上是增加所有的FromBuilder为起点的Route),RouteBuilder将通过getRouteList()方法解析所有的Route(Returns the routing map from inbound endpoints to processors)。
- 启动CamelContext
- 遍历所有的Component,如果实现了Service方法,则进行启动;此时CamelContext有2个Component:DirectComponet和MockComponet。DirectComponet没有实现Service接口,MockComponet进行了实现,但方法为空。
- 遍历所有的route的Servcie并启动,此时为通过direct:start构造的FromBuilder而来的EventDrivenConsumerRoute。
- 获取EventDrivenConsumerRoute所包含的Servcie
- 获取EventDrivenConsumerRoute对应的processor,如果processor实现了Service接口,则加入列表;此例为DeadLetterChannel,DeadLetterChannel实现了Service接口,需要加入。
- 获取EventDrivenConsumerRoute对应的endpoint为direct:start,根据上一步的processor创建Consumer。Consumer接口继承了Service。一定加入。
- 启动Service,启动前将这些Service加入到CamelContext需要关闭的服务列表中
- 启动DeadLetterChannel
- 调用output:Processor的启动方法:调用SendProcessor的启动方法,SendProcessor启动调用destination的成员变量MockEndPoint的createProducer()方法。
- 调用deadLetter:Processor的启动方法:RecipientList实现了Service接口,进行启动(实现为空)。
- 启动Consumer on DirectEndpoint:将该Consumer增加到DirectEndpoint的Consumer列表中。
- 启动DeadLetterChannel
- 获取EventDrivenConsumerRoute所包含的Servcie
//Send a message,see ContextTestSupport.java
template.send("direct:start", new Processor() {
public void process(Exchange exchange) {
Message in = exchange.getIn();
in.setBody(body);
in.setHeader("testCase", getName());
}
});
- 在CamelContext中获取direct:start对应的EndPoint,并设置到CamelTemplate的缓存endpointCache中。
- 通过ProducerCache进行send(endpoint,processor)
- ProducerCache不包含direct:start的Producer,调用DirectEndipoint进行创建;并进行启动(实现为空)。将Producer设置到ProducerCache中。
- 调用Producer的createExchange方法:调用DirectEndpoint的createExchange方法,创建默认的DefaultExchange.
- 调用processor的process(defaultExchange)方法。
- 调用配置中的方法,即设置名为testCase的header.
- 调用Producer的process(defaultExchange)方法。
- 调用Producer on DirectEndpoint的process方法
- 调用DirectEndpoint的process方法
- 依次调用consumer.getProcessor.process(Exchange)方法
- DirectEndpoint唯一一个consumer为DeadLetterChannel,调用其process方法
- 调用output:SendProcessor的process方法
- 调用producer on SendProcessor的process方法
- producer的实现为DefaultProducer on MockEndpoint,调用MockEndpoint的process方法
- 调用producer on SendProcessor的process方法
- 调用output:SendProcessor的process方法
- DirectEndpoint唯一一个consumer为DeadLetterChannel,调用其process方法
- 依次调用consumer.getProcessor.process(Exchange)方法
- 调用DirectEndpoint的process方法
- 调用Producer on DirectEndpoint的process方法
-----------------------------------------------------------------------------------------------------------------------------------
若Route定义为:
from("direct:start").process(new Processor() {
public void process(Exchange exchange) {
Message in = exchange.getIn();
in.setBody(in.getBody(String.class) + " World!");
}
}).to("mock:result");
则向FromBuilder增加两个ProcessBuilder:
- addProcessBuilder(new ConstantProcessorBuilder(processor));
- ToBuilder answer = new ToBuilder(this, endpoint);
addProcessBuilder(answer);
在makeProcessor时通过上述两个Builder产生的processor构造成new CompositeProcessor
若Route定义为:
from("direct:start").setBody(body().append(" World!")).to("mock:result");
则向FromBuilder增加两个ProcessBuilder:
- addProcessorBuilder(ProcessorBuilder.setBody(expression));
- ToBuilder answer = new ToBuilder(this, endpoint);
addProcessBuilder(answer);
在makeProcessor时通过上述两个Builder产生的processor构造成new CompositeProcessor
在执行阶段,CompositeProcessor遍历执行两个processor。
-------------------------------------------------------------------------------------------------
Camel 1.1、1.3、1.4对上述过程有较大变动。