[KANMARS原创] - Lua源码阅读_DAY_001






本文从初学者的角度试探性的看了一下Lua的实现



最近草草的看了点lua的结构,看这门语言的原因,是因为lua很短,并且是程序员从应用开发到语言开发的一个比较简单的路径。



学艺不精,但是必须总结一下以防忘记



——————



lua语法请查询官方文档,本处不再赘述



——————



lua最重要的是内部的数据结构,可以参照阿里云大神罗日健的相关博客:



http://blog.aliyun.com/761?spm=0.0.0.0.Bbv98y       Lua数据结构 — TValue(一)



http://blog.aliyun.com/768?spm=0.0.0.0.IIIJKM        Lua数据结构 — TString(二)



http://blog.aliyun.com/787?spm=0.0.0.0.nwRCjZ        Lua数据结构 — Table(三)



http://blog.aliyun.com/845?spm=0.0.0.0.BvDyCO        Lua数据结构 — 闭包(四)



http://blog.aliyun.com/789?spm=0.0.0.0.SHkRm9         Lua数据结构 — Udata(五)



http://blog.aliyun.com/795?spm=0.0.0.0.xddNuq         Lua数据结构 — Lua_state(六)








此外,参照网易杭州研究中心总监吴云洋的博客,也是不错的



http://blog.codingnow.com/




PS:我从2004到2011,玩《大话西游》七年,人生因这个游戏而改变。



我看云风的博客一年,学习lua的一些语法或者内存结构……



直到今天上午,才知道:《大话西游》是吴云洋开发的,而吴云洋就是云风。








——————



lua最常用的地方是游戏引擎的开发,其优势如下:



1、Lua脚本可以很容易的被C/C++ 代码调用,也可以反过来调用C/C++的函数,这使得Lua在应用程序中可以被广泛应用。



2、在目前所有的解释器语言中,Lua的速度是最快的。



3、Lua足够的小,可以在嵌入平台大范围使用。



——————




但对我来说,其优点就是:小,能让我短时间了解一门语言是如何运行的。



Lua是用纯C语言实现的,幸好我的C语言已经达到了可以出去混饭吃的水平。







Lua的数据结构由TValue,TString,UData,GCObject等构成,



要点如下:大范围应用了TValue作为值引用,而TString和UData等都是可垃圾回收的对象,通过GCObject链接到了垃圾回收链上。



而TString和UData都采用的是一个头+体的结构,即从TString后开始读取TString中的长度,即为字符串的真正内容。UData类似。







Table是Lua比较重要的数据类型,在内部实现上,分别使用散列表Node node和数组TValue array来存放下标是”Value”和[index]的键和下标。



当长度不够时,会调用luaH_resize函数对这两个内存进行扩容,而扩容在底层使用的是luaM_reallocvector–》realloc内存分配,可以对已分配内存进行扩容重新分配



即Table可以实现动态的扩容或者缩容







接下来是Lua_state,Lua_state是一个全局的上下文信息。储存了Lua执行过程的栈信息,函数调用信息等,参照Lua_state结构体的源码











/

** ‘per thread’ state

더보기

[KANMARS原创] - SPRING源码解析-AbstractApplicationContext



包含最重要的Spring方法    refresh



内部调用顺序

    public void refresh() throws BeansException, IllegalStateException {

        synchronized (this.startupShutdownMonitor) {

            // Prepare this context for refreshing.        

            // 初始化环境,包含Environment    StandardEnvironment {activeProfiles=[], defaultProfiles=[default], propertySources=[systemProperties,systemEnvironment]}

            prepareRefresh();



            // Tell the subclass to refresh the internal bean factory.

            // 初始化BeanFactory,    DefaultListableBeanFactory

            // 包含

            // 1、加载Resources    XmlBeanDefinitionReader    ResourcePatternResolver         DefaultResourceLoader                  

            // 2、根据Resources加载BeanDefinition    BeanDefinitionParserDelegate     BeanDefinitionHolder        GenericBeanDefinition                  

            // 3、注册BeanDefinition到BeanFactory中    BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());

            // 4、通知Bean定义事件    getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));        内部将依赖的BeanDefinition进行依赖添加innerBeanDefinitions,beanReferences    

            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();



            // Prepare the bean factory for use in this context.

            // 对BeanFactory进行预处理

            // 1、设置默认值,如classloader等    

            // 2、设置默认处理对象ApplicationContextAwareProcessor

            // 3、设置被忽略的依赖接口    ignoredDependencyInterfaces,如ResourceLoaderAware,ApplicationEventPublisherAware等

            // 4、设置被忽略的依赖类    resolvableDependencies,如BeanFactory.class等

            // 5、如果包含运行时注入类    loadTimeWeaver,则添加BeanFactoryProcess对象

            // 6、注册一些默认Bean    beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());

            //                 beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());

            //                 beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());

            prepareBeanFactory(beanFactory);



            try {

                // Allows post-processing of the bean factory in context subclasses.

                postProcessBeanFactory(beanFactory);



                // Invoke factory processors registered as beans in the context.

                // 1、执行    BeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry注册前时间处理

                // 2、通过beanFactory.getBeansOfType(BeanDefinitionRegistryPostProcessor.class, true, false);    获取所有的BeanDefinitionRegistryPostProcessor

                // 3、执行invokeBeanFactoryPostProcessors(registryPostProcessors, beanFactory);    执行注册前的BeanFactoryProcessor

                // 4、invokeBeanFactoryPostProcessors(registryPostProcessorBeans, beanFactory);    执行注册的

                // 5、invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);

                invokeBeanFactoryPostProcessors(beanFactory);



                // Register bean processors that intercept bean creation.

                // 1、注册BeanPostProcessors

                registerBeanPostProcessors(beanFactory);



                // Initialize message source for this context.

                // 1、初始化DelegatingMessageSource    信息国际化

                initMessageSource();



                // Initialize event multicaster for this context.

                // 1、初始化Spring事件体系            SimpleApplicationEventMulticaster,通过multicastEvent方法可以对增加的ApplicationListener通知消息

                initApplicationEventMulticaster();



                // Initialize other special beans in specific context subclasses.

                // 初始化其他Bean,暂为空方法

                onRefresh();



                // Check for listener beans and register them.

                // 1、对Listeners进行注册

                registerListeners();



                // Instantiate all remaining (non-lazy-init) singletons.

                // 对Bean进行初始化,执行BeanPostProcessors

                finishBeanFactoryInitialization(beanFactory);



                // Last step: publish corresponding event.

                // 刷新生命周期对象

                // 发送初始化结束信号

                // 在全局上下文视图中注册ApplicationContext

                // LiveBeansView.registerApplicationContext(this);

                finishRefresh();

            }



            catch (BeansException ex) {

                // Destroy already created singletons to avoid dangling resources.

                destroyBeans();



                // Reset ‘active’ flag.

                cancelRefresh(ex);



                // Propagate exception to caller.

                throw ex;

            }

        }

    }


더보기

JAVA方法调用-封装与继承中,执行的字节码是如何确定的


JAVA动态扩展能力的来源



JAVA之核心,是封装、多态、继承。



具体一点,就是:



    1、数据和方法的封装



    2、方法的多态和类的多态



    3、单继承(可突破)的实现



第1点和第3点,其他语言都有,故不赘言



第二点,方法的多态,今天我们说一下:



方法的多态,最重要的是在方法重载方法重写都存在的情况下确定要调用哪一个方法。







方法调用阶段的唯一任务就是 确定被调用方法的版本(即调用哪一个方法) ,暂时不涉及方法内部的具体运行过程。



class文件的编译过程中不包含传统编译中的连接步骤,一切方法调用在class文件中存储的都是符号引用,而不是方法在实际运行时内存布局中的入口地址,这使得java有着更强大的动态扩展能力,但也使得java方法的调用过程变得相对复杂起来,需要在类的加载甚至运行期间才能确定目标方法的直接引用。



JAVA的调用方式有两种:解析调用分派调用

解析调用



        之前说到,所有方法在class文件里面都是一个常量池中的符号引用,在 类加载的解析阶段 ,会将其中的一部分符号引用转化为直接引用,这种解析能成立的前提是, 方法在程序真正运行之前就有一个可确定的调用版本,并且这个方法的调用版本在运行期是不可改变的 。



符合这个条件的有 静态方法,私有方法,实例构造器和父类方法 四类,它们在 类加载的时候会把符号引用解析为该方法的直接引用。



解析调用一定是一个静态的过程,编译期间就完全确定,在类装载的解析阶段就会把涉及到的符号引用全部转化为可确定的直接引用,不会延迟到运行期间再去完成。



分派调用 :分派调用可能是静态的也可能是动态的,根据分派依据的宗量数又可分为单分派和多分派。分派机制与java的多态机制关系密切。



             1.静态分派 : 依赖静态类型来定位方法执行版本的分派动作,称为静态分派。静态分派的最典型的应 用就是方法重载。静态分派发生在编译阶段,因此确定静态分派的动作实际上不是由虚拟机来执行的



             2.动态分派: 在运行期间根据实际类型来确定方法执行版本的分派调用过程称为动态分派。这跟多态性的另一个体现——重写有着很密切的关联。



             3.单分派: 根据一个宗量对目标方法进行选择



             4.多分派: 根据多于一个的总量对目标方法进行选择。



    注:方法的接收者与方法的参数统称为方法的宗量





JVM提供了4条方法调用的字节码指令:

    invokestatic:调用静态方法

    invokespecial:调用实例构造器<init>方法,私有方法和父类方法

    invokevirtual:调用所有的虚方法

    invokeinterface:调用接口方法,会在运行时再确定一个实现此接口的对象。



除此以外(除静态方法,实例构造器,私有方法,父类方法以外)其他方法称为虚方法。





单分派多分派

方法的接收者与方法的参数统称为方法的宗量。



根据分派基于多少种宗量,可以将分派划分为单分派和多分派两种



单分派是根据一个宗量对目标方法进行选择,

多分派是根据多于一个宗量对目标方法进行选择。

————————————————————————————————————————————————————————————————-



一般的JAVA调用中,同时有重载和重写发生的情况







1、根据之前方法调用可能生成的4种字节码,找到对应方法可能生成的字节码,再根据字节码解析过程进行判断。



2、首先进行静态分派,生成相应的字节码,在常量池中生成对应的方法符号引用,这个过程根据了两个宗量进行选择(接收者和参数),因此静态分派是多分派类型。



