Tomcat的系统架构与设计模式

Tomcat总体结构

conf/server.xml配置文件:

Tomcat的心脏即为Connector和Container组件:

1
2
往外层看,一个Container对应多个Connector(如图有http和ajp等不同的Connetctor,Connector负责对外交流,接收请求,Container处理Connector接受的请求),它们共同组成一个Service,而多个Service就组成一个Server;
往里层看,Container含有Engine(Servlet引擎),Engine含有Host(虚拟主机),Host含有Context(一个Context对应一个Web应用),Context含有Wrapper(一个Wrapper对应一个Servlet)。

Service类的实现类为StandardService类。由于Service中,Container只有一个,Connector可多个,因此,StandardService提供setContainer()方法用于设置Container(具体实现:去掉老Container与Service的关系,添加新Container与Service的关系,并一一添加Connector与新Containner的关系),以及addConnector()/removeConnector()方法用于添加/删除Connector(具体实现:在StandardService类中维护的connectors数组中增减Connector)。

Server类的实现类为StandardServer类。Server中可有多个Service,因此,StandardServer同样提供addService()/removeService()方法来增减Service,以及findService()来供外部找到相应的Service。

Connector组件

Connector负责接收浏览器发过来的TCP连接请求,创建org.apache.coyote.Requestorg.apache.coyote.Response用于交换数据,之后Container会创建一个新的线程,并接收到传来的Request和Response对象,重新创建org.apache.catalina.connector.Requestorg.apache.catalina.connector.Response对象,进行后续处理。

Container组件

Container使用了经典的责任链模式,即从Engine到Warpper,层层关联。Engine作为顶层,不能调用setParent()方法再设置父容器,但可以调用addChild()方法添加子容器(且子容器只能是host);Wrapper作为最底层容器,也不能调用addChild()方法添加子容器,但可以调用setParent()方法设置父容器(且父容器只能是context)。

简单的tomcat可以没有Engine和Host。

Spring框架的设计理念与设计模式分析

核心组件

  • Spring的核心组件即:Bean、Context、Core;
  • 三者的形象比喻即:Bean是演员,Context是舞台背景,Core是演出的道具。
  • Bean即是Object的包装,Context就是要发现每个Bean之间的关系,为他们建立好并维护这个关系,所以Context就是Bean关系的集合,这个关系集合又叫Ioc容器。而Core就是发现、建立、维护关系所需要的一系列工具,把Core组件看成Util更容易理解。

Spring Bean的创建是典型的工厂模式,顶级接口即BeanFactory,有三个子类,分别是:ListableBeanFactory(表明bean是可列表的)、HierarchicalBeanFactory(表明Bean是有继承关系的,即每个Bean可能有父Bean)、AutowireCapableBeanFactory(定义Bean的自动装配规则),以上四个接口共同定义了Bean的集合、关系和行为。

Bean的完整定义在配置文件的<bean/>节点。当Spring成功解析一个Bean节点时,在spring的内部就会转化为一个BeanDefnition对象,以后所有的操作都是在这个对象上进行的。

Ioc容器如何工作

如何创建BeanFactory

Ioc容器实际上是COntext组件结合其他两个组件共同构建的一个Bean关系网。构建的入口即是AbstractApplicationContext类的refresh()

更新BeanFactory,首先就是如果BeanFactory已存在就更新,否则就创建,而更新的代码是,如果存在就destroyBeans()closeBeanFactory(),然后createBeanFactory(),创建的原始对象即是DefaultListableBeanFactory。并且后面会调用loadBeanDefinitions(beanFactory)。前文说到Spring内部Bean被转化为一个BeanDefnition对象,该方法即是加载、解析Bean的定义。

Ioc的扩展点

构建入口refresh()的实现代码处,有这样两句关键代码,体现了Spring的扩展点:

1
2
3
4
//初始化和执行BeanFactoryPostProcessor beans
invokeBeanFactoryPostProcessors(beanFactory);
//初始化和执行BeanPostProcessor beans
registerBeanPostProcessors(beanFactory);

