首页 > 代码库 > JFinal初始化分析-常量初始化-1
JFinal初始化分析-常量初始化-1
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="http://www.mamicode.com/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