3、再进行动态分派,将符号引用变成直接引用时,只对方法的接收者进行选择,因此只有一个宗量,动态分派是单分派。



————————————————————————————————————————————————————————————————-







理解JAVA方法调用过程,有利于理解JAVA中:多态和继承的实现原理









더보기

[KANMARS原创] - JETTY服务器WEBAPPCONTEXT详解

<


1.new WebAppContext()


    1.1    private MetaData _metadata=new MetaData();



    1.2 调用构造方法


        ServletContextHandler(HandlerContainer parent, String contextPath, SessionHandler sessionHandler, SecurityHandler securityHandler, ServletHandler servletHandler, ErrorHandler errorHandler)

            初始化    ContextHandler._scontext = new Context();

            设置    _sessionHandler        即使为空

            设置    _securityHandler    即使为空

            设置    _servletHandler        即使为空

2、经server._handler._beans.start调用   – >WebAppContext(AbstractLifeCycle).start()

    2.1    WebAppContext._metadata.setAllowDuplicateFragmentNames(isAllowDuplicateFragmentNames());

    2.2    WebAppContext.doStart()

    2.2.1    WebAppContext.preConfigure()            //预先配置


    2.2.1.1    WebAppContext.loadConfigurations    //加载配置信息-》



                    用sun.misc.Launcher$AppClassLoader的类加载器预先加载储存于dftConfigurationClasses的class信息,并且初始化到_configurations[i]中



                    _configurations[i]=(Configuration)Loader.loadClass(this.getClass(), _configurationClasses[i]).newInstance();



                    这些类包括:



                    ”org.eclipse.jetty.webapp.WebInfConfiguration”        WEBINFO文件解压等处理



                    ”org.eclipse.jetty.webapp.WebXmlConfiguration”        WebXml配置文件读取



                    ”org.eclipse.jetty.webapp.MetaInfConfiguration”        根据webxml生成filter,servlet等对象



                    ”org.eclipse.jetty.webapp.FragmentConfiguration”        未知,但似乎没什么用    



                    ”org.eclipse.jetty.webapp.JettyWebXmlConfiguration”    未知,但似乎某种情况下会起到什么用处



    2.2.1.2    WebAppContext.loadSystemClasses    //加载系统类



                    设置private ClasspathPattern _systemClasses = new ClasspathPattern(dftSystemClasses);



                    而dftSystemClasses=



                    public final static String[] dftSystemClasses =

{

        “java.”,                            // Java SE classes (per servlet spec v2.5 / SRV.9.7.2)

        “javax.”,                           // Java SE classes (per servlet spec v2.5 / SRV.9.7.2)

        “org.xml.”,                         // needed by javax.xml

        “org.w3c.”,                         // needed by javax.xml

        “org.apache.commons.logging.”,      // TODO: review if special case still needed

        “org.eclipse.jetty.continuation.”,  // webapp cannot change continuation classes

        “org.eclipse.jetty.jndi.”,          // webapp cannot change naming classes

        “org.eclipse.jetty.plus.jaas.”,     // webapp cannot change jaas classes

        “org.eclipse.jetty.websocket.WebSocket”, // WebSocket is a jetty extension

        “org.eclipse.jetty.websocket.WebSocketFactory”, // WebSocket is a jetty extension

        “org.eclipse.jetty.websocket.WebSocketServlet”, // webapp cannot change WebSocketServlet

        “org.eclipse.jetty.servlet.DefaultServlet” // webapp cannot change default servlets

    } ;



    2.2.1.3    WebAppContext.loadServerClasses()    //加载服务类



                   设置private ClasspathPattern _serverClasses = new ClasspathPattern(dftServerClasses);



                    而dftServerClasses=



public final static String[] dftServerClasses =

    {

        “-org.eclipse.jetty.continuation.”, // don’t hide continuation classes

        “-org.eclipse.jetty.jndi.”,         // don’t hide naming classes

        “-org.eclipse.jetty.plus.jaas.”,    // don’t hide jaas classes

        “-org.eclipse.jetty.websocket.WebSocket”, // WebSocket is a jetty extension

        “-org.eclipse.jetty.websocket.WebSocketFactory”, // WebSocket is a jetty extension

        “-org.eclipse.jetty.websocket.WebSocketServlet”, // don’t hide WebSocketServlet

        “-org.eclipse.jetty.servlet.DefaultServlet”, // don’t hide default servlet

        “-org.eclipse.jetty.servlet.listener.”, // don’t hide useful listeners

        “org.eclipse.jetty.”                // hide other jetty classes

    } ;



    2.2.1.4    创建WebAppClassLoader WebAppClassLoader classLoader = new WebAppClassLoader(this);



    2.2.1.4.1    按照如下构造参数顺序构造URLClassLoader



                            WebAppClassLoader构造参数中的parent->Classloader



                            Thread.currentThread().getContextClassLoader()



                            WebAppClassLoader.class.getClassLoader()



                            ClassLoader.getSystemClassLoader()



    2.2.1.5    WebAppContext.preConfigure().        最后一步    configurations[i].preConfigure(this);调用2.2.1.1生成的对象中的preConfigure方法



    2.2.1.5.1    WebInfConfiguration.findWorkDirectory()        查找context是否已经设置了webINF的参数



                    //如果有,就直接使用



    2.2.1.5.2    WebInfConfiguration.resolveTempDirectory().makeTempDirectory        //在用户的个人临时文件夹目录创建文件夹    new File(System.getProperty(“java.io.tmpdir”))           



                    context.setTempDirectory(tmpDir);



                    文件夹的创建规则,可以参考    resolveTempDirectory方法的文档



                    A. Try to use an explicit directory specifically for this webapp:






  1.  Iff an explicit directory is set for this webapp, use it. Do NOT set delete
    on exit.


  2. Iff javax.servlet.context.tempdir context attribute is set for this webapp
    && exists && writeable, then use it. Do NOT set delete on exit.





                    B. Create a directory based on global settings. The new directory will be
