电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術(shù)文章
文章詳情頁

淺談JAVA 類加載器

瀏覽:31日期:2022-08-30 15:34:48

類加載機(jī)制

類加載器負(fù)責(zé)加載所有的類,系統(tǒng)為所有被載入內(nèi)存中的類生成一個(gè) java.lang.Class 實(shí)例。一旦一個(gè)類被載入 JVM 中,同個(gè)類就不會(huì)被再次載入了。現(xiàn)在的問題是,怎么樣才算“同一個(gè)類”?

正如一個(gè)對(duì)象有一個(gè)唯一的標(biāo)識(shí)一樣,一個(gè)載入 JVM 中的類也有一個(gè)唯一的標(biāo)識(shí)。在 Java 中,一個(gè)類用其全限定類名(包括包名和類名)作為標(biāo)識(shí):但在 JVM 中,一個(gè)類用其全限定類名和其類加載器作為唯一標(biāo)識(shí)。例如,如果在 pg 的包中有一個(gè)名為 Person 的類,被類加載器 ClassLoader 的實(shí)例 k1 負(fù)責(zé)加載,則該 Person 類對(duì)應(yīng)的 Class 對(duì)象在 JVM 中表示為(Person、pg、k1)。這意味著兩個(gè)類加載器加載的同名類:(Person、pg、k1)和(Person、pg、k12)是不同的,它們所加載的類也是完全不同、互不兼容的。

當(dāng) JVM 啟動(dòng)時(shí),會(huì)形成由三個(gè)類加載器組成的初始類加載器層次結(jié)構(gòu)。

Bootstrap ClassLoader:根類加載器。 Extension ClassLoader:擴(kuò)展類加載器。 System ClassLoader:系統(tǒng)類加載器。

Bootstrap ClassLoader 被稱為引導(dǎo)(也稱為原始或根)類加載器,它負(fù)責(zé)加載 Java 的核心類。在Sun 的 JVM 中,當(dāng)執(zhí)行 java.exe 命令時(shí),使用 -Xbootclasspath 或 -D 選項(xiàng)指定 sun.boot.class.path 系統(tǒng)屬性值可以指定加載附加的類。

JVM的類加載機(jī)制主要有如下三種。

全盤負(fù)責(zé)。所謂全盤負(fù)責(zé),就是當(dāng)一個(gè)類加載器負(fù)責(zé)加載某個(gè) Class 時(shí),該 Class 所依賴的和引用的其他 Class 也將由該類加載器負(fù)責(zé)載入,除非顯式使用另外一個(gè)類加載器來載入。 父類委托。所謂父類委托,則是先讓 parent(父)類加載器試圖加載該 Class,只有在父類加載器無法加載該類時(shí)才嘗試從自己的類路徑中加載該類。 緩存機(jī)制。緩存機(jī)制將會(huì)保證所有加載過的 Class 都會(huì)被緩存,當(dāng)程序中需要使用某個(gè) Class 時(shí),類加載器先從緩存區(qū)中搜尋該 Class,只有當(dāng)緩存區(qū)中不存在該 Class 對(duì)象時(shí),系統(tǒng)才會(huì)讀取該類對(duì)應(yīng)的二進(jìn)制數(shù)據(jù),并將其轉(zhuǎn)換成 Class 對(duì)象,存入緩存區(qū)中。這就是為什么修改了 Class 后,必須重新啟動(dòng) JVM,程序所做的修改才會(huì)生效的原因。

除了可以使用 Java 提供的類加載器之外,開發(fā)者也可以實(shí)現(xiàn)自己的類加載器,自定義的類加載器通過繼承 ClassLoader 來實(shí)現(xiàn)。JVM 中這4種類加載器的層次結(jié)構(gòu)如下圖所示。

淺談JAVA 類加載器

注意:類加載器之間的父子關(guān)系并不是類繼承上的父子關(guān)系,這里的父子關(guān)系是類加載器實(shí)例之間的關(guān)系

