淺說動態生成Class實現MVC

<h1>前言</h1> <p>java web的MVC,一個爛的不能再爛的一個話題了,能夠說,如今市面上或者網上一搜,都有不少很優秀的MVC框架。那麼這裏爲何還要寫一篇着相關的文章呢,在這介紹下本文的背景,以前幫一個朋友作個網站,因爲本人只會java,因此就用java寫了一個,可是因爲資金有限,只能找一些便宜的jsp空間,那麼這樣隨之而來的問題就是,這樣的空間實在是給的東西有限,最主要的問題就是內存不夠。因此就想,若是我不用任何框架,純servlet編寫,是否就能節約內存和提升執行效率,因而選擇了直接採用servlet編寫,可是這樣確實帶來不少維護和編程上的不便。因而就想可否寫一個MVC框架,在程序執行以前按照規則自動生成各類代理類,那麼在程序運行的時候就不須要什麼反射,注入等等。既然目標已經肯定,那麼就按照這個思路繼續往下走吧,就是如何按照規則自動生成咱們想要的class。</p> <h1>Action規則制定</h1> <p>首先咱們但願定義Action的規則,他的主要做用就是告訴程序,不一樣的請求是由哪些類和方法處理的。看看下面的代碼: </p> <pre style="overflow: auto" class="brush:java;gutter:true;first-line:1;tab-size:4;toolbar:true;">代碼1: @Action(&quot;/MockServlet&quot;) public class MockServletAction {java

@UrlMapping(
    value=&quot;/execute.action&quot;,
    method=&quot;GET&quot;,
    result=&quot;SUCCESS&quot;,
    path=&quot;/servlet/test.jsp&quot;
)
public String execute() throws IOException {
    return &quot;SUCCESS&quot;;
}

}</pre>web

<p>這段代碼很容易讀懂,@Action註解告訴程序,全部以/MockServlet開頭的請求由這個類處理,而@UrlMapping中的value告訴程序在/MockServlet以後又是&quot;/execute.action&quot;由execute()這個方法處理,而且必須是GET方式發送過來的請求;到到目前位置,這些註解有點Spring Mvc的味道了,接下來就是@UrlMapping的result和path屬性了,其實他的意思就是當這個方法返回的是SUCCESS的時候採用&quot;/servlet/test.jsp&quot; 這個頁面作圖片的渲染。</p>編程

<p>接下來就是如何生成咱們想要的代碼了,首先讓咱們使用最原始的Servlet實現上面的功能,假設咱們的Action沒有任何註解,代碼以下: </p>app

<pre style="overflow: auto" class="brush:java;gutter:true;first-line:1;tab-size:4;toolbar:true;">代碼2: public class MockServletAction { public String execute() throws IOException { return &quot;SUCCESS&quot;; } }</pre>框架

<p>咱們一樣想讓這個Action去處理/MockServlet/execute.action這個GET請求,那麼咱們應該按照以下代碼作:</p>jsp

<pre style="overflow: auto" class="brush:java;gutter:true;first-line:1;tab-size:4;toolbar:true;">代碼3: public class ActionServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String servletPath = req.getServletPath(); if(servletPath.equals(&quot;/MockServlet/execute.action&quot;)){ String result = new MockServletAction().execute(); if(result.equals(&quot;SUCCESS&quot;)){ req.getRequestDispatcher(&quot;/servlet/test.jsp&quot;).forward(request, response); } } } }</pre>maven

<p>經過上面就可以明白,咱們但願有這麼一個框架,它可以經過代碼1中的註解的中所定義的請求轉發規則來自定生成代碼3。這樣就既可以高效率的運行,減小系統運行時資源的損耗,同時也也能提升開發效率。 </p>ide

<p>咱們也能夠爲事務作自動修改class,無非就是在方法先後加入事務啓動和事務提交的代碼;依賴注入的話就在構造方法中生成注入的代碼等等. </p>svn

<h1>Class自動生成的策略</h1>網站

<p>有人也有疑問,就是我自動生成class,一樣也是消耗資源的。沒錯不只僅消耗資源,並且還消耗的很是多。可是這種消耗是一次性的,也就是說我程序運行開始就將class生成好,之後就直接使用這個class而無需重複生成。可是有的時候server的配置實在太爛,或者我就是個極端主義者,我就是但願server損耗的越少越好。那麼爲此這個就有如下兩種策略供選擇: </p>

<h2>1.運行時自動生成Class </h2>

<p>程序運行開始將全部須要的class自動生成或者將修改後的class替換成原有的class。固然這種方式的優勢就是開發階段快,可是弊端就是,咱們沒法在server中替換已經load的class,而且大多數的server提供商也不讓你使用自定義系統級別的classloader,因此咱們自動生成的class都將以反射的方式調用。 </p>

<h2>2.在開發階段自動生成Class</h2>

<p>在開發階段就自動生成class,而後打包到war包中,這樣在server上運行的時候使用咱們生成的class就和通常的方法調用沒有任何區別,也就是這一點使得咱們可以規避掉策略1中的弊端。原則上講着一種方式在開發和打包這兩個階段中多了一個步驟,就是添加自動生成的class,可是因爲項目採用MAVEN開發,咱們可以編寫一個maven插件,自動的執行自動生成類的打包。因此建議使用這種方式。 </p>

<h1>實現</h1>

<p>目前上述構想已經實現,項目名稱爲Wheel,而maven插件名稱爲wheel-maven-plugin。可是wheel所使用的依賴包asmsupport-0.3-SNAPSHOT,classgrep-1.2-SNAPSHOT都尚未release,尚未發佈到maven,因此須要手動maven install到本地的maven倉庫。各個包編譯打包順序以下: </p>

<ul> <ol>asmsupport執行maven clean install</ol>

<ol>classgrep執行maven clean install</ol>

<ol>wheel執行maven clean install</ol>

<ol>wheel-maven-plugin執行maven clean install</ol> </ul>

<p>這裏也有一個簡單是實例WheelSampleApp, 裏面展現了大部分的功能,如AOP,注入等等。</p>

<p>以上涉及到的項目的源碼地址:</p>

<ul> <ol><b>asmsupport:</b>http://code.taobao.org/svn/asmsupport/trunk</ol>

<ol><b>classgrep:</b>http://code.taobao.org/svn/classgrep/trunk</ol>

<ol><b>wheel:</b>http://code.taobao.org/svn/wheel/trunk</ol>

<ol><b>wheel-maven-plugin:</b>http://code.taobao.org/svn/wheel-maven-plugin/trunk</ol>

<ol><b>WheelSampleApp:</b>http://code.taobao.org/svn/WheelSampleApp/trunk</ol> </ul>

<p>Wheel和wheel-maven-plugin正在醞釀發佈第一個版本,而calssgrep-1.1和asmsupport-0.2都已經發布,只是wheel所依賴的classgrep-1.2和asmsupport-0.3 這兩個新版本還爲發佈,後續也將補全新功能和bug陸續發佈。 </p>

相關文章
相關標籤/搜索