called “Jetty“+host+”“+port+”__”+context+”“+virtualhost Work out where to
create this directory:






  1. Iff $(jetty.home)/work exists create the directory there. Do NOT set delete
    on exit. Do NOT delete contents if dir already exists.


  2. Iff WEB-INF/work exists create the directory there. Do NOT set delete on
    exit. Do NOT delete contents if dir already exists.


  3. Else create dir in $(java.io.tmpdir). Set delete on exit. Delete contents if
    dir already exists.













    2.2.1.5.3    WebInfConfiguration.unpack (context);



    2.2.1.5.3.1                    web_app = context.newResource(war);               



    2.2.1.5.3.1.1                       return  Resource.newResource(urlOrPath);          URL = file.toURI().toURL()        file:/E:/webapp.war        返回了一个FileResources



    2.2.1.5.3.2                    Resource jarWebApp = JarResource.newJarResource(web_app);    将FileResources转化为一个jarsource        采用方式为将file:/E:/webapp.war修改为jar:file:/E:/webapp.war~/



    2.2.1.5.3.3        context.getTempDirectory(), “.extractlock”位置生成一个控制锁



    2.2.1.5.3.4        extractedWebAppDir.mkdir();        extractedWebAppDir即为临时文件夹



                            例如C:\Documents and Settings\Administrator\Local Settings\Temp\jetty-0.0.0.0-8080-webapp.war--any-\webapp



    2.2.1.5.3.5        jar_web_app.copyTo(extractedWebAppDir);    jar资源,即war包进行解,拷贝到extractedWebAppDir即临时目录中



    2.2.1.5.3.6        删除控制锁context.getTempDirectory(), “.extract_lock”



    2.2.1.5.3.7        context.setBaseResource(web_app);        设置context的基础资源位置是刚才申请的临时文件夹



    2.2.1.5.4            对父类的container进行处理    把父类依赖的jar包加入当前的上下文classloader中    //Apply ordering to container jars - if no pattern is specified, we won’t match any of the container jars



                            最终执行的方法context.getMetaData().addContainerJar(Resource.newResource(uri));



    2.2.1.5.5            对WEBINF的jar包进行处理



                            最终执行的方法context.getMetaData().addWebInfJar(Resource.newResource(uri));



    2.2.1.5.5.1            List<Resource> jars = findJars(context);    获取到web-inf/lib目录下的所有jar包



                            调用2.2.1.5.5执行webInfJarNameMatcher.match(webInfPattern, uris, true)



                            最终调用context.getMetaData().addWebInfJar(Resource.newResource(uri));,将web-inf/lib下的jar包或者zip包加入classpath







    2.2.1.5.6    WebXmlConfiguration.preConfigure    预处理webxml



    2.2.1.5.6.1    String defaultsDescriptor = context.getDefaultsDescriptor();    解析    webdefault.xml    org/eclipse/jetty/webapp/webdefault.xml



    2.2.1.5.6.2    context.getMetaData().setDefaults (dftResource);    给MetaData设置webdefault.xml配置



    2.2.1.5.6.2.1    MetaData._webDefaultsRoot =  new DefaultsDescriptor(webDefaults); 



    2.2.1.5.6.2.1.1    _webDefaultsRoot.parse();        解析webdefault.xml



    2.2.1.5.6.2.1.1.1    webDescriptor.newParse()        新建一个XmlParser xmlParser=new XmlParser()    底层为SAXParserFactory



    2.2.1.5.6.2.1.1.2    在xmlParse中注册dtd和URL的关系



    2.2.1.5.6.2.1.1.3    webDescriptor._root = _parser.parse(_xml.getInputStream())        将webdefault.xml解析为一个Node对象



    2.2.1.5.6.2.1.1.4    webDescriptor.processVersion    ,解析webdefault.xml中的版本号、metadata-complete(是否启用注解)



    2.2.1.5.6.2.1.1.5    webDescriptor.processOrdering    解析如下参数



                                absolute-ordering    是否WebFragment要排序



    2.2.1.5.6.3    Resource webxml = findWebXml(context);        寻找web.xml,解析,但是不执行



    2.2.1.5.6.4    //parse but don’t process override-web.xml     



 



    2.2.1.5.7    MetaInfConfiguration.preConfigure    预处理MetaINF



    2.2.1.5.7.1    //Merge all container and webinf lib jars to look for META-INF resources    将所有ContainerJars和WEBINF jars进行合并



    2.2.1.5.7.2    JarScanner scanner新建jar包扫描类



    2.2.1.5.7.3    scanner扫描WEBINF下的文件,如果是:web-fragment.xml和META-INF/resources/或者以DTD结尾,则分别加载到



                        addResource(context,METAINF_FRAGMENTS,Resource.newResource(jarUri));



                        addResource(context,METAINF_RESOURCES,Resource.newResource(“jar:”+jarUri+”!/META-INF/resources”));

                        addResource(context,METAINF_TLDS,Resource.newResource(“jar:”+jarUri+”!/“+name));



                        中



    2.2.1.5.8    FragmentConfiguration.preConfigure    预处理Fragment



    2.2.1.5.8.1    findWebFragments(context, context.getMetaData());,最终完成的是



                    metaData.addFragment(frag, Resource.newResource(frag.getURL()+”/META-INF/web-fragment.xml”));    



                    metaData.addFragment(frag, Resource.newResource(“jar:”+frag.getURL()+”!/META-INF/web-fragment.xml”));



   



    2.2.1.5.9    JettyWebXmlConfiguration.preConfigure    预处理jetty的webxml        空



                    



    2.2.1.6    WebAppContext.super.doStart()        ContextHandler.doStart()    



    2.2.1.6.1    设置当前线程的类加载器为WebAppClassLoader



    2.2.1.6.2    设置 contexthandler._mimeTypes = new MimeTypes()



    2.2.1.6.3    设置当前线程的线程局部变量context.set(_scontext);



    2.2.1.6.4    调用startContext方法,即调用WebAppContext.startContext()



    2.2.1.6.4.1    WebAppContext.configure()



    2.2.1.6.4.2    调用2.2.1.1五个变量的configure方法



        



                    ”org.eclipse.jetty.webapp.WebInfConfiguration”        WEBINFO文件解压等处理



                    ”org.eclipse.jetty.webapp.WebXmlConfiguration”        WebXml配置文件读取



                    ”org.eclipse.jetty.webapp.MetaInfConfiguration”        根据webxml生成filter,servlet等对象



                    ”org.eclipse.jetty.webapp.FragmentConfiguration”        未知,但似乎没什么用    



                    ”org.eclipse.jetty.webapp.JettyWebXmlConfiguration”    未知,但似乎某种情况下会起到什么用处







    2.2.1.6.4.2.1     WebInfConfiguration.configure



    2.2.1.6.4.2.1.1    ((WebAppClassLoader)context.getClassLoader()).addClassPath(classes);    将/WEB-INF/classes增加到classpath中    最终增加到了URLClassLoader中的    private final URLClassPath ucp;上



    2.2.1.6.4.2.1.2    ((WebAppClassLoader)context.getClassLoader()).addJars(lib);                将/WEB-INF/lib中的jar包或者zip包增加到classpath中,    最终增加到了URLClassLoader中的    private final URLClassPath ucp;上



    2.2.1.6.4.2.1.3    Look for extra resource        查找扩展资源



   



    2.2.1.6.4.2.2    WebXmlConfiguration.configure



    2.2.1.6.4.2.2.1    context.getMetaData().addDescriptorProcessor(new StandardDescriptorProcessor());    为MetaData增加webxml描述的处理器,是StandardDescriptorProcessor



    2.2.1.6.4.2.2.2    new StandardDescriptorProcessor()时,需要注册一系列解析器



                    registerVisitor(“context-param”, this.getClass().getDeclaredMethod(“visitContextParam”, signature));

                    registerVisitor(“display-name”, this.getClass().getDeclaredMethod(“visitDisplayName”, signature));

                    registerVisitor(“servlet”, this.getClass().getDeclaredMethod(“visitServlet”, 
signature));

                    registerVisitor(“servlet-mapping”, this.getClass().getDeclaredMethod(“visitServletMapping”,  signature));

                    registerVisitor(“session-config”, this.getClass().getDeclaredMethod(“visitSessionConfig”, 
signature));

                    registerVisitor(“mime-mapping”, this.getClass().getDeclaredMethod(“visitMimeMapping”,  signature));

                    registerVisitor(“welcome-file-list”, this.getClass().getDeclaredMethod(“visitWelcomeFileList”, 
signature));

                    registerVisitor(“locale-encoding-mapping-list”, this.getClass().getDeclaredMethod(“visitLocaleEncodingList”,  signature));

                    registerVisitor(“error-page”, this.getClass().getDeclaredMethod(“visitErrorPage”, 
signature));

                    registerVisitor(“taglib”, this.getClass().getDeclaredMethod(“visitTagLib”,  signature));

                    registerVisitor(“jsp-config”, this.getClass().getDeclaredMethod(“visitJspConfig”, 
signature));

                    registerVisitor(“security-constraint”, this.getClass().getDeclaredMethod(“visitSecurityConstraint”,  signature));

                    registerVisitor(“login-config”, this.getClass().getDeclaredMethod(“visitLoginConfig”, 
signature));

                    registerVisitor(“security-role”, this.getClass().getDeclaredMethod(“visitSecurityRole”,  signature));

                    registerVisitor(“filter”, this.getClass().getDeclaredMethod(“visitFilter”, 
signature));

                    registerVisitor(“filter-mapping”, this.getClass().getDeclaredMethod(“visitFilterMapping”,  signature));

                    registerVisitor(“listener”, this.getClass().getDeclaredMethod(“visitListener”, 
signature));

                    registerVisitor(“distributable”, this.getClass().getDeclaredMethod(“visitDistributable”,  __signature));



                    这些解析器,既是web.xml的解析处理器



    2.2.1.6.4.2.3     MetaInfConfiguration.configure        空



    2.2.1.6.4.2.4     FragmentConfiguration.configure    



    2.2.1.6.4.2.4.1    context.getMetaData().orderFragments()    对Servlet3.0片段Fragment进行排序           



                                    —-需要看protected Ordering _ordering是否有值;



                                    —-如果没有值,则只执行_orderedWebInfJars.addAll(_webInfJars);方法,将webINF的jar全部放到_orderedWebInfJars中  







    2.2.1.6.4.2.5    JettyWebXmlConfiguration.configure



    2.2.1.6.4.2.5.1    在web-inf下寻找jetty8-web.xml,否则寻找web-jetty.xml,



                                XmlConfiguration jetty_config = (XmlConfiguration)context.getAttribute(XML_CONFIGURATION);



                               寻找到之后,调用jetty_config.configure(context);进行解析



    2.2.1.6.4.3    WebAppContext._metadata.resolve(this);    对webAppContext进行解析处理



    2.2.1.6.4.3.1    _origins.clear();



    2.2.1.6.4.3.2    // set the webxml version    给context.getServletContext()设置版本号,即给_scontext设置版本号



    2.2.1.6.4.3.3    执行StandardDescriptorProcessor    p



    2.2.1.6.4.3.3.1    p.process(context,getWebDefault());    解析webdefault.xml    使用StandardDescriptorProcessor解析webdefault.xml中的标签

    2.2.1.6.4.3.3.2    p.process(context,getWebXml())            解析web.xml            使用StandardDescriptorProcessor解析web.xml中的标签



                        举例说明,servlet加载过程:    参见StandardDescriptorProcessor.protected void visitServlet(WebAppContext context, Descriptor descriptor, XmlParser.Node node)方法



                        1、获取ID



                        2、获取servlet-name



                        3、创建ServletHolder,设置servletName为 servlet-name



                        4、将ServletHolder设置入Context中的ServletHandler            org.eclipse.jetty.servlet.ServletHandler    在步骤1.2或者首次调用getServletHandler时创建

                        5、解析init-param    并设置入ServletHolder



                        6、解析servlet-class



                        7、如果servlet-class是jspservlet,则设置初始化参数scratchdir



                        8、如果servlet-class不为空,则



                        8.1    ((WebDescriptor)descriptor).addClassName(servlet_class);        在WebDescriptor中增加一条记录



                        8.2    Origin o = context.getMetaData().getOrigin(servlet_name+”.servlet.servlet-class”);    尝试从缓存中获取servlet_name+”.servlet.servlet-class”



                                如果获取不到,则holder.setClassName(servlet_class);

                                                        context.getMetaData().setOrigin(servlet_name+”.servlet.servlet-class”, descriptor);



                        9、加载load-on-startup参数



                        10、加载security-role-ref参数



                        11、加载run-as参数



                        12、加载async-supported参数



                        13、加载enabled参数



                        14、加载multipart-config参数



    2.2.1.6.4.3.3.3    p.process(context,wd);    解析WebDescriptor      getOverrideWebs()



   



    2.2.1.6.4.4    WebAppContext.super.startContext()        加载父类的startContext



    2.2.1.6.4.4.1    将SessionHandler,SecurityHandler,ServletHandler组成管道队列



    2.2.1.6.4.4.2    将sessionHandler作为第一个管道,设置入WebAppContext(handlerWrapper._handler)



    2.2.1.6.4.4.3    WebAppContext(ServletContextHandler)super.startContext()



    2.2.1.6.4.4.4    WebAppContext().super.doStart()->scopeHandler.dostart()->scopeHandler.doStart()—->>>>>>>>>>…….



    2.2.1.6.4.4.4.1    sessionhandler.start()



    2.2.1.6.4.4.4.2    ConstraintSecurityHandler.start()



    2.2.1.6.4.4.4.3    ServletHandler.start()



    2.2.1.6.4.4.4.3.1    updateNameMappings()    更新_servletNameMap和_servlets数组



    2.2.1.6.4.4.4.3.2    updateMappings()    更新_filterPathMappings和_filterNameMappings,_servletPathMap,



  



    2.2.1.6.4.4.5    WebAppContext(ContextHandler)._errorHandler.start();



    2.2.1.6.4.4.6    callContextInitialized(((ServletContextListener)LazyList.get(_contextListeners, i)), event);    通知监听事件



   



    2.2.1.6.4.4.7    结束    2.2.1.6.4.4.3    WebAppContext(ServletContextHandler)super.startContext()



    2.2.1.6.4.4.8    OK to Initialize servlet handler now                    ServletContextHandler.startContext  –>  _servletHandler.initialize()



    2.2.1.6.4.4.8.1    _filters.start()    



    2.2.1.6.4.4.8.2    servlets[i].start()    ServletHolder.start



    2.2.1.6.4.4.8.2.1    ServletHolder -> Holder -> Holder._class=Loader.loadClass(Holder.class, _className);     加载class类


    2.2.1.6.4.4.8.2.2    checkServletType();    检查servlet类型   


    2.2.1.6.4.4.8.2.3    initServlet();    包括实例化,调用初始化方法等



                     _servlet=newInstance();   



                    _config=new Config();



                    _servlet.init(_config);



    2.2.1.6.5    结束2.2.1.6.4 WebContext.startContext()



    2.2.1.6.6    current_thread.setContextClassLoader(old_classloader);将classloader恢复原样



   



    2.2.1.7    WebAppContext.postConfigure() 



            WebInfConfiguration.postConfigure 空



            WebXmlConfiguration.postConfigure空



            MetaInfConfiguration.postConfigure空



            FragmentConfiguration.postConfigure空



            JettyWebXmlConfiguration.postConfigure空







  —————————至此webAppContext启动完毕