第二句代码主要是获取实现BeanFactoryPostProcessor接口的子类,并执行它的postProcessBeanFactory()方法,该方法顾名思义即是调用BeanFactory新增加工器,即当BeanFactory创建时被调用。这个方法参数需要传入一个beanFactory(实际是ConfigurableListableBeanFactory,表示可配置的BeanFactory),说明可以对beanFactory做修改。

第四句代码,方法顾名思义是注册Bean新增加工器,即该方法也是获取实现了BeanPostProcessor接口的子类,并把它们(Bean新增加工器)注册到BeanFactory对象的beanPostProcessors变量中。BeanPostProcessor接口定义了两个方法:postProcessBeforeInitialization()postProcessAfterInitialization(),每当bean对象初始化时,进行相关调用,执行用户自定义的操作。

另外一个就是FactoryBean,这是一个工厂Bean,一个可以产生Bean的Bean。如果一个类继承FactoryBean,用户可以自己定义产生实例对象的方法,只需实现它的getObject()方法即可。

由上,Spring的Ioc容器的扩展点主要有:

  • BeanFactoryPostProcessor:构建BeanFactory时调用;
  • BeanPostProcessor:构建Bean时调用;
  • InitializingBean、DisposableBean:Bean实例创建和销毁时调用;
  • FactroyBean:可让你创建自定义的对象,可实现更多的控制。

Spring中AOP的特性详解

AOP即通过上面的FactoryBean来进行扩展来完成这个特性的。代理类继承了FactoryBean的ProxyFactoryBean。

设计模式解析之代理模式

即给某一个对象创建一个代理对象,由这个代理对象控制对原对象的引用,代理对象可在调用原对象时增加一些额外操作。

Spring MVC的工作机制与设计模式

整体介绍

SpringMVC的嵌入关键就是通过配置Web.xml的servlet,核心类即DispatcherServlet,它继承了HttpServlet,在Servlet的init方法调用时DispatcherServlet执行SpringMVC的初始化工作。具体初始化:

  • initMultipartResolver:用于文件上传服务;
  • initLocalResolver:用于处理应用的国际化;
  • initThemeResolver:用于定义一个主题;
  • initHandlerMappings:用于定义用户设置的请求映射关系;核心组件
  • initHandelrAdapters:用于根据Handler的类型定义不同的处理规则;核心组件
  • initHandlerExceptionResolvers:当Handler处理出错时,会通过这个Handler统一处理;
  • initRequestToViewTranslator:将指定的ViewName按照定义的RequestToViewNameTranslator替换成想要的格式(如加上前缀、后缀);
  • initViewResolvers:用于将View解析成页面。核心组件

Control设计

Control=HandlerMapping+HandlerAdapters

HandlerMapping

HandlerMapping负责帮助我们管理URL和对应处理类(Handler)的映射关系,就是将一个或多个URL映射到一个或多个Spring Bean中。

它的初始化工作完成的两个最重要的工作就是:将URL与Handler的对应关系保存在handlerMap集合中,并将所有的interceptors对象保存在adaptedInterceptors数组中。

HandlerAdapter

HandlerAdapter用于帮助自定义各种Handler。一般的MVC框架会先定义一个特定接口,让Handler去实现,然后MVC框架通过调用接口方法来调用Handler。而SpringMVC此处使用了多接口(如有:HttpRequestHandlerAdapter、SimpleControllerHandlerAdapter、SimpleServletHandlerAdapter等),不同接口定义不同方法,然后让Handler去选择实现这些个接口,让Handelr的实现更加灵活。

它的初始化工作即是创建一个HandlerAdapter对象,将这个HandlerAdapter对象保存在DispatcherServlet的handlerAdapters集合中。

整体调用逻辑