下面程序示范了訪問 JVM 的類加載器。

public class ClassLoaderPropTest { public static void main(String[] args) throws IOException { // 獲取系統(tǒng)類加載器 ClassLoader systemLoader = ClassLoader.getSystemClassLoader(); System.out.println('系統(tǒng)類加載器:' + systemLoader); /* * 獲取系統(tǒng)類加載器的加載路徑——通常由CLASSPATH環(huán)境變量指定 如果操作系統(tǒng)沒有指定CLASSPATH環(huán)境變量,默認(rèn)以當(dāng)前路徑作為 * 系統(tǒng)類加載器的加載路徑 */ Enumeration<URL> em1 = systemLoader.getResources(''); while (em1.hasMoreElements()) { System.out.println(em1.nextElement()); } // 獲取系統(tǒng)類加載器的父類加載器:得到擴(kuò)展類加載器 ClassLoader extensionLader = systemLoader.getParent(); System.out.println('擴(kuò)展類加載器:' + extensionLader); System.out.println('擴(kuò)展類加載器的加載路徑:' + System.getProperty('java.ext.dirs')); System.out.println('擴(kuò)展類加載器的parent: ' + extensionLader.getParent()); }}

運(yùn)行上面的程序,會(huì)看到如下運(yùn)行結(jié)果

系統(tǒng)類加載器:sun.misc.Launcher$AppClassLoader@73d16e93file:/F:/EclipseProjects/demo/bin/擴(kuò)展類加載器:sun.misc.Launcher$ExtClassLoader@15db9742擴(kuò)展類加載器的加載路徑:C:Program FilesJavajre1.8.0_181libext;C:WindowsSunJavalibext擴(kuò)展類加載器的parent: null

從上面運(yùn)行結(jié)果可以看出,系統(tǒng)類加載器的加載路徑是程序運(yùn)行的當(dāng)前路徑,擴(kuò)展類加載器的加載路徑是null(與 Java8 有區(qū)別),但此處看到擴(kuò)展類加載器的父加載器是null,并不是根類加載器。這是因?yàn)楦惣虞d器并沒有繼承 ClassLoader 抽象類,所以擴(kuò)展類加載器的 getParent() 方法返回null。但實(shí)際上,擴(kuò)展類加載器的父類加載器是根類加載器,只是根類加載器并不是 Java 實(shí)現(xiàn)的。

從運(yùn)行結(jié)果可以看出,系統(tǒng)類加載器是 AppClassLoader 的實(shí)例,擴(kuò)展類加載器 ExtClassLoader 的實(shí)例。實(shí)際上,這兩個(gè)類都是 URLClassLoader 類的實(shí)例。

注意:JVM 的根類加載器并不是 Java 實(shí)現(xiàn)的,而且由于程序通常無須訪問根類加載器,因此訪問擴(kuò)展類加載器的父類加載器時(shí)返回null。

類加載器加載 Class 大致要經(jīng)過如下8個(gè)步驟。

檢測(cè)此 Class 是否載入過(即在緩存區(qū)中是否有此Class),如果有則直接進(jìn)入第8步,否則接著執(zhí)行第2步。 如果父類加載器不存在(如果沒有父類加載器,則要么 parent 一定是根類加載器,要么本身就是根類加載器),則跳到第4步執(zhí)行;如果父類加載器存在,則接著執(zhí)行第3步。 請(qǐng)求使用父類加載器去載入目標(biāo)類,如果成功載入則跳到第8步,否則接著執(zhí)行第5步。 請(qǐng)求使用根類加載器來載入目標(biāo)類,如果成功載入則跳到第8步,否則跳到第7步。 當(dāng)前類加載器嘗試尋找 Class 文件(從與此 ClassLoader 相關(guān)的類路徑中尋找),如果找到則執(zhí)行第6步,如果找不到則跳到第7步。 從文件中載入 Class,成功載入后跳到第8步。 拋出 ClassNotFoundExcepuon 異常。 返回對(duì)應(yīng)的 java.lang.Class 對(duì)象。

其中,第5、6步允許重寫 ClassLoader的 findClass() 方法來實(shí)現(xiàn)自己的載入策略,甚至重寫 loadClass() 方法來實(shí)現(xiàn)自己的載入過程。

創(chuàng)建并使用自定義的類加載器

JVM 中除根類加載器之外的所有類加載器都是 ClassLoader 子類的實(shí)例,開發(fā)者可以通過擴(kuò)展 ClassLoader 的子類,并重寫該 ClassLoader 所包含的方法來實(shí)現(xiàn)自定義的類加載器。查閱API文檔中關(guān)于 ClassLoader 的方法不難發(fā)現(xiàn),ClassLoader 中包含了大量的 protected 方法——這些方法都可被子類重寫。

ClassLoader 類有如下兩個(gè)關(guān)鍵方法。

loadClass(String name, boolean resolve):該方法為 ClassLoader 的入口點(diǎn),根據(jù)指定名稱來加載類,系統(tǒng)就是調(diào)用 ClassLoader 的該方法來獲取指定類對(duì)應(yīng)的 Class 對(duì)象。 findClass(String name):根據(jù)指定名稱來查找類。

如果需要實(shí)現(xiàn)自定義的 ClassLoader,則可以通過重寫以上兩個(gè)方法來實(shí)現(xiàn),通常推薦重寫 findClass() 方法,而不是重寫 loadClass() 方法。loadClass() 方法的執(zhí)行步驟如下。

用 findLoadedClass(String) 來檢查是否已經(jīng)加載類,如果已經(jīng)加載則直接返回。 在父類加載器上調(diào)用 loadClass() 方法。如果父類加載器為null,則使用根類加載器來加載。 調(diào)用 findClass(String) 方法查找類。

從上面步驟中可以看出,重寫 findClass()方法可以避免覆蓋默認(rèn)類加載器的父類委托、緩沖機(jī)制兩種策略:如果重寫 loadClass() 方法,則實(shí)現(xiàn)邏輯更為復(fù)雜。

在 ClassLoader 里還有一個(gè)核心方法:Class defineClass(String name, byte[] b, int off,int len) 該方法負(fù)責(zé)將指定類的字節(jié)碼文件(即 Class 文件,如 Hello.class)讀入字節(jié)數(shù)組 byte[] b 內(nèi),并把它轉(zhuǎn)換為 Class對(duì)象,該字節(jié)碼文件可以來源于文件、網(wǎng)絡(luò)等。

defineClass() 方法管理 JVM 的許多復(fù)雜的實(shí)現(xiàn),它負(fù)責(zé)將字節(jié)碼分析成運(yùn)行時(shí)數(shù)據(jù)結(jié)構(gòu),并校驗(yàn)有效性等。不過不用擔(dān)心,程序員無須重寫該方法。實(shí)際上該方法是 final 的,即使想重寫也沒有機(jī)會(huì)。

除此之外,ClassLoader 里還包含如下一些普通方法。

findSystemClass(String name):從本地文件系統(tǒng)裝入文件。它在本地文件系統(tǒng)中尋找類文件,如果存在,就使用 defineClass() 方法將原始字節(jié)轉(zhuǎn)換成 Class 對(duì)象,以將該文件轉(zhuǎn)換成類。 static getSystemClassLoader():這是一個(gè)靜態(tài)方法,用于返回系統(tǒng)類加載器。 getParent():獲取該類加載器的父類加載器。 resolveClass(Class<?> c):鏈接指定的類。類加載器可以使用此方法來鏈接類c。讀者無須理會(huì)關(guān)于此方法的太多細(xì)節(jié)。 findLoadedClass(String name):如果此 Java 虛擬機(jī)已加載了名為 name 的類,則直接返回該類對(duì)應(yīng)的 Class 實(shí)例,否則返回null,該方法是 Java 類加載緩存機(jī)制的體現(xiàn)。

下面程序開發(fā)了一個(gè)自定義的 ClassLoader,該 ClassLoader 通過重寫 findClass() 方法來實(shí)現(xiàn)自定義的類加載機(jī)制。這個(gè) ClassLoader 可以在加載類之前先編譯該類的文件,從而實(shí)現(xiàn)運(yùn)行 Java 之前先編譯該程序的目標(biāo),這樣即可通過該 ClassLoader 直接運(yùn)行 Java 源文件。

public class CompileClassLoader extends ClassLoader { // 讀取一個(gè)文件的內(nèi)容 private byte[] getBytes(String filename) throws IOException { File file = new File(filename); long len = file.length(); byte[] raw = new byte[(int) len]; try (FileInputStream fin = new FileInputStream(file)) { // 一次讀取class文件的全部二進(jìn)制數(shù)據(jù) int r = fin.read(raw); if (r != len) throw new IOException('無法讀取全部文件:' + r + ' != ' + len); return raw; } } // 定義編譯指定Java文件的方法 private boolean compile(String javaFile) throws IOException { System.out.println('CompileClassLoader:正在編譯 ' + javaFile + '...'); // 調(diào)用系統(tǒng)的javac命令 Process p = Runtime.getRuntime().exec('javac ' + javaFile); try { // 其他線程都等待這個(gè)線程完成 p.waitFor(); } catch (InterruptedException ie) { System.out.println(ie); } // 獲取javac線程的退出值 int ret = p.exitValue(); // 返回編譯是否成功 return ret == 0; } // 重寫ClassLoader的findClass方法 protected Class<?> findClass(String name) throws ClassNotFoundException { Class clazz = null; // 將包路徑中的點(diǎn)(.)替換成斜線(/)。 String fileStub = name.replace('.', '/'); String javaFilename = fileStub + '.java'; String classFilename = fileStub + '.class'; File javaFile = new File(javaFilename); File classFile = new File(classFilename); // 當(dāng)指定Java源文件存在,且class文件不存在、或者Java源文件 // 的修改時(shí)間比class文件修改時(shí)間更晚,重新編譯 if (javaFile.exists() && (!classFile.exists() || javaFile.lastModified() > classFile.lastModified())) { try { // 如果編譯失敗,或者該Class文件不存在 if (!compile(javaFilename) || !classFile.exists()) { throw new ClassNotFoundException('ClassNotFoundExcetpion:' + javaFilename); } } catch (IOException ex) { ex.printStackTrace(); } } // 如果class文件存在,系統(tǒng)負(fù)責(zé)將該文件轉(zhuǎn)換成Class對(duì)象 if (classFile.exists()) { try { // 將class文件的二進(jìn)制數(shù)據(jù)讀入數(shù)組 byte[] raw = getBytes(classFilename); // 調(diào)用ClassLoader的defineClass方法將二進(jìn)制數(shù)據(jù)轉(zhuǎn)換成Class對(duì)象 clazz = defineClass(name, raw, 0, raw.length); } catch (IOException ie) { ie.printStackTrace(); } } // 如果clazz為null,表明加載失敗,則拋出異常 if (clazz == null) { throw new ClassNotFoundException(name); } return clazz; } // 定義一個(gè)主方法 public static void main(String[] args) throws Exception { // 如果運(yùn)行該程序時(shí)沒有參數(shù),即沒有目標(biāo)類 if (args.length < 1) { System.out.println('缺少目標(biāo)類,請(qǐng)按如下格式運(yùn)行Java源文件:'); System.out.println('java CompileClassLoader ClassName'); } // 第一個(gè)參數(shù)是需要運(yùn)行的類 String progClass = args[0]; // 剩下的參數(shù)將作為運(yùn)行目標(biāo)類時(shí)的參數(shù), // 將這些參數(shù)復(fù)制到一個(gè)新數(shù)組中 String[] progArgs = new String[args.length - 1]; System.arraycopy(args, 1, progArgs, 0, progArgs.length); CompileClassLoader ccl = new CompileClassLoader(); // 加載需要運(yùn)行的類 Class<?> clazz = ccl.loadClass(progClass); // 獲取需要運(yùn)行的類的主方法 Method main = clazz.getMethod('main', (new String[0]).getClass()); Object[] argsArray = { progArgs }; main.invoke(null, argsArray); }}

上面程序中的粗體字代碼重寫了 findClass() 方法,通過重寫該方法就可以實(shí)現(xiàn)自定義的類加載機(jī)制。在本類的 findClass() 方法中先檢查需要加載類的 Class 文件是否存在,如果不存在則先編譯源文件,再調(diào)用 ClassLoader 的 defineClass() 方法來加載這個(gè) Class 文件,并生成相應(yīng)的 Class 對(duì)象。

接下來可以隨意提供一個(gè)簡單的主類,該主類無須編譯就可以使用上面的 CompileClassLoader 來運(yùn)行它。

public class Hello { public static void main(String[] args) { for (String arg : args) { System.out.println('運(yùn)行Hello的參數(shù):' + arg); } }}

淺談JAVA 類加載器

本示例程序提供的類加載器功能比較簡單,僅僅提供了在運(yùn)行之前先編譯 Java 源文件的功能。實(shí)際上,使用自定義的類加載器,可以實(shí)現(xiàn)如下常見功能。

執(zhí)行代碼前自動(dòng)驗(yàn)證數(shù)字簽名。 根據(jù)用戶提供的密碼解密代碼,從而可以實(shí)現(xiàn)代碼混淆器來避免反編譯 *.class 文件。 根據(jù)用戶需求來動(dòng)態(tài)地加載類。 根據(jù)應(yīng)用需求把其他數(shù)據(jù)以字節(jié)碼的形式加載到應(yīng)用中。

URLClassLoader 類

Java 為 ClassLoader 提供了一個(gè) URLClassLoader 實(shí)現(xiàn)類,該類也是系統(tǒng)類加載器和擴(kuò)展類加載器的父類(此處的父類,就是指類與類之間的繼承關(guān)系)。URLClassLoader 功能比較強(qiáng)大,它既可以從本地文件系統(tǒng)獲取二進(jìn)制文件來加載類,也可以從遠(yuǎn)程主機(jī)獲取二進(jìn)制文件來加載類。

在應(yīng)用程序中可以直接使用 URLClassLoader 加載類,URLClassLoader 類提供了如下兩個(gè)構(gòu)造器。

URLClassLoader(URL[] urls):使用默認(rèn)的父類加載器創(chuàng)建一個(gè) ClassLoader 對(duì)象,該對(duì)象將從 urls 所指定的系列路徑來查詢并加載類。 URLClassLoader(URL[] urls, ClassLoader parent):使用指定的父類加載器創(chuàng)建一個(gè) ClassLoader 對(duì)象,其他功能與前一個(gè)構(gòu)造器相同。

一旦得到了 URLClassLoader 對(duì)象之后,就可以調(diào)用該對(duì)象的 loadClass() 方法來加載指定類。下面程序示范了如何直接從文件系統(tǒng)中加載 MySQL 驅(qū)動(dòng),并使用該驅(qū)動(dòng)來獲取數(shù)據(jù)庫連接。通過這種方式來獲取數(shù)據(jù)厙連接,可以無須將 MySQL 驅(qū)動(dòng)添加到 CLASSPATH 環(huán)境變量中。

public class URLClassLoaderTest { private static Connection conn; // 定義一個(gè)獲取數(shù)據(jù)庫連接方法 public static Connection getConn(String url, String user, String pass) throws Exception { if (conn == null) { // 創(chuàng)建一個(gè)URL數(shù)組 URL[] urls = { new URL('file:mysql-connector-java-5.1.30-bin.jar') }; // 以默認(rèn)的ClassLoader作為父ClassLoader,創(chuàng)建URLClassLoader URLClassLoader myClassLoader = new URLClassLoader(urls); // 加載MySQL的JDBC驅(qū)動(dòng),并創(chuàng)建默認(rèn)實(shí)例 Driver driver = (Driver) myClassLoader.loadClass('com.mysql.jdbc.Driver').getConstructor().newInstance(); // 創(chuàng)建一個(gè)設(shè)置JDBC連接屬性的Properties對(duì)象 Properties props = new Properties(); // 至少需要為該對(duì)象傳入user和password兩個(gè)屬性 props.setProperty('user', user); props.setProperty('password', pass); // 調(diào)用Driver對(duì)象的connect方法來取得數(shù)據(jù)庫連接 conn = driver.connect(url, props); } return conn; } public static void main(String[] args) throws Exception { System.out.println(getConn('jdbc:mysql://localhost:3306/mysql', 'root', '32147')); }}

上面程序中的前兩行粗體字代碼創(chuàng)建了一個(gè) URLClassLoader 對(duì)象,該對(duì)象使用默認(rèn)的父類加載器,該類加載器的類加載路徑是當(dāng)前路徑下的 mysql-connector-java-5.1.30-bin.jar 文件,將 MySQL 驅(qū)動(dòng)復(fù)制到該路徑下,這樣保證該 ClassLoader 可以正常加載到 com.mysql.jdbc.Driver 類。

程序的第三行粗體字代碼使用 ClassLoader 的 loadClass() 加載指定類,并調(diào)用 Class 對(duì)象的 newInstance() 方法創(chuàng)建了一個(gè)該類的默認(rèn)實(shí)例——也就是得到 com.mysql.jdbc.Driver 類的對(duì)象,當(dāng)然該對(duì)象的實(shí)現(xiàn)類實(shí)現(xiàn)了 java.sql.Driver 接口,所以程序?qū)⑵鋸?qiáng)制類型轉(zhuǎn)換為 Driver,程序的最后一行粗體字代碼通過 Driver 而不是 DriverManager 來獲取數(shù)據(jù)庫連接,關(guān)于 Driver 接口的用法讀者可以自行查閱API文檔。

正如前面所看到的,創(chuàng)建 URLClassLoader 時(shí)傳入了一個(gè) URL 數(shù)組參數(shù),該 ClassLoader 就可以從這系列 URL 指定的資源中加載指定類,這里的 URL 可以以 file: 為前綴,表明從本地文件系統(tǒng)加載;可以以 http: 為前綴,表明從互聯(lián)網(wǎng)通過 HTTP 訪問來加載;也可以以 ftp: 為前綴,表明從互聯(lián)網(wǎng)通過 FTP訪問來加載......功能非常強(qiáng)大。

以上就是淺談JAVA 類加載器的詳細(xì)內(nèi)容,更多關(guān)于JAVA 類加載器的資料請(qǐng)關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: Java
相關(guān)文章:
主站蜘蛛池模板: 台式核磁共振仪,玻璃软化点测定仪,旋转高温粘度计,测温锥和测温块-上海麟文仪器 | 超声波破碎仪-均质乳化机(供应杭州,上海,北京,广州,深圳,成都等地)-上海沪析实业有限公司 | EPDM密封胶条-EPDM密封垫片-EPDM生产厂家| 嘉兴泰东园林景观工程有限公司_花箱护栏 | 广州冷却塔维修厂家_冷却塔修理_凉水塔风机电机填料抢修-广东康明节能空调有限公司 | 常州翔天实验仪器厂-恒温振荡器-台式恒温振荡器-微量血液离心机 恒温恒湿箱(药品/保健品/食品/半导体/细菌)-兰贝石(北京)科技有限公司 | 电磁辐射仪-电磁辐射检测仪-pm2.5检测仪-多功能射线检测仪-上海何亦仪器仪表有限公司 | 液氮罐(生物液氮罐)百科-无锡爱思科 | 挤奶设备过滤纸,牛奶过滤纸,挤奶机过滤袋-济南蓝贝尔工贸有限公司 | 大_小鼠elisa试剂盒-植物_人Elisa试剂盒-PCR荧光定量试剂盒-上海一研生物科技有限公司 | 大学食堂装修设计_公司餐厅效果图_工厂食堂改造_迈普装饰 | 玻璃钢格栅盖板|玻璃钢盖板|玻璃钢格栅板|树篦子-长沙川皖玻璃钢制品有限公司 | 澳威全屋定制官网|极简衣柜十大品牌|衣柜加盟代理|全屋定制招商 百度爱采购运营研究社社群-店铺托管-爱采购代运营-良言多米网络公司 | 蒸汽热收缩机_蒸汽发生器_塑封机_包膜机_封切收缩机_热收缩包装机_真空机_全自动打包机_捆扎机_封箱机-东莞市中堡智能科技有限公司 | 自动配料系统_称重配料控制系统厂家 | 电脑知识|软件|系统|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网 | 二氧化碳/活性炭投加系统,次氯酸钠发生器,紫外线消毒设备|广州新奥 | 首页-瓜尔胶系列-化工单体系列-油田压裂助剂-瓜尔胶厂家-山东广浦生物科技有限公司 | 工业插头-工业插头插座【厂家】-温州罗曼电气 | 钣金加工厂家-钣金加工-佛山钣金厂-月汇好 | 实验室pH计|电导率仪|溶解氧测定仪|离子浓度计|多参数水质分析仪|pH电极-上海般特仪器有限公司 | 佛山市钱丰金属不锈钢蜂窝板定制厂家|不锈钢装饰线条|不锈钢屏风| 电梯装饰板|不锈钢蜂窝板不锈钢工艺板材厂家佛山市钱丰金属制品有限公司 | 海外整合营销-独立站营销-社交媒体运营_广州甲壳虫跨境网络服务 焊管生产线_焊管机组_轧辊模具_焊管设备_焊管设备厂家_石家庄翔昱机械 | 聚丙烯酰胺PAM-聚合氯化铝PAC-絮凝剂-河南博旭环保科技有限公司 巨野电机维修-水泵维修-巨野县飞宇机电维修有限公司 | 济南玻璃安装_济南玻璃门_济南感应门_济南玻璃隔断_济南玻璃门维修_济南镜片安装_济南肯德基门_济南高隔间-济南凯轩鹏宇玻璃有限公司 | 烟气换热器_GGH烟气换热器_空气预热器_高温气气换热器-青岛康景辉 | 氟氨基酮、氯硝柳胺、2-氟苯甲酸、异香兰素-新晨化工 | 玻璃钢型材-玻璃钢风管-玻璃钢管道,生产厂家-[江苏欧升玻璃钢制造有限公司] | 大型冰雕-景区冰雕展制作公司,3D创意设计源头厂家-[赛北冰雕] | 板式换网器_柱式换网器_自动换网器-郑州海科熔体泵有限公司 | 上海三信|ph计|酸度计|电导率仪-艾科仪器 | 加盟店-品牌招商加盟-创业项目商机平台 | 环比机械 | 实验室pH计|电导率仪|溶解氧测定仪|离子浓度计|多参数水质分析仪|pH电极-上海般特仪器有限公司 | 塑料薄膜_PP薄膜_聚乙烯薄膜-常州市鑫美新材料包装厂 | 塑胶地板-商用PVC地板-pvc地板革-安耐宝pvc塑胶地板厂家 | 【德信自动化】点胶机_全自动点胶机_自动点胶机厂家_塑料热压机_自动螺丝机-深圳市德信自动化设备有限公司 | 动库网动库商城-体育用品专卖店:羽毛球,乒乓球拍,网球,户外装备,运动鞋,运动包,运动服饰专卖店-正品运动品网上商城动库商城网 - 动库商城 | 注浆压力变送器-高温熔体传感器-矿用压力传感器|ZHYQ朝辉 | 上海瑶恒实业有限公司|消防泵泵|离心泵|官网 | 百度关键词优化_网站优化_SEO价格 - 云无限好排名 |