作为Handler的运行过程如下,Servlet对象将请求交给webAppContext执行handler方法,WebAppContext含有三个handler链,顺序为sessionhandler,ConstraintSecurityHandler,ServletHandler



由于sessionhandler和ServletHandler是scopeHandler,而ConstraintSecurityHandler是普通Handler,因此执行顺序如下

    3.1    sessionhandler.doScope()     创建session,对 cookie写出jsessionid



    3.2    ServletHandler.doScope()     根据target,从_servletNameMap中获取到一个ServletHolder    servlet_holder=
(ServletHolder)_servletNameMap.get(target);

                                                    设置到baseRequest.setUserIdentityScope(servlet_holder)中



    3.3    sessionhandler.doHandler()    空,正常后延



    3.4    ConstraintSecurityHandler.doHandler()    未知代码



    3.5    ServletHandler.doHandler()



            ServletHolder servlet_holder=(ServletHolder) baseRequest.getUserIdentityScope();    公益企业ServletHolder



            FilterChain    获取过滤器链



            执行过滤器链



            如果过滤器链执行完毕,执行servlet_holder.handle(baseRequest,req,res);



            即:servlet.service(request,response);







———————————至此WebAppContext运行完毕







以上就是花三天时间整理的jetty-webAppContext运行过程



———–



对于我自己,要把代码忘掉,记住核心的部分。记得太多反而没用。



比如WebAppContext,最核心的部分应该是WebAppClassLoader类对不同的应用环境进行隔离的部分:



    通过类加载器实现了不同应用在同一个进程内的妥善隔离,值得学习。这是一种非常有效的沙盒机制。







还有web.xml的解析部分,通过反射机制实现了每个标签的处理程序







但其中糟粕的地方也挺多,例如WebAppClassLoader被设置到了ThreadLocal变量中,这样意味着:服务器启动只能用单线程启动,否则就会异常。



虽然并没什么太大影响,但是仍然不太建议这么做。













더보기

[KANMARS原创] - JETTY服务器组件UML图


Jetty组件UML图

더보기

[KANMARS原创] - JETTY服务器源码全解析:从Jetty的组件结构,到Jetty是如何运行的


 



今天学习了一下Jetty的代码,版本为V8.1.17.v20150415



做个笔记,以防忘记



比较专业的jetty架构解析,可以参考如下链接



http://my.oschina.net/tryUcatchUfinallyU/blog?disp=1&catalog=300813&sort=time&p=2



http://www.ibm.com/developerworks/cn/web/wa-lo-jetty/



http://ipjmc.iteye.com/blog/1839999



http://www.blogjava.net/DLevin/archive/2014/05/07/413158.html



最好看完这11+1+1+1篇文章之后再看我写的以下内容,否则容易急功近利……







——————————————————————————————————————————————————————————————



——————————————————————————伟大的分割线——————————————————————————————



——————————————————————————————————————————————————————————————







jetty的架构为基于LifyCycle的架构,每个组件都实现了该接口,具有LifyCyle的生命周期



public interface LifeCycle{

    public void start() throws Exception;

    public void stop() throws Exception;

    public boolean isRunning();

    public boolean isStarted();

    public boolean isStarting();

    public boolean isStopping();

    public boolean isStopped();

    public boolean isFailed();

    public void addLifeCycleListener(LifeCycle.Listener listener);

    public void removeLifeCycleListener(LifeCycle.Listener listener);

    public interface Listener extends EventListener

    {

        public void lifeCycleStarting(LifeCycle event);

        public void lifeCycleStarted(LifeCycle event);

        public void lifeCycleFailure(LifeCycle event,Throwable cause);

        public void lifeCycleStopping(LifeCycle event);

        public void lifeCycleStopped(LifeCycle event);

    }

}



通过实现该接口,一个Class类就具有了生命周期,可以作为Jetty的组件来管理



——————————————————————————————————————————————————————————————



——————————————————————————伟大的分割线——————————————————————————————



——————————————————————————————————————————————————————————————



我们看一段简单的代码,这段代码实现了一个简单的web服务器



——————-pom.xml



<dependencies>

        <dependency>

            <groupId>org.eclipse.jetty</groupId>

            <artifactId>jetty-server</artifactId>

            <version>8.1.17.v20150415</version>

        </dependency>

        <dependency>

            <groupId>org.eclipse.jetty</groupId>

            <artifactId>jetty-webapp</artifactId>

            <version>8.1.17.v20150415</version>

        </dependency>

        <dependency>

            <groupId>org.eclipse.jetty</groupId>

            <artifactId>jetty-servlet</artifactId>

            <version>8.1.17.v20150415</version>

        </dependency>

        <dependency>

            <groupId>org.eclipse.jetty</groupId>

            <artifactId>jetty-jsp</artifactId>

            <version>8.1.17.v20150415</version>

        </dependency>

    </dependencies>



——————————main方法



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

        Server server = new Server();

        QueuedThreadPool threadPool = new QueuedThreadPool();

        threadPool.setMinThreads(10);

        threadPool.setMaxThreads(100);

        threadPool.setDetailedDump(false);

        server.setThreadPool(threadPool);

        

        

        SelectChannelConnector selectChannelConnector = new SelectChannelConnector();

        selectChannelConnector.setHost(“0.0.0.0”);

        selectChannelConnector.setPort(8080);

        selectChannelConnector.setMaxIdleTime(3000000);

        selectChannelConnector.setAcceptors(2);

        selectChannelConnector.setStatsOn(false);

        selectChannelConnector.setConfidentialPort(8443);

        selectChannelConnector.setLowResourcesConnections(20000);

        selectChannelConnector.setLowResourceMaxIdleTime(5000);

        

        server.addConnector(selectChannelConnector);

        

        

        WebAppContext webAppContext = new WebAppContext();

        webAppContext.setContextPath(“/“);

        webAppContext.setWar(“E:/workspace/workspace-jetty/webapp/target/webapp.war”);

        server.setHandler(webAppContext);

        server.start();

        server.join();

    }



以上代码即为:把webapp.war作为一个服务发布出去。







——————————————————————————————————————————————————————————————



———————————————————————-Jetty服务器的组成结构————————————————————————————-


——————————————————————————————————————————————————————————————






首先我们来分析jetty的组成结构



    如上一个main方法示例所示:一个jetty服务器由以下四部分组成:



    Connector    ———–      Server      ———–     ThreadPool        ———-      Handler



    从Jetty发布包中的etc/jetty.xml中你可以清楚的看到对应配置   



    如果想启动一个jetty服务器这四个组件必不可少



    如果要想明确一下这四种组件的具体作用,可以大致定义如下:



    1、Connector:常用的是SelectChannelConnector,



                        重要变量如下:



                                        private final SelectorManager _manager = new ConnectorSelectorManager();    –连接选择管理器



                        重要方法如下:



                                        open    打开一个新的SocketChannel通道



                                        accept    尝试accept一个连接,如果发生连接,则将连接注册到SelectorManager中



                                        newConnection    新建一个AsyncHttpConnection



                                        newEndPoint        新建一个SelectChannelEndPoint         



                                        doStart        组件启动方法



    2、Server:Jetty启动类



                        重要变量如下:



                                        private final Container _container=new Container();        组件容器



                                        private ThreadPool _threadPool;                                    线程池

                                        private Connector[] _connectors;                                 连接



                        重要方法如下:



                                        doStart        组件启动方法



                                        doStop        组件停止方法



                                        start            继承自AbstractLifeCycle的启动方法



                                        stop            继承自AbstractLifeCycle的停止方法



    3、ThreadPool:Jetty线程池,常用实现类为QueuedThreadPool



                        重要变量如下:



                                        private final ConcurrentLinkedQueue<Thread> _threads=new ConcurrentLinkedQueue<Thread>();    可用线程



                                        private BlockingQueue<Runnable> _jobs;        需要执行的任务



                                        private Runnable _runnable = new Runnable()……    默认启动任务:从_jobs中poll出一个任务并执行



                        重要方法如下







                                        doStart        组件启动方法



                                        doStop        组件停止方法



                                        dispatch        将job任务增加到执行队列_jobs等待执行



                                        startThread    在调用doStart时触发,启动_minThreads指定个数的“默认线程”_runnable默认任务



    4、Handler:即处理器,Jetty使用了Handler处理器的架构



    参见http://my.oschina.net/tryUcatchUfinallyU/blog/110553



    从设计模板角度来看 Handler 的设计实际上就是一个责任链模式,接口类 HandlerCollection
可以帮助开发者构建一个链,而另一个接口类 ScopeHandler
可以帮助你控制这个链的访问顺序。另外一个用到的设计模板就是观察者模式,用这个设计模式控制了整个 Jetty 的生命周期,只要继承了
LifeCycle 接口,你的对象就可以交给 Jetty 来统一管理了。所以扩展 Jetty
非常简单,也很容易让人理解,整体架构上的简单也带来了无比的好处,Jetty 可以很容易被扩展和裁剪。







    Handler的接口如下:






public interface Handler extends LifeCycle, Destroyable{

    public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)

        throws IOException, ServletException;

    public void setServer(Server server);

    public Server getServer();

    public void destroy();

}






    HandlerContainer接口如下:






public interface HandlerContainer extends LifeCycle{

    public Handler[] getHandlers();

    public Handler[] getChildHandlers();

    public Handler[] getChildHandlersByClass(Class<?> byclass);

    public <T extends Handler> T getChildHandlerByClass(Class<T> byclass);

}






    由代码可知:Handler的作用就是,对Request和Response对象进行处理,使之完成相应的功能。







    示例中的Handler是WebAppContext,此外,Handler还可以是HandlerList和HandlerCollection,其区别在于HandlerList在责任链模式下,如果一个请求被标记为已处理过或者已经报异常,则不会继续处理;而HandlerCollection无论什么情况,会执行所有的Handler。



    对WebAppContext的分析需要较大篇幅,本文不予分析。







