1. 程式人生 > >JFinal初始化分析-常量初始化-1

JFinal初始化分析-常量初始化-1

但是 nts 3.0 nal ring 問題 簡單 環境配置 comment

spring自己基本不熟悉,因為超多的xml配置太繁瑣,就放棄了。自己也不是專做開發的,主要工作是運維。jfianl的出現,無xml配置,令人驚喜。

當時就想學一下這個框架的設計,就找博文來讀,但是發現很多博主一遍贊嘆jfinal的強大,一邊說jfinal的設計很簡單,好像每個博主自己都可以設計一套jfinal一樣,但基本每個博主也都是蜻蜓點水的分析一下啟動或某一塊,然後及基本不再寫了。

我自己覺得jfinal很強大,體量雖然很小,但是設計卻不簡單,相反卻很精巧。可以看出波哥不是因為設計而設計。而是以簡單、快速開發為設計核心的。

要自己設計寫一套jfianl框架,沒有較高的水平,很難。自己覺得jfianl框架不像大家認為的這麽簡單,要設計一套這樣的框架絕非容易的事情。

反之自己抱著學習的態度,希望能搞明白裏面的原理,需要時,也能自己造輪子。

這個算是開始吧,希望能堅持,遇到問題時,也希望能得到波哥的指點。

中間件部署web應用時,會加載web.xml配置文件,並依次listener -> filter -> servlet加載。

1、jfinal的web.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://java.sun.com/xml/ns/javaee"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         id="WebApp_ID" version="3.0">

    <filter>
        <filter-name>jfinal</filter-name>
        <filter-class>com.jfinal.core.JFinalFilter</filter-class>
        <init-param>
            <param-name>configClass</param-name>
            <param-value>app.TestConfig</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>jfinal</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

</web-app>

可以看出web.xml配置文件沒有配置監聽、和serlvet,只有一個全局過濾器com.jfinal.core.JFinalFilter,可以說,這個過濾器是第一個被加載的class。

過濾器的生命周期是init()->doFilter()->destroy(),init()放一些初始化的信息,doFilter攔截所有請求,並進行處理。

jfinal號稱無xml配置,只要通過一個class就可以完成所有配置,這個class如下:

public class TestConfig extends JFinalConfig{
    public void configConstant(Constants constants) {
        constants.setDevMode(true);
    }

    public void configRoute(Routes me) {
        me.add("/test",TestController.class);
    }

    public void configEngine(Engine engine) {

    }

    public void configPlugin(Plugins plugins) {

    }
    public void configInterceptor(Interceptors interceptors) {

    }
    public void configHandler(Handlers handlers) {}

    public static void main(String[] args){
        JFinal.start("src/main/webapp",8000,"/j");
    }
}

可以看出,用時繼承JFinalConfig, 實現以下方法,就可以完成配置,如JFinalConfig源碼:

//配置常量
public abstract void configConstant(Constants var1);
//配置路由
public abstract void configRoute(Routes var1);
//未知
public abstract void configEngine(Engine var1);
//配置插件
public abstract void configPlugin(Plugins var1);
//自定義攔截器,
public abstract void configInterceptor(Interceptors var1);
//過濾鏈,就是全局過濾器的過濾鏈
public abstract void
configHandler(Handlers var1);

從上可以看出,只要繼承JFinalConfig,就可以完成自己的配置,這些配置我們先稱為全局環境配置對象(Constants、Routes、Engine、Interceptors、Handlers等),那這些環境配置是什麽時候被實例化的?

2、JFinal配置的加載 在web.xml配置中,過濾器有個參數,ConfigClass,值是app.TestConfig,就是JFconfigClass的子類,也就是自己的配置class.這說明,我們的配置的class是通過web.xml傳遞給了JFinalFilter過濾器的init()方法。

JFinalFilter的基礎代碼,簡化後的:

public class JFinalFilter implements Filter {
private JFinalConfig jfinalConfig;//TestConfig將會賦值給它。
public void init(FilterConfig filterConfig) {
    createJFinalConfig(filterConfig.getInitParameter("configClass"));
}
}

createJFinalConfig的內部實現就是

jfinalConfig =(jfinalConfig)Class.forName("app.TestConfig").newInstance();

這樣就new 了一個app.TestConfig的實例,但是只是實例,並沒有調用裏面的幾個方法,所以方法中的傳遞的環境配置對象還是空的。比如TestConfig:

public void configConstant(Constants constants) {
        constants.setDevMode(true);
}

並沒有被執行,所以constants還是空的。這裏涉及兩個問題:

1、誰調用configConstant()方法,並傳遞了Constants 實例對象?

2、Constants 實例化後,如何使用Constants 實例對象?

我們基本可以考慮,這些相關配置對象應該只會被初始化一次,不可能被反復new 出新的對象。那麽可以猜測這些配置的對象應該是單實例,或者static final的來初始化的。

繼續往下看,可以看到是JFinal.init完成了對這些configConstant()方法的調用。

public class JFinalFilter implements Filter {
private JFinalConfig jfinalConfig;//TestConfig將會賦值給它。
public void init(FilterConfig filterConfig) {
    //反射生成TestConfig對象實例(<a href="ypj5.com">羊皮卷網</a>)
    createJFinalConfig(filterConfig.getInitParameter("configClass"));
    //通過調用TestConfig中的方法,完成環境對象的設置,
    if (jfinal.init(jfinalConfig, filterConfig.getServletContext()) == false) {
			throw new RuntimeException("JFinal init error!");
	}
}
}

可以看到,jfinalConfig對象傳遞給了jfinal.init()方法,這個方法返回一個boolean值,如果是false表示初始化失敗了。同時還將ServletContext傳遞給了jfinal.init()方法。下面就需要分析jfinal.init()方法了。可以猜測代碼是這麽樣寫的:

public class JFinal(){
    public static final Constants =new Constants();
    public static init(JFinalConfig testConfig,ServletContext context){
        testConfig.configConstant(Constants);
    }
}

這樣就完成了TestConfig.configConstant方法調用,就完成了Constants裏面字段的set()。

JFinal初始化分析-常量初始化-1