1
2
3
4
5
URL到来时,DispatcherServlet执行`doDispatch()`方法。
方法会匹配`DispatcherServlet的handlerMappings集合中的某个HandlerMapping对象的某个Handler`,匹配成功后返回一个HandlerExecutionChain对象(处理链,这个处理链包含用户定义的多个HandlerInterceptor对象)。
通过调用该对象的`getHandler()`方法可以得到Handler对象,通过获得的Handler对象进一步去匹配`支持该Handler的DispatcherServlet的handlerAdapters集合中的HandlerAdapter对象`,并返回handlerAdapter对象。
然后调用这个handlerAdapter对象的`handle()`方法(该方法需传入Handler对象,并将Handler对象强转为所继承的父类,如上的Controller、HttpRequestHandler)。
`handle()`方法将调用强转后的handler的`handleRequest()`方法,并返回ModelAndView对象,最后根据ModelAndView进行渲染。

Model设计

在业务逻辑层通常也有Model实例,不过此处所谓的Model,是指针对模版渲染的Model(ModelAndView)。

ModelAndView对象是连接业务逻辑层与View表现层的桥梁,对SpringMVC来说它也是连接Handler与View的桥梁。

Model顾名思义即会持有一个ModelMap对象和一个View对象(或View名称)。在Handler中,将模板中需要的对象会存在这个ModelMap中,然后传递到View对应的ViewResolvers中,不同的ViewResovler对这个ModelMap中的对象有不同的处理方式。

View设计

View=RequestToViewNameTranslator+ViewResolver

RequestToViewNameTranslator用来支持用户自定义对ViewName的解析,如给请求的ViewName加上前缀或后缀,或替换成特定的字符等。

ViewResolver则是根据ViewName创建View对象。

设计模式解析之模板模式

核心即是:大的逻辑已经定义,要做的就是实现一些具体步骤。

SpringMVC的View设计使用了模板模式,View只定义了接口方法,AbstractView类实现了在View中定义的所有方法,并留有一个抽象方法renderMergedOutputModel给子类去实现。而子类AbstractJasperReportsView和AbstractTeamplateView抽象类实现了上述留有的方法,并进一步细化出了renderReport抽象方法和renderMergedTemplateModel方法给子类去进一步实现。

深入分析iBatis框架之系统架构与映射原理

左边的SqlMapClient接口主要定义了客户端的操作行为,包括select、insert、update和delete。而邮编主要定义了当前客户端在当前线程中的执行环境。SqlMapSession可以共享使用,也可以自己创建,如果自己创建,需要在结束时自行关闭。

iBatis通过解析SqlMap配置文件得到所有的Statement执行语句,同时会形成ParameterMap、ResultMap和SQL。当iBatis构建好RequestScope执行环境后,要做的工作就是把传过来的对象数据结合ParameterMap中的信息提取出一个参数数组,这个数组的顺序对应与SQL中参数的顺序,然后调用preparedStatement.setXXX(i,parameter)提交参数。

iBatis可以自己管理事务,也可以由外部管理。iBatis自己管理是通过共享SqlMapSession对象实现的,多个Statement执行时共享一个SqlMapSession实例,而且线程安全。如果外部程序管理就要自行控制SqlMapSession对象的生命周期。

设计模式解析之简单工厂模式

核心即:通过判断其条件,来返回不同的对象实例

iBatis中的DataExchangeFactory即使用了简单工厂模式,它是一个工厂,它可根据传递进来的不同class类型返回不同的对象产品,这里返回的产品都是单例,当然简单工厂模式也可以每次创建一个新对象返回给调用者。

设计模式解析之工厂模式

与简单工厂模式不同的是,这里就不再是一个工厂,而是多个工厂,与一个顶层抽象工厂。如果把服务器单机比作简单工厂模式的工厂,那么服务器集群+一个负载均衡服务器就是工厂模式的多个工厂和顶层抽象工厂。

在iBatis中的DataSourceFacotry就是抽象工厂类,对应的JndiDataSourceFactory和DbcpDataSourceFactory就是具体工厂。

更多文章,请关注:开猿笔记