——————————————————————————————————————————————————————————————



———————————————————————-Jetty服务器的启动顺序————————————————————————————-


——————————————————————————————————————————————————————————————






接下来我们来分析Jetty的启动顺序,网上的流程图很多,凑巧我的编辑器不能画图,所以我将启动顺序用写的方式写出来。



1、new Server()



    1.1    初始化server对象



    1.2    初始化Container容器



2、new QueuedThreadPool()



    2.1    初始化_threads线程队列



3、server.setThreadPool(threadPool);    对服务器设置线程池



    3.1    调用server的祖宗类AggregateLifeCycle.addBean方法,将bean注册入_beans



    3.2    _container.addBean(threadPool)        ——————–JettyV8.17版本似乎有BUG?此处代码会判断_listeners为0时不能加入对象,类似“空腹吃饭有害健康”的笑话。



4、new SelectChannelConnector()    新建一个ChannelConnector



    4.1    初始化    private final SelectorManager _manager = new ConnectorSelectorManager();    



    4.2    调用addBean方法将_manager注册到SelectChannelConnector的祖宗类AggregateLifeCycle._beans中



    4.3    设置  int  _acceptors    根据(Runtime.getRuntime().availableProcessors+3)/4设置_acceptor的数量



5、server.addConnector(selectChannelConnector);    对服务器增加Connector



    5.1    更新server._connectors    数组对象为新的connector数组



6、new WebAppContext()    新建Handler    比较复杂,不在此说明







7、server.setHandler(webAppContext);    



    7.1    _handler=handler赋值为hander



    7.2    handler.setServer(getServer());    建立server和handler的连接关系



8、server.start();启动Jetty服务器



    8.1    server调用继承自AbstractLifeCycle的start方法



    8.1.1    server调用继承自AbstractLifeCycle的setStarting()方法



    8.1.2    server调用自身实现的抽象方法dostart



    8.1.2.1    server.dostart方法中ShutdownMonitor.getInstance().start()启动停机监控



    8.1.2.2    server.dostart方法中HttpGenerator设置服务器版本号8.1.17.v20150415



    8.1.2.3    server.dostart方法中super.doStart();



    8.1.2.3.1    server的父类HandlerWrapper.doStart(),调用父类doStart



    8.1.2.3.1.1    如果server的_handler不为空,则执行_handler.start();        ——————————–



    8.1.2.3.1.2    调用server的父类HandlerWrapper的父类AbstractHandler的父类AggregateLifeCycle的doStart方法



                        8.1.2.3.1.2.1    循环调用_beans.start()方法-》触发所有通过server.addBean注册到_beans中的组件的继承自LifeCycle的start方法



                        8.1.2.3.1.2.2    设置server对象的已启动标志_started为true



    8.1.2.3.1.3    调用server的父类HandlerWrapper的父类AbstractHandler的父类AggregateLifeCycle的父类AbstractLifeCycle的dostart方法



    8.1.2.4    server.dostart方法中:由于server.addConnector时,没有addBean,所以在8.1.2.3.1.2.1步骤没有调用connector的start方法



                    因此,server.dostart中,循环调用_connectors.start



    8.1.3    server调用继承自AbstractLifeCycle的setStarted()方法

    8.2    server调用继承自AbstractLifeCycle的start结束



9、接步骤8.1.2.3.1.1启动Handler继承自AbstractLifeCycle的start方法



10、接步骤8.1.2.3.1.2启动AggregateLifeCycle._beans中注册的LifyCycle



    10.1    启动步骤3.1通过server.addBean注册到AggregateLifeCycle._beans中的LifeCycle->QueuedThreadPool.start



    10.1.1    调用_beans.start,即QueuedThreadPool.start



    10.1.2    QueuedThreadPool调用继承自父类AbstractLifeCycle的start方法



    10.1.2.1    QueuedThreadPool调用继承自父类AbstractLifeCycle的setStarting方法



    10.1.2.2    QueuedThreadPool调用自身实现的doStart方法



    10.1.2.2.1    QueuedThreadPool调用继承自父类AbstractLifeCycle的doStart方法



    10.1.2.2.2    QueuedThreadPool如果_jobs,任务队列为空,则对任务队列赋初始值ArrayBlockingQueue或者BlockingArrayQueue



    10.1.2.2.3    QueuedThreadPool调用循环while(isRunning() && threads<_minThreads),新建_minThreads



    10.1.2.2.3.1    QueuedThreadPool循环初始化线程时,调用startThread方法,新建线程



    10.1.2.2.3.1.1    QueuedThreadPool.startThread调用newThread(_runnable)方法,创建一个实现了_runable接口的线程



                            备注:_runable接口功能为为从_jobs中取出一个任务,并且调用该任务的_job.run方法



    10.1.2.2.3.1.2    启动新创建的_runable线程



    10.1.2.2.4    QueuedThreadPool结束调用doStart方法



    10.1.2.3    QueuedThreadPool调用继承自父类AbstractLifeCycle的setStarted方法



    10.1.3    QueuedThreadPool结束调用继承自父类AbstractLifeCycle的start方法



11、接步骤8.1.2.4,server.doStart方法中,启动Connector组件,调用try{_connectors[i].start();}



    (由于_connector没有注册到AggregateLifeCycle._beans中,也有可能是故意为之,使connector最后执行)



    11.1    SelectChannelConnector调用继承自父类AbstractLifeCycle的start方法



    11.1.1    SelectChannelConnector调用继承自父类AbstractLifeCycle的setStarting方法



    11.1.2    SelectChannelConnector调用自身实现的doStart方法



    11.1.2.1    SelectChannelConnector调用父类AbstractConnector的doStart方法



    11.1.2.2    SelectChannelConnector调用自身实现的open方法



    11.1.2.2.1    SelectChannelConnector初始化ServerSocketChannel _acceptChannel;



    11.1.2.2.2    SelectChannelConnector将ServerSocketChannel _acceptChannel绑定到指定端口new InetSocketAddress(getPort())

    11.1.2.2.3    SelectChannelConnector调用AggregateLifeCycle.addBean方法,将_acceptChannel注册入AggregateLifeCycle._beans



    11.1.2.3    SelectChannelConnector结束调用自身实现的open方法



    11.1.2.4    SelectChannelConnector调用父类AbstractConnector的父类AggregateLifeCycle的doStart方法



    11.1.2.5    SelectChannelConnector的祖宗类AggregateLifeCycle检查_beans是否已经全部启动,如果没有启动,则调用start方法



    11.1.2.5.1    在步骤4.2中,ConnectorSelectorManager被注册到了SelectChannelConnector的祖宗类AggregateLifeCycle._beans中,此处SelectChannelConnector的隐含对象ConnectorSelectorManager的start方法被调用



    11.1.2.5.2    ConnectorSelectorManager调用继承自祖宗类AbstractLifeCycle的.start方法



    11.1.2.5.3    ConnectorSelectorManager调用继承自祖宗类AbstractLifeCycle的.setStarting方法



    11.1.2.5.4    ConnectorSelectorManager调用继承自父类SelectorManager实现的.doStart()方法



    11.1.2.5.4.1    ConnectorSelectorManager的父类SelectorManager初始化_selectSet[]数组为新的SelectSet数组



    11.1.2.5.4.2    ConnectorSelectorManager的父类SelectorManager调用父类AbstractLifeCycle.doStart()方法,空方法



    11.1.2.5.4.3    SelectorManager.doStart中对SelectSet进行循环



    11.1.2.5.4.3.1    创建新的Runable接口对象”循环调用SelectSet.doSelect”



    11.1.2.5.4.3.2    将Runable接口对象通过调用ConnectorSelectorManager.dispatch方法,委托给QueuedThreadPool执行



    11.1.2.5.5    ConnectorSelectorManager结束调用继承自父类SelectorManager实现的.doStart()方法



    11.1.2.5.6    ConnectorSelectorManager调用继承自祖宗类AbstractLifeCycle的.setStarted方法



    11.1.2.6    SelectChannelConnector的祖宗类AggregateLifeCycle设置_started启动标志为已启动



    11.1.2.7    SelectChannelConnector的祖宗类AggregateLifeCycle调用父类AbstractLifeCycle.doStart()空方法



    11.1.2.8    SelectChannelConnector结束调用父类AbstractConnector的父类AggregateLifeCycle的doStart方法



    11.1.2.9    SelectChannelConnector结束调用父类AbstractConnector的doStart方法



    11.1.2.10    SelectChannelConnector根据_acceptorThreads配置,创建相应数量的Acceptor委托给_threadPool执行



    11.1.3    SelectChannelConnector结束调用自身实现的doStart方法



    11.2    SelectChannelConnector调用继承自父类AbstractLifeCycle的setStarted方法



    11.3    SelectChannelConnector的start结束。



12、接步骤11.1.2.10,SelectChannelConnector根据_acceptorThreads配置,创建相应数量的Acceptor委托给_threadPool执行



    12.1    AbstractConnector的内部类Acceptor开始运行



    12.2    Acceptor调用accept方法(由于是SelectorChannelConnector创建了父类AbstractConnector的内部类Acceptor对象,则Acceptor对象调用的AbstractConnector的抽象方法accept,最终调用的是SelectorChannelConnector的accept方法)



    12.3    Acceptor调用SelectorChannelConnector的accept方法



    12.4    SelectorChannelConnector.accept方法中开始accept阻塞SocketChannel channel = server.accept();



    12.5    客户端发起连接



    12.6    阻塞释放



    12.7    SelectorChannelConnector.accept方法中,调用_manager.register(channel);,即SelectorManager.register(SocketChannel channel)



    12.8    用取余算法随机取一个SelectorManager._selectSet[i]的SelecSet

    12.9    将变更事件放入SelectSet中,调用wakup函数唤醒在SelectSet上睡眠的线程



