代碼編譯框架
❶ 如何寫一個編譯時註解框架
1、註解
我們日常使用的很多開源庫都有註解的實現,主要有運行時註解和編譯時註解兩種。
運行時註解:主要作用就是得到註解的信息
Retrofit:
調用
@GET("/users/{username}")
User getUser(@Path("username") String username);
定義
@Documented
@Target(METHOD)
@Retention(RUNTIME)
@RestMethod("GET")
public @interface GET {
String value();
}
編譯時註解:主要作用動態生成代碼
Butter Knife
調用
@InjectView(R.id.user)
EditText username;
定義
@Retention(CLASS)
@Target(FIELD)
public @interface InjectView {
int value();
}
2、編譯時註解
要實現編譯時註解需要3步:
1、定義註解(關於註解的定義可以參考下面引用的博客)
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.ElementType;
@Target({ ElementType.FIELD, ElementType.TYPE })
@Retention(RetentionPolicy.CLASS)
public @interface Seriable
{
}
2、編寫註解解析器
@SupportedAnnotationTypes("annotation.Seriable")
@SupportedSourceVersion(SourceVersion.RELEASE_6)
public class ViewInjectProcessor extends AbstractProcessor {
@Override
public boolean process(Set annotations,
RoundEnvironment roundEnv) {
for (Element ele : roundEnv.getElementsAnnotatedWith(InjectView.class)) {
if(ele.getKind() == ElementKind.FIELD){
//todo
}
return true;
}
@SupportedAnnotationTypes,定義要支持註解的完整路徑,也可以通過getSupportedAnnotationTypes方法來定義
@Override
public Set getSupportedAnnotationTypes() {
Set types = new LinkedHashSet<>();
types.add(InjectView.class.getCanonicalName());
return types;
}
@SupportedSourceVersion(SourceVersion.RELEASE_6)表示支持的jdk的版本
3、創建制定文件resources/META-INF/services/javax.annotation.processing.Processor,並填寫註解解析器的類路徑,這樣在編譯的時候就能自動找到解析器
看上去實現編譯時註解還是很容易的,但是真要完整的實現一個類似Butter Knife的框架,這還只是開始。
Butter Knife是專注View的注入,在使用註解的類編譯後,查看編譯後的class文件,會發現多出了文件,如:
SimpleActivity$$ViewInjector.java
SimpleActivity$$ViewInjector.java,就是通過編譯時註解動態創建出來的,查看SimpleActivity$$ViewInjector.java的內容
// Generated code from Butter Knife. Do not modify!
package com.example.butterknife;
import android.view.View;
import butterknife.ButterKnife.Finder;
public class SimpleActivity$$ViewInjector {
public static void inject(Finder finder, final com.example.butterknife.SimpleActivity target, Object source) {
View view;
view = finder.findRequiredView(source, 2131230759, "field 'title'");
target.title = (android.widget.TextView) view;
view = finder.findRequiredView(source, 2131230783, "field 'subtitle'");
target.subtitle = (android.widget.TextView) view;
view = finder.findRequiredView(source, 2131230784, "field 'hello', method 'sayHello', and method 'sayGetOffMe'");
target.hello = (android.widget.Button) view;
view.setOnClickListener(
new butterknife.internal.DebouncingOnClickListener() {
@Override
public void doClick(
android.view.View p0
) {
target.sayHello();
}
});
view.setOnLongClickListener(
new android.view.View.OnLongClickListener() {
@Override
public boolean onLongClick(
android.view.View p0
) {
return target.sayGetOffMe();
}
});
view = finder.findRequiredView(source, 2131230785, "field 'listOfThings' and method 'onItemClick'");
target.listOfThings = (android.widget.ListView) view;
((android.widget.AdapterView) view).setOnItemClickListener(
new android.widget.AdapterView.OnItemClickListener() {
@Override
public void onItemClick(
android.widget.AdapterView p0,
android.view.View p1,
int p2,
long p3
) {
target.onItemClick(p2);
}
});
view = finder.findRequiredView(source, 2131230786, "field 'footer'");
target.footer = (android.widget.TextView) view;
}
public static void reset(com.example.butterknife.SimpleActivity target) {
target.title = null;
target.subtitle = null;
target.hello = null;
target.listOfThings = null;
target.footer = null;
}
}
inject方法進行初始化,reset進行釋放。inject都是調用Finder的方法與android系統的findViewById等方法很像,再來看Finder類,只截取部分。
public enum Finder {
public T findRequiredView(Object source, int id, String who) {
T view = findOptionalView(source, id, who);
if (view == null) {
String name = getResourceEntryName(source, id);
throw new IllegalStateException("Required view '"
+ name
+ "' with ID "
+ id
+ " for "
+ who
+ " was not found. If this view is optional add '@Nullable' (fields) or '@Optional'"
+ " (methods) annotation.");
}
return view;
}
public T findOptionalView(Object source, int id, String who) {
View view = findView(source, id);
return castView(view, id, who);
}
@Override protected View findView(Object source, int id) {
return ((View) source).findViewById(id);
}
@SuppressWarnings("unchecked") // That's the point.
public T castView(View view, int id, String who) {
try {
return (T) view;
} catch (ClassCastException e) {
if (who == null) {
throw new AssertionError();
}
String name = getResourceEntryName(view, id);
throw new IllegalStateException("View '"
+ name
+ "' with ID "
+ id
+ " for "
+ who
+ " was of the wrong type. See cause for more info.", e);
}
}
findRequiredView方法實際上就是我們常用findViewById的實現,其動態幫我們添加了這些實現。view注入的原理我們就清楚了。
雖然編譯時創建了這個類,運行的時候如何使用這個類呢,這里我用自己實現的一個類來描述
public class XlViewInjector {
static final Map, AbstractInjector> INJECTORS = new LinkedHashMap, AbstractInjector>();
public static void inject(Activity activity){
AbstractInjector injector = findInjector(activity);
injector.inject(Finder.ACTIVITY, activity, activity);
}
public static void inject(Object target, View view){
AbstractInjector injector = findInjector(target);
injector.inject(Finder.VIEW, target, view);
}
private static AbstractInjector findInjector(Object target){
Class clazz = target.getClass();
AbstractInjector injector = INJECTORS.get(clazz);
if(injector == null){
try{
Class injectorClazz = Class.forName(clazz.getName()+"$$"+ProxyInfo.PROXY);
injector = (AbstractInjector) injectorClazz.newInstance();
INJECTORS.put(clazz, injector);
}catch(Exception e){
e.printStackTrace();
}
}
return injector;
}
}
XlViewInjector與ButterKnife,比如調用時我們都會執行XlViewInjector.inject方法,通過傳入目標類的名稱獲得封裝後的類實例就是SimpleActivity$$ViewInjector.java,再調用它的inject,來初始化各個view。
總結一下整個實現的流程:
1、通過編譯時註解動態創建了一個包裝類,在這個類中已解析了註解,實現了獲取view、設置監聽等代碼。
2、執行時調用XlViewInjector.inject(object)方法,實例化object類對應的包裝類,並執行他的初始化方法inject;
因此我們也能明白為什麼XlViewInjector.inject(object)方法一定要在setContentView之後執行。
3、實現註解框架時的坑
解析有用到android api,因此需要創建Android工程,但是android library並沒有javax的一些功能,
在eclipse環境下,右鍵build-path add library把jdk加進來
在android studio下,需要先創建java Library功能,實現與view無關的解析,再創建一個android library功能引用這個工程並實現餘下的解析。
❷ 這是C++寫的代碼框架,這幾句怎麼理解,為什麼模板參數中沒有使用class或者typename
定義時模版參數的確可以設置成一個枚舉,這樣在編譯期間就能確定的
而後面的代碼是在特例化模版,既然是在特例化,那就可以把枚舉值代入了
❸ osgi框架把編譯後的代碼放在哪裡
需配置sqljdbc.jar成runtime依賴 再把sqljdbc.jar一起打包到你的應用程序
❹ 有什麼動態編譯java源代碼的框架
可以的,我說說大概思路,很簡單,你自己具體實現吧,把代碼寫給你沒意義的:
將你這段字元串輸出到一個文件里,用Java類文件的方式命名。
2.調用外部javac命令將該文件編譯。
3.用類載入器(ClassLoad)動態載入新的class文件並用Class.forName()注冊該類,然後就可以正常使用了。
上面的每一步都能在中找到實現方法,自己發揮吧。
❺ ssh框架下實現word在線編譯的代碼
1-apache的POI,此方法對Excel的導出做的很好,目前對Word的導出方面的功能尚未完全。
2-純JavaScript腳本實現。主要通過客戶端調用本機Office組件來實現。
3-在JSP頁面引入頭文件實現。
純JavaScript腳本實現細節方面大體是創建一個word組件ActiveXObject('Word.Application'),用js通過表ID取得表內容然後保存到word,要注意的是js實現有很多不好的地方,例如Internet選項需要把ActiveX空間全部啟用,安全級別設置為中。這樣的話豈不是每台機器都要配置一下。其次每次生成word文檔以後彈出對話框(無法保存此文件,因為它已在別處打開(C:\...\STARTUP\Powerword.dot)),出現此問題就需要把C:\Documents and Settings\當前用戶名\Application Data\Microsoft\Word\STARTUP下的Powerword.dot文件刪除,每次遇到此問題就需要刪除文件來解決,十分不方便。
JSP頁面引入來實現Word保存就方便多了,但是也有不足的地方,首先如果需要引入
<meta http-equiv="Content-Type" content="application/msword; charset=gb2312" />
如果需要下載的話就引入
<%@ page contentType="application/msword; charset=gb2312" %>
其實如果大家用框架做就方便多了,比如Struts2。在Action里直接寫如下代碼:
if(out!=null){
String fileName="";
fileName+="評價報告.doc";
try {
HttpServletResponse response = ServletActionContext.getResponse();
response.setHeader("Content-disposition","attachment; filename="+new String(fileName.getBytes("GB2312"), "8859_1"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
out是jsp頁面表單元素,一個button,用於提交表單到相應Action進行Word下載。Action設置jsp頁面頭文件。這樣每次點擊button就可以把相應jsp頁面的內容保存到Word中並且支持下載,Word中內容並且是可編輯狀態。
不足的地方在於由於表內容是動態生成,有的需要先查看在下載Word,就需要另外建立一個新JSP頁面進行Word下載,當然首先要在struts.xml里配置好頁面轉向。
新建立的頁面傳值同查看頁面要保持一樣。
❻ 如何編譯CNTK框架
如何編譯CNTK框架
現階段不可能。
.NET 下你用的所有 CLR 方法也好類也好都是封裝在一個個 .NET Framework 的 DLL 里的,程序運行時必須這些文件,除非你一個 CLR 類和方法都沒用過(那不就是純 C 語言而且是只有標准庫的 C 了么)。
有些類似於 Remote Soft's Salamander .NET Native Compiler、Infralution Globalizer 這些工具,也不是把代碼編譯成機器語言了,而是把需要的類庫等直接寫入了 PE,會導致程序體積大大增加,而且只支持 .NET 2.0,最重要的是還是收費軟體。
❼ 如何自己編譯源代碼
我們使用編譯器將自己的源代碼轉換成目標代碼, 使用鏈接器將我們的目標代碼鏈接成一個可執行程序。另外, 我們使用一些程序在計算機中輸入源代碼文本並且編輯它。這些是最初的和最重要的工具, 它們構成程序員的工具集合或「程序開發環境」。 如果你使用的是命令行窗口, 就像很多專業程序員所做的那樣, 你將不得不自己來編寫編譯和鏈接命令。如果你使用IDE(「互動式開發環境」或「集成式開發環境」), 就像很多程序員所做的那樣, 簡單地點擊正確按鈕就可以完成這個工作。附錄C介紹了如何在你的C++實現中編譯和鏈接。 IDE通常包括一個具有有用特性的編輯器, 例如用不同顏色的代碼來區分你的源代碼中的注釋、 關鍵字和其他部分, 以及其他幫助你來調試代碼、 編譯和運行代碼的功能。調試是發現程序中的錯誤和排除錯誤的活動, 你在前進的道路上會聽到很多有關它的內容。 我們使用微軟的Visual C++作?喑炭 ⒒肪呈道 H綣 頤羌虻サ廝怠氨嘁肫鰲被蚴恰癐DE」的某些部分, 那就是所指Visual C++系統。但是, 你可以使用一些提供最新的、 符合標準的C++實現的系統。我們所說的大多數內容(經過微小的修改)對所有的C++實現都將是正確的, 並且其代碼可以在任何地方運行。在工作中, 我們使用幾種不同的實現。
❽ 源碼怎麼編譯
使用編譯器如VC++6.0,VC++2008
❾ 我想讓自己的程序(圖一)變成圖2,怎麼使用C++進行編譯能不能給出個大概的代碼框架結構
圖1是字元界面,圖2是圖形界面,二者差距很大,C++做不出圖2的界面來,要用VC++才行。用MFC創建一個單文檔工程,就會提供一個開發圖形界面的對話框,在對話框里添加控制項即可做出圖2的界面來;然後為每個控制項添加功能代碼就基本完成了……
❿ 什麼是程序的編輯器,編譯器,什麼是Framework(框架)
編譯器是程序輔助工具,一般會生成一些幫助代碼
框架是編程的一種模式,把正個代碼實現的功能按起的作用分類,可以使思路清析