慢思考者

今天Hacker News推了一篇文章我觉得很有意思:I’m a very slow thinker。作者说他反应很慢,经常是别人跟他说一件有趣的事情,他要过一段时间后才反应过来,“噢,原来这么有趣呀,哈哈”;别人问他一个深度问题,他会直接说他不知道,到第二天早上他会给出一个答案来。作者有个不错的观点是,他并不以此为耻,因为他觉得他并不是要去赢得一个辩论比赛,他习惯慢思考,只有慢思考才能真正把握问题的真正奥义,第一反应往往是不准确而且是过时的。 想想我自己,我自认为也是一个反应很慢的人,我根本没法跟那些思维极其敏捷的人相比。 »

Read More

记一次类污染问题定位

今天项目线上测试出现了一个问题,一个War包启动失败(使用Jetty Runner启动),报的错是: Caused by: java.lang.NoSuchMethodError: org.apache.cxf.transport.AbstractTransportFactory.<init>(Ljava/util/List;Lorg/apache/cxf/Bus;)V »

Read More

用shade插件build可执行jar包

之前一直用assembly插件来build可执行的jar包,但用assembly插件有个问题,就是在build有依赖到Spring Framework的jar的时候,像META-INF目录下面的如spring.handlers和spring.schemas文件就会被互相覆盖,初了Spring Framework,我们常用的SPI,如果有两个SPI的名字一样(当然,这是不好的practice),也就是说如果META-INF/services目录有两个名字一样的文件,也会被互相覆盖。这个时候,用shade插件就有办法避免。 Shade插件如下: <plugin> <groupId>org. »

Read More

Spring MVC源码剖析系列(2) - DispatcherServlet工作原理之HandlerMapping

在本系列的第一篇,我剖析了DispatcherServlet的初始化过程,但还有很多东西没有说清楚,比如HandlerMapping的具体初始化,本篇就来厘清它。 如果你没有显式指定(通过xml配置文件或者Annotation)你要用的HandlerMapping类的话,DispatcherServlet默认会去classpath底下找DispatcherServlet.properties这个文件,然后从这个文件中读取出HandlerMapping类,并实例化对象。 DispatcherServlet.properties文件如下:(这里用的是4.3.9.release版本的Spring-MVC,里面的那个DefaultAnnotationHandlerMapping已经被Deprecated了,更新的版本是用的RequestMappingHandlerMapping,但这并不影响我们的分析): 我们先看一下DefaultAnnotationHandlerMapping类的继承关系: 我们看到这个DefaultAnnotationHandlerMapping最后其实是实现了ApplicationContextAware这个接口,我们要记住这个,因为它在后面会发挥重要的作用。 我们这里关注的是, »

Read More

Jetty源码剖析系列(7) - 底层网络通信的细节

我们先来回顾一下Jetty负责网络连接的类ServerConnector的构造函数: 可以看到在ServerConnector的构造函数里会创建一个SelectorManager,然后加到它的bean里面(这里其实体现了Jetty的一个设计模式,就是设计了一个containner,把相关的模块放到这个containner里面,启动该container(调用doStart方法)就会连带启动里面的模块(调用模块的doStart方法), Jetty里面的Server,Connector都是这样的containner。) 我们再来看newSelectorManager方法: 就是创建一个ServerConnectorManager对象,ServerConnectorManager继承了SelectorManager类: ,我们再看一下SelectorManager的doStart方法: 可以看到在调用父类的doStart方法之前,会创建ManagedSelector,并将该selector加到SelectorManager的bean里面,随后再在调用父类的doStart方法时调用该selector的doStart方法,注意selector的数目是根据CPU的数量计算出来的, newSelector方法其实就是直接构建一个ManagedSelector对象: 我们看一下ManagedSelector的构造函数: 关于ManagedSelector,我在系列(4) »

Read More

Spring MVC源码剖析系列(1) - DispatcherServlet工作原理之初始化

最近接手一个项目,用的是SpringMVC框架。循例想剖析一下它的源码,以求更深刻地理解MVC的实现。 DispatcherServlet是SpringMVC最核心的类,就拿它开刀:) 在web.xml中定义DispatcherServlet和它的Mapping: DispatcherServlet继承于FrameworkServlet,而FrameworkServlet又继承于HttpServletBean, HttpServletBean再继承于HttpServlet: DispatcherServlet有一段静态代码块值得关注: 它会到ClassPath下加载一个叫DispatcherServlet.properties的文件的内容,在SpringMVC的jar包里面有这个文件: 你可以理解为SpringMVC为你预先定义好一些后面有可能会用到的类。 Servlet容器(如Jetty)会调用Servlet的init方法,在这里,HttpServletBean重写了init()方法如下: 上面方法中值得注意的是调用了initServletBean方法,这个方法在FrameworkServlet中被重写了: 我们看到这里将会通过调用initWebApplicationContext方法来初始化一个webApplicationContext,这个非常重要, »

Read More

Jetty源码剖析系列(6) - Connector与ServerSocket

本文主要从源代码的角度来分析Jetty的Connector如何通过ServerSocket来绑定和监听网络地址和端口的过程。 Jetty的Connector实现类是ServerConnector,循例从它的doStart()方法开始(至于是如何到达这个方法,请移步本系列的前几篇): 它的doStart方法先调用父类AbstractNetworkConnector的doStart方法: 在父类的doStart方法里面会调用子类实现的open方法,此处是ServerConnector的open方法: 到这里已经可以看到Jetty的Connector与Java NIO的关系了,将会调用openAcceptChannel方法来构建一个NIO的ServerSocketChannel: 从上图的代码我们可以看到,Jetty默认用Java NIO来实现了它的网络框架,另外一点就是,如果你用java来实现一套网络框架,无非就是BIO和NIO两种,返朴归真。 先常规调用ServerSocketChannel的静态方法open方法来打开一个ServerSocketChannel: 因为Java的NIO是基于Selector来实现的,所以在这里会通过SelectorProvider类的静态方法provider来加载Selector的实现类: 它先尝试从System Property里加载Selector的实现类并实例化: 如果没有的话,就尝试通过SPI的方式来加载Selector的实现类并实例化: »

Read More