13、接步骤11.1.2.5.4.3.2    将Runable接口对象”循环调用SelectSet.doSelect”通过调用ConnectorSelectorManager.dispatch方法,委托给QueuedThreadPool执行



    13.1    SelectSet调用doSelect方法



    13.2    从SelectSet内部对象ConcurrentLinkedQueue<Object> _changes变更事件队列中poll出一个事件



    13.2.1    如果poll出的事件是EndPoint,进行相应处理



    13.2.2    如果poll出的事件是ChannelAndAttachment,进行相应处理



    13.2.3    如果poll出的事件是ChangeTask,则直接运行



    13.2.4    如果poll出的事件是Runnable,则委托给线程池运行



    13.2.5    如果poll出的事件是SocketChannel



    13.2.5.1    在当前SelectSet的专用Selector上注册一个channel的read事件    



    13.2.5.2    调用createEndPoint方法创建一个SelectChannelEndPoint



    13.2.5.2.1    调用newEndPoint方法,创建一个SelectChannelEndPoint



    13.2.5.2.2    调用ConnectorSelectorManager.newEndPoint方法,return SelectChannelConnector.this.newEndPoint(channel,selectSet,sKey);



    13.2.5.2.3    SelectChannelEndPoint endp= new SelectChannelEndPoint(channel,selectSet,key, SelectChannelConnector.this._maxIdleTime);



    13.2.5.2.4    endp设置Connection为selectSet.getManager().newConnection(channel,endp, key.attachment())



    13.2.5.2.4.1    调用ConnectorSelectorManager.newConnection方法,创造一个new AsyncHttpConnection(SelectChannelConnector.this,endpoint,getServer());



                    内部已经生成一系列解析HTTP的工具,如:



                    HttpBuffersImpl _buffers = new HttpBuffersImpl();



                    protected final Parser _parser;



                    protected final Request _request;

                    protected final HttpFields _requestFields;



                    protected final Generator _generator;



                    protected final HttpFields _responseFields;



                    protected final Response _response;        等



    13.2.5.3    调用key.attach(endpoint);将SelectChannelEndPoint附加到channel读事件的key上



    13.2.5.4    调用SelectChannelEndPoint.schedule()



    13.2.5.4.1    正常情况下,调用SelectChannelEndPoint.dispatch



    13.2.5.4.2    调用_manager.dispatch(_handler);即ConnectorSelectorManager.dispatcher方法,将_handler交给线程池执行



                        _handler接口如下



                    private final Runnable _handler = new Runnable()

                    {

                        public void run() { handle(); }

                    };



    13.2.5.4.3    即:线程池会运行_handler接口,调用SelectChannelEndPoint.handle方法



    13.2.5.4.3.1    调用AsyncConnection next = (AsyncConnection)_connection.handle();    此处的AsyncConnection是在步骤13.2.5.2.4.1中生成



    13.2.5.4.3.1.1    调用AsyncHttpConnection.handle()方法



    13.2.5.4.3.1.2    调用AsyncHttpConnection的父类AbstractHttpConnection的类变量_parser的parseAvailable()方法



    13.2.5.4.3.1.2.1    调用_parser的parseNext()方法



    13.2.5.4.3.1.2.2    生成_buffer=getHeaderBuffer();–>从AsyncHttpConnection中获取new 时初始化的buffer



    13.2.5.4.3.1.2.3    调用_parser的fill()方法给_buffer填充数据



    13.2.5.4.3.1.2.3.1    调用_endp.fill(_buffer),即SelectChannelEndPoint.fill(_buffer)



    13.2.5.4.3.1.2.3.2    调用SelectChannelEndPoint的父类ChannelEndPoint.fill(_buffer)方法



    13.2.5.4.3.1.2.3.3    调用SelectChannelEndPoint的父类ChannelEndPoint的_channel.read(bbuf)方法填充数据,即:SocketChannelImpl.fill(bbuf)



    13.2.5.4.3.1.2.3.4    结束调用_endp.fill(_buffer),即SelectChannelEndPoint.fill(_buffer)



    13.2.5.4.3.1.2.4    结束调用_parser的fill()方法给_buffer填充数据



    13.2.5.4.3.1.2.5    _parser开始解析http报文(起始代码HttpParse.java 343行while (_state<STATE_END && length–>0))



                                此处Http报文解析写的很经典,通过定义一定的状态位,控制解析报文的状态,从-14状态直至最终结束,推荐学习之,虽然这种写法很奇葩……



                                让我想起了以前我有幸参观的伟大的、独一无二的、软件定制巨头南天公司的一伙人写的一个配置文件的解析,也是一个while循环,读取配置文件






    // States

    public static final int STATE_START=-14;

    public static final int STATE_FIELD0=-13;

    public static final int STATE_SPACE1=-12;

    public static final int STATE_STATUS=-11;

    public static final int STATE_URI=-10;

    public static final int STATE_SPACE2=-9;

    public static final int STATE_END0=-8;

    public static final int STATE_END1=-7;

    public static final int STATE_FIELD2=-6;

    public static final int STATE_HEADER=-5;

    public static final int STATE_HEADER_NAME=-4;

    public static final int STATE_HEADER_IN_NAME=-3;

    public static final int STATE_HEADER_VALUE=-2;

    public static final int STATE_HEADER_IN_VALUE=-1;

    public static final int STATE_END=0;

    public static final int STATE_EOF_CONTENT=1;

    public static final int STATE_CONTENT=2;

    public static final int STATE_CHUNKED_CONTENT=3;

    public static final int STATE_CHUNK_SIZE=4;

    public static final int STATE_CHUNK_PARAMS=5;

    public static final int STATE_CHUNK=6;

    public static final int STATE_SEEKING_EOF=7;






                                通过状态位的逐渐提升,逐步完成了method,url,version,header……等一系列报文的解析



                                以jetty8.17版本为例:



                                HttpParser379行完成Method解析



                                HttpParser438行完成URI解析



                                HttpParser491行完成对AbstractHttpConnection的request信息:Method,Uri,Protoco;的注入



                                                        通过调用AbstractHttpConnection.startRequest(Buffer method, Buffer uri, Buffer version)注入三个信息



                                HttpParser520,522行,完成了一对Header和value的解析



                                HttpParser596行,完成了_hander对Header的注入



                                                        通过调用AbstractHttpConnection.parsedHeader(Buffer name, Buffer value)



                                                        在_requestFields中add(name,value)

    13.2.5.4.3.1.2.6    在HttpParser644行—-》在未知response状态的情况下,假设_contentLength=HttpTokens.NO_CONTENT;(619行,原因是:如果头部既没有长度532行又没有549行chunk,就认为是没有内容的,那么就是无长度的)



                                进入644行_handler.headerComplete();



    13.2.5.4.3.1.2.7    调用AbstractHttpConnection.headerComplete()



    13.2.5.4.3.1.2.7.1    调用AbstractHttpConnection.headerComplete()



    13.2.5.4.3.1.2.7.2    设置_generator.setVersion(11)代表http1.1



    13.2.5.4.3.1.2.7.3    进入http1.1的switch处理分支



    13.2.5.4.3.1.2.7.4    进入AbstractHttpConnection.handleRequest分支



    13.2.5.4.3.1.2.7.5    AbstractHttpConnection对uri进行处理,生成path,info



    13.2.5.4.3.1.2.7.6    AbstractHttpConnection调用_request.setPathInfo(info)



    13.2.5.4.3.1.2.7.7    AbstractHttpConnection第494行server.handle(this);调用server方法处理AbstractHttpConnection,实现类为AsyncHttpConnection



    13.2.5.4.3.1.2.7.8    Server调用public void handle(AbstractHttpConnection connection)方法



    13.2.5.4.3.1.2.7.8.1    生成 target,Request,Response对象



    13.2.5.4.3.1.2.7.8.2    调用Server.handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)方法



    13.2.5.4.3.1.2.7.8.3    调用Server._handler.handle(target,baseRequest, request, response)



                                即:WebAppContext.handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)方法



                                ……….



    13.2.5.4.3.1.3    结束调用AsyncHttpConnection的父类AbstractHttpConnection的类变量_parser的parseAvailable()方法



    13.2.5.4.3.1.4    调用_endp.flush(),将输出内容传输到客户端浏览器上。







——————————————————————————————————————————————————————————————



至此Jetty
服务器的启动顺序展示完毕:



上文展示了从Jetty启动、生命周期对象初始化、建立IO监听、到一个客户端发起连接、客户端输入Http报文,输入事件经各组件之间的消息传递、报文交给处理器解析执行、最终交给WebAppCOntext的Handle处理的全过程



从上文调用顺序可以看到,Jetty的模块化十分清晰,结构简单可靠,扩展性强,举个例子,如果你想用Jetty改造一下,做成一个其他协议的通讯框架,仅需在步骤13.2.5.4.3.1上扩展一个自己的Connection即可








——————————————————————————————————————————————————————————————



———————————————————————-Handle处理过程————————————————————————————-


——————————————————————————————————————————————————————————————



下文要说一下Handle处理的过程



关于Handle最好先阅读一下这两篇文章,以补充一下基础知识:



http://my.oschina.net/tryUcatchUfinallyU/blog/112972



http://www.blogjava.net/DLevin/archive/2014/05/07/413158.html



——————————————————————————————————————————————————————————————



Handler接口如下,可以看到,主要执行的是handle方法






public interface Handler extends LifeCycle, Destroyable{

    public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)

        throws IOException, ServletException;

    public void setServer(Server server);

    public Server getServer();

    public void destroy();

}






其子类中比较重要的有:



    HandlerCollection    具有Handler的集合,可以按照顺序全部执行内部的handler



    HandlerList            具有Handler的列表,按照顺序执行内部handler,如果内部发生异常或者request标记为已处理,则不再继续向下执行



    HandlerWrapper     是内部一个_handler的包装,实现了HandlerContainer和LifyCycle接口,具有略微高级一点的功能。



    ScopedHandler       内部有两个方法doScoped和doHandle,类文档如是说:






  <p>For example if Scoped handlers A, B & C were chained together, then

  the calling order would be:<pre>

  A.handle(…)

    A.doScope(…)

      B.doScope(…)

        C.doScope(…)

          A.doHandle(…)

            B.doHandle(…)

               C.doHandle(…)   

  <pre>

 

  <p>If non scoped handler X was in the chained A, B, X & C, then

  the calling order would be:<pre>

  A.handle(…)

    A.doScope(…)

      B.doScope(…)

        C.doScope(…)

          A.doHandle(…)

            B.doHandle(…)

              X.handle(…)

                C.handle(…)

                  C.doHandle(…)  






                但我认为这是一个然并卵的功能:请看ScopedHandler.handle的代码:






public final void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException

    {

        if (_outerScope==null)  

            doScope(target,baseRequest,request, response);

        else

            doHandle(target,baseRequest,request, response);

    }



public final void nextScope(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)

        throws IOException, ServletException

    {

        if (_nextScope!=null)

            _nextScope.doScope(target,baseRequest,request, response);

        else if (_outerScope!=null)

            _outerScope.doHandle(target,baseRequest,request, response);

        else

            doHandle(target,baseRequest,request, response);

    }



public final void nextHandle(String target, final Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException

    {

        if (_nextScope!=null && _nextScope==_handler)

            _nextScope.doHandle(target,baseRequest,request, response);

        else if (_handler!=null)

            _handler.handle(target,baseRequest, request, response);

    }






            关键在于方法中的_nextScope和_outerScope究竟是什么东西



            在SocpeHandler的doStart方法中可以看到:



                _outerScope就是处理序列中第一个doStart的ScopedHandle,而_nextScope是当前ScopedHandle的父类HandleWrapper的实例变量_handler



            换句话说:只有用一种极其奇葩的写法,才能实现如文档说明的效果:参见http://www.blogjava.net/DLevin/archive/2014/05/07/413158.html文档



            N句话总结之:



                1、在实现中,其Handler链表由HandlerWrapper构建,在doStart()方法中计算_nextScope字段以及
_outerScope字段,在handle()方法中,如果_outerScope为null,则调用doScope()方法,否则调用
doHandle()方法;



                2、在执行完doScope()方法后,调用nextScope()方法,该方法顺着_nextScope链表走,直到尽头,后调用doHandle()方法;



                3、而doHandle()方法在完成是调用nextHandle()方法,它也沿着_nextScope链表走,只要_nextScope和
_handler相同,则调用其doHandle()方法,但是如果_nextScope和_handler不同,则调用_handler中的
handle()方法,用于处理在ScopedHandler链表中插入非ScopedHandler的情况



            使用示例可以参见jetty中的testCase,也可以参照下例:






public class App003 {



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

        Server server = new Server();

        QueuedThreadPool threadPool = new QueuedThreadPool();

        threadPool.setMaxThreads(100);

        server.setThreadPool(threadPool);



        SelectChannelConnector selectChannelConnector = new SelectChannelConnector();

        selectChannelConnector.setHost(“0.0.0.0”);

        selectChannelConnector.setPort(8080);

        server.addConnector(selectChannelConnector);

        

        ScopedHandlerA sa = new ScopedHandlerA();

        ScopedHandlerB sb = new ScopedHandlerB();

        ScopedHandlerC sc = new ScopedHandlerC();

        HandlerWrapperA ha = new HandlerWrapperA();

        

        sa.setHandler(sb);

        sb.setHandler(ha);

        ha.setHandler(sc);

       

        server.setHandler(sa);

        server.start();

        server.join();

        

    }

    

    public static class ScopedHandlerA extends ScopedHandler{

        public void doScope(String target, Request baseRequest,

                HttpServletRequest request, HttpServletResponse response)

                throws IOException, ServletException {

            System.out.println(“SHA-Scoped–>”);

            nextScope(target, baseRequest, request, response);

            System.out.println(“<–SHA-Scoped”);

        }

        public void doHandle(String target, Request baseRequest,

                HttpServletRequest request, HttpServletResponse response)

                throws IOException, ServletException {

            System.out.println(“SHA-Handle–>”);

            nextHandle(target, baseRequest, request, response);

            System.out.println(“<–SHA-Handle”);

        }

    }

    

    public static class ScopedHandlerB extends ScopedHandler{

        public void doScope(String target, Request baseRequest,

                HttpServletRequest request, HttpServletResponse response)

                throws IOException, ServletException {

            System.out.println(“SHB-Scoped–>”);

            nextScope(target, baseRequest, request, response);

            System.out.println(“<–SHB-Scoped”);

        }

        public void doHandle(String target, Request baseRequest,

                HttpServletRequest request, HttpServletResponse response)

                throws IOException, ServletException {

            System.out.println(“SHB-Handle–>”);

            nextHandle(target, baseRequest, request, response);

            System.out.println(“<–SHB-Handle”);

        }

    }

    

    public static class ScopedHandlerC extends ScopedHandler{

        public void doScope(String target, Request baseRequest,

                HttpServletRequest request, HttpServletResponse response)

                throws IOException, ServletException {

            System.out.println(“SHC-Scoped–>”);

            nextScope(target, baseRequest, request, response);

            System.out.println(“<–SHC-Scoped”);

        }

        public void doHandle(String target, Request baseRequest,

                HttpServletRequest request, HttpServletResponse response)

                throws IOException, ServletException {

            System.out.println(“SHC-Handle–>”);

            nextHandle(target, baseRequest, request, response);

            System.out.println(“<–SHC-Handle”);

        }

    }

    public static class HandlerWrapperA extends HandlerWrapper{

        public void handle(String target, Request baseRequest,

                HttpServletRequest request, HttpServletResponse response)

                throws IOException, ServletException {

            System.out.println(“h-Handle–>”);

            super.handle(target, baseRequest, request, response);

            System.out.println(“<–h-Handle”);

        }

    }

}



执行结果如下:



SHA-Scoped–>

SHB-Scoped–>

SHC-Scoped–>

SHA-Handle–>

SHB-Handle–>

h-Handle–>

SHC-Handle–>

<–SHC-Handle

<–h-Handle

<–SHB-Handle

<–SHA-Handle

<–SHC-Scoped

<–SHB-Scoped

<–SHA-Scoped






        这种写法就会形成如文档描述的效果,但我个人认为这是一个然并卵的功能:



        它的优点如下:



            1、可以在不同的handler之间集中执行scoped代码,例如配置加载等功能



            2、可以随时选择中断不同层级的scoped运行



        但缺点非常严重



            1、构造方法奇特,需要对Handle,HandleWrapper,ScopedHandle等十分了解



            2、逻辑比较复杂,对嵌套递归写法的熟练度要求是“必须为50%,多一点少一点都不行”,开发人员对递归的熟练度低于50%则看不懂,高于50%则会换其他的写法。



            3、代码组装难懂,需要用多个HandleWrapper才能组装成Handle链,与责任链模式相比堪称四不像结构。



            4、代码使用复杂,必须将handle,doScope,doHandle,nextScope,nextHandle形成正确的顺序,才可以调用成功。







        换做是我,我会把三个scope和2个handler拆分成3*2+2=8个handler,直线结构的程序要比这四处乱跳的jumpto要更加稳固、更容易维护。







    ContextHandle:继承自ScopedHandler,最重要的方法是doScope和doHandle



    ServletContextHandler:继承自ContextHandler,重要的是重写了的ContextHandler.startContext方法



    WebAppContext:继承自ServletContextHandler,重要的是实现了web应用支持的doStart,和从ContextHandle中继承来的doHandle方法。







——————————————————————————————————————————————————————————————



—————————————————————————— 伟大的分割线—————————————————————————————-



——————————————————————————————————————————————————————————————


Jetty服务器的启动、初始化、事件触发、组件消息传送、Handler处理就说到这儿。






以上内容是Jetty的核心部分,其他的附加组件如ajp、annotations、deploy、等都是从这个基础上扩展而来的。



大家如果有深入学习Jetty的需要,最好直接翻看代码,比看文档要好懂的多。

더보기

[KANMARS原创] - DEBUG分析SPRING IOC容器启动过程


以ClassPathXmlApplicationContext为例,分析Spring启动步骤



Spring启动步骤



    1、ClassPathXmlApplicationContext



        1.1    ClassPathXmlApplicationContext.setConfigLocations()    设置配置文件



        1.2    ClassPathXmlApplicationContext.refresh()                    根据配置文件进行刷新



        1.3    AbstractApplicationContext.refresh()



        1.4    AbstractApplicationContext.obtainFreshBeanFactory()    初始化BeanFactory



        1.4.1    AbstractRefreshableApplicationContext.refreshBeanFactory()        刷新BeanFactory



        1.4.2    AbstractRefreshableApplicationContext.createBeanFactory()        创建DefaultListableBeanFactory



        1.4.3    AbstractXmlApplicationContext.loadBeanDefinitions(DefaultListableBeanFactory beanFactory)     给beanFacroty加载BeanDefinition



        1.4.3.1    创建XmlBeanDefinitionReader,    给XmlBeanDefinitionReader设置beanFactory



        1.4.4    AbstractXmlApplicationContext.loadBeanDefinitions(XmlBeanDefinitionReader reader)                通过XmlBeanDefinition加载BeanDefinition



        1.4.4.1    AbstractXmlApplicationContext.getConfigResources()                获取资源配置信息



        1.4.4.2    AbstractXmlApplicationContext.getConfigLocations()                获取资源配置字符串



        1.4.4.2.1    XmlBeanDefinitionReader.loadBeanDefinitions(configLocations)    加载资源配置



        1.4.4.2.2    AbstractBeanDefinitionReader.loadBeanDefinitions(String… locations)    根据资源配置字符串加载beanDefinition



        1.4.4.2.3    AbstractBeanDefinitionReader.loadBeanDefinitions(String location, Set<Resource> actualResources)    根据资源配置字符串加载beanDefinition



        1.4.4.2.4    AbstractBeanDefinitionReader.getResourceLoader()                    获取resourceLoader,即ClassPathXmlApplicationContext



        1.4.4.2.5    AbstractApplicationContext.getResources(String locationPattern)    获取Resources    



        1.4.4.2.6    AbstractApplicationContext.resourcePatternResolver.getResources(String locationPattern)     获取Resources



        1.4.4.2.7    PathMatchingResourcePatternResolver.getResources(String locationPattern)        获取Resources



        1.4.4.2.8    getResourceLoader().getResource(locationPattern)                即ClassPathXmlApplicationContext.getResource(locationPattern)



        1.4.4.2.9    DefaultResourceLoader.getResource(locationPattern)



        1.4.4.2.10    DefaultResourceLoader.getResourceByPath(location)            



        1.4.4.2.11    return new ClassPathContextResource(path, getClassLoader());



        1.4.4.2.12    返回1.4.4.2.3



        1.4.4.2.13    AbstractBeanDefinitionReader.loadBeanDefinitions(Resource… resources)    根据加载出的ClassPathContextResource读取配置



        1.4.4.2.14    XmlBeanDefinitionReader.loadBeanDefinitions(EncodedResource encodedResource)



        1.4.4.2.15    XmlBeanDefinitionReader.doLoadBeanDefinitions(encodedResource.getResource().getInputStream())    从resource中获取输入流,交给下一步执行



        1.4.4.2.16    XmlBeanDefinitionReader.doLoadBeanDefinitions(InputSource inputSource, Resource resource)



        1.4.4.2.17    Document doc = this.documentLoader.loadDocument(

                    inputSource, getEntityResolver(), this.errorHandler, validationMode, isNamespaceAware());



                            加载Document配置



        1.4.4.2.18    XmlBeanDefinitionReader.registerBeanDefinitions(Document doc, Resource resource)    根据Document 来加载配置



        1.4.4.2.19    XmlBeanDefinitionReader.createBeanDefinitionDocumentReader()        即创建DefaultBeanDefinitionDocumentReader



        1.4.4.2.20    documentReader.registerBeanDefinitions(doc, createReaderContext(resource))    注册doc,并且用resource创建上下文



        1.4.4.2.21    DefaultBeanDefinitionDocumentReader.doRegisterBeanDefinitions(doc.getDocumentElement())    执行解析并注册



        1.4.4.2.22    BeanDefinitionParserDelegate delegate = DefaultBeanDefinitionDocumentReader.createDelegate()    创建BeanDefinitionDelegate代理



        1.4.4.2.23    DefaultBeanDefinitionDocumentReader.preProcessXml(root)    空操作



        1.4.4.2.24    DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(root,this.delegate)    用DeanDefinitionParseDelegate代理解析root



        1.4.4.2.25    DefaultBeanDefinitionDocumentReader.processBeanDefinition     用DeanDefinitionParseDelegate代理解析root



        1.4.4.2.26    DefaultBeanDefinitionDocumentReader.processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate)



        1.4.4.2.27    BeanDefinitionHolder bdHolder=delegate.parseBeanDefinitionElement(ele)     解析bdHolder



        1.4.4.2.27.1        AbstractBeanDefinition beanDefinition = BeanDefinitionParserDelegate.parseBeanDefinitionElement(ele, beanName, containingBean)



        1.4.4.2.27.2        BeanDefinitionParserDelegate.createBeanDefinition(className,parent)



        1.4.4.2.27.3        BeanDefinitionReaderUtils.createBeanDefinition()



        1.4.4.2.27.4        BeanDefinitionReaderUtils.createBeanDefinition()            生成BeanDefinition,即:GenericBeanDefinition



        1.4.4.2.28    return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);    返回步骤1.4.4.2.27



        1.4.4.2.29    BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());    



                            第一个参数为1.4.4.2.28生成的holder,第二个参数为DefaultListableBeanFactory



        1.4.4.2.30    registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());



        1.4.4.2.30.1    registry.beanDefinitionNames.add(beanName);



        1.4.4.2.30.2    registry.beanDefinitionMap.put(beanName, beanDefinition);



        1.4.4.2.30.3    registry.resetBeanDefinition(String beanName)    



        1.4.4.2.30.3.1    clearMergedBeanDefinition(beanName);



        1.4.4.2.30.3.2    destroySingleton(beanName);



        1.4.4.2.30.3.3    clearByTypeCache();



        1.4.4.2.30.3.4    if (beanName.equals(bd.getParentName())) {resetBeanDefinition(bdName);}    清除父类的BeanDefinition



        1.4.4.2.30.3    registry.registerAlias(beanName, aliase);



        1.4.4.2.31    DefaultBeanDefinitionDocumentReader.processBeanDefinition()



                            getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));



        1.4.4.2.32    返回步骤1.4.4.2.26



        1.4.4.2.33    DefaultBeanDefinitionDocumentReader.postProcessXml(root)    空操作



        1.4.4.2.34    返回步骤1.4.4.2.20



        1.4.4.2.35    返回步骤1.4.4.2.16



        1.4.4.2.36    返回步骤1.4.4.2.15



        1.4.4.2.37    返回步骤1.4.4.2.14



        1.4.4.2.38    返回步骤1.4.4.2.13



        1.4.4.2.39    返回步骤1.4.4.2.2



        1.4.4.2.40    返回步骤1.4.4



        1.4.5        返回步骤1.4.3



        1.4.6        步骤1.4.3继续    AbstractApplicationContext.obtainFreshBeanFactory()



                        ConfigurableListableBeanFactory beanFactory = getBeanFactory();



                        执行步骤1.4AbstractApplicationContext.obtainFreshBeanFactory()完毕



        1.5        AbstractApplicationContext.prepareBeanFactory()            设置一些初始配置,设置默认bean和BeanPostProcessor    LoadTimeWeaverAwareProcessor



        1.6        AbstractApplicationContext.postProcessBeanFactory()        // Allows post-processing of the bean factory in context subclasses.    空方法



        1.7        AbstractApplicationContext.invokeBeanFactoryPostProcessors()             Instantiate and invoke all registered BeanFactoryPostProcessor beans,



        1.8        AbstractApplicationContext.initMessageSource()                加载国际化信息



        1.9        AbstractApplicationContext.initApplicationEventMulticaster()        加载Spring容器事件体系



        1.10        AbstractApplicationContext.onRefresh()                刷新一些特殊的bean    



        1.11        AbstractApplicationContext.finishBeanFactoryInitialization(beanFactory)    初始化非延时加载的单例bean



        1.11.1        beanFactory.preInstantiateSingletons();        初始化实例



        1.11.2        DefaultListableBeanFactory.preInstantiateSingletons()



        1.11.2.1        RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);    获取到BeanDefinition



        1.11.2.2               DefaultListableBeanFactory.getBean(beanName)        获取bean



        1.11.2.3        AbstractBeanFactory.doGetBean(final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)



        1.11.2.4        Object sharedInstance = getSingleton(beanName);



        1.11.2.5        this.singletonObjects.get(beanName);

        1.11.2.6        mbd.isSingleton()    



                            getSingleton()->createBean()



        1.11.2.6.1        AbstractAutowireCapableBeanFactory.doCreateBean(beanName,mbd, args)



        1.11.2.6.2        AbstractAutowireCapableBeanFactory.resolveBeanClass()



        1.11.2.6.3        Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);



        1.11.2.6.4        BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd)



                                .getInstantiationStrategy().instantiate(mbd, beanName, parent);



        1.11.2.6.5        SimpleInstantiationStrategy.BeanUtils.instantiateClass(constructorToUse);



        1.11.2.6.6        返回1.11.2.6



        1.11.2.7        bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);



        1.11.2.8        返回1.11.2.2



        1.11.2.9        返回1.11.1



        1.11.3        返回1.11



        1.12        beanFactory.preInstantiateSingletons(); 结束



        1.13        AbstractApplicationContext.finishRefresh()



        1.13.1     AbstractApplicationContext.initLifecycleProcessor()                初始化DefaultLifecycleProcessor



        1.13.2    AbstractApplicationContext.getLifecycleProcessor().onRefresh();       运行DefaultLifecycleProcessor



        1.13.3    publishEvent(new ContextRefreshedEvent(this));            getApplicationEventMulticaster().multicastEvent(event);



        1.13.4    LiveBeansView.registerApplicationContext(this);        在LiveBeansView中注册当前的applicationContext



        1.13.5    返回ClassPathXmlApplicationContext



    加载结束











        







        



        



        



        



        

















더보기

[KANMARS原创] - 从零单排-BSR服务器介绍--从0开始构建web服务器










两个月前基于Netty写了一个web服务器框架。



当时候主要的目的是,朋友托我写个支持web通讯的东西,但是现在websocket又不通用,所以只好在服务器上打心思,基于netty写了一个web通讯框架,可以单机轻松实现上万并发。



后来拿出去吹牛,被人鄙视了,被鄙视的缘由是:通讯框架用netty,协议层用netty,日志层用log4j,JSON层用阿里巴巴的jsonlib………是对现有框架的封装,没有任何“自主知识产权”的东西……







于是,抽了一点时间从0开始写了个web服务器,名称是BSR-半兽人,GIT地址位于    https://github.com/kanmars/bsr.git



其特点如下:



    1、整个服务器采用分模块设计,共有:server,event,http,pipe,demo四个模块



    2、通讯层使用NIO实现,使用注册表机制储存链接上下文



    3、链接分发机制采用reactor反应炉模式,由BossThread分发到注册表中,由WorkerThread线程进行后续处理



    4、工作线程处理采用管道Pipe机制,采用管道序列来实现复杂的处理操作,纵向可扩展,扩展能力优秀



    5、支持三种简单管道:



                EchoPipe,回声管道



                HttpProtocolPipe,HTTP协议解析管道



                HttpResourcePipe,HTTP静态资源处理管道



    6、对管道进行顺序组装,可以生成复杂逻辑



    7、HttpProtocolPipe,HTTP协议解析完全独立实现,不依赖现有框架,实现了较为完整的HTTP报文处理,如request,response,session,cookie等



    8、MainDemo.java中是服务器的启动示例



目前的缺点:



    1、功能较为原始



    2、稳定性有待改善



    3、没有参照现有框架如jetty等的设计



下一步可做的进一步优化:



    1、对MainDemo的启动进程进行优化,优化多线程结构



    2、对服务器Bean实现jmx协议,便于远程控制



    3、实现springmvc的处理管道,使程序具有springmvc功能



    4、完善异常机制,使程序稳定运行



    5、对常用资源进行池化操作











下一次的优化,可能就是用c语言写一个了,我一直对自己的设定,是c+java双精通







但是正如我所说的,编程是一个然并卵的行业。

더보기

TB全局变量的用法


TB中GLOBAL变量的用法,相当于List,不再赘言


Params


Vars   

    NumericSeries val;

Begin

val = GetGlobalVar(0);

If(val == InvalidNumeric){

val = 0;

SetGlobalVar(0,100);

}



val = val + 100;

SetGlobalVar(0,val);

//PlotNumeric(“cccc”,val );

FileAppend(“D:\每个BAR序列值.log”,”每个BAR序列值CurrentBar = “+Text(CurrentBar));

PlotNumeric(“dddd”,AvgEntryPrice+3380,0,Green);



End

더보기

学习到了一些东西


在和朋友聊天的过程中学习到了一些东西



做程序化交易:



要明白入场时机、离场时机



更要明白:止损、止盈策略



常用的止损止盈策略有:



        1、幅度止损



        2、固定点位止损



        3、回吐止损



        4、指标止损



        止盈反之



——–



要保住利润,不惜在同一根bar上开平

더보기