【String註解驅動開發】面試官讓我說說:如何使用FactoryBean向Spring容器中註冊bean?

寫在前面

在前面的文章中,我們知道可以通過多種方式向Spring容器中註冊bean。可以使用@Configuration結合@Bean向Spring容器中註冊bean;可以按照條件向Spring容器中註冊bean;可以使用@Import向容器中快速導入bean對象;可以在@Import中使用ImportBeanDefinitionRegistrar向容器中註冊bean。

項目工程源碼已經提交到GitHub:https://github.com/sunshinelyz/spring-annotation

FactoryBean概述

一般情況下,Spring通過反射機制利用bean的class屬性指定實現類來實例化bean 。在某些情況下,實例化bean過程比較複雜,如果按照傳統的方式,則需要在 標籤中提供大量的配置信息,配置方式的靈活性是受限的,這時採用編碼的方式可以得到一個更加簡單的方案。Spring為此提供了一個org.springframework.bean.factory.FactoryBean的工廠類接口,用戶可以通過實現該接口定製實例化bean的邏輯。

FactoryBean接口對於Spring框架來說佔有重要的地位,Spring 自身就提供了70多個FactoryBean的實現。它們隱藏了實例化一些複雜bean的細節,給上層應用帶來了便利。從Spring 3.0 開始, FactoryBean開始支持泛型,即接口聲明改為FactoryBean 的形式:

在Spring 5.2.6版本中,FactoryBean接口的定義如下所示。

package org.springframework.beans.factory;
import org.springframework.lang.Nullable;

public interface FactoryBean<T> {

	String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";

	@Nullable
	T getObject() throws Exception;

	@Nullable
	Class<?> getObjectType();

	default boolean isSingleton() {
		return true;
	}
}
  • T getObject():返回由FactoryBean創建的bean實例,如果isSingleton()返回true,則該實例會放到Spring容器中單實例緩存池中。
  • boolean isSingleton():返回由FactoryBean創建的bean實例的作用域是singleton還是prototype。
  • Class getObjectType():返回FactoryBean創建的bean類型。

這裏,需要注意的是:當配置文件中 標籤的class屬性配置的實現類是FactoryBean時,通過 getBean()方法返回的不是FactoryBean本身,而是FactoryBean#getObject()方法所返回的對象,相當於FactoryBean#getObject()代理了getBean()方法。

FactoryBean實例

首先,創建一個PersonFactoryBean,實現FactoryBean接口,如下所示。

package io.mykit.spring.plugins.register.bean;

import org.springframework.beans.factory.FactoryBean;
/**
 * @author binghe
 * @version 1.0.0
 * @description 商品的FactoryBean,測試FactoryBean
 */
public class PersonFactoryBean implements FactoryBean<Person> {

    //返回一個Person對象,這個對象會被註冊到Spring容器中
    @Override
    public Person getObject() throws Exception {
        return new Person();
    }

    @Override
    public Class<?> getObjectType() {
        return Person.class;
    }

    //bean是否為單例;true:是;false:否
    @Override
    public boolean isSingleton() {
        return true;
    }
}

接下來,我們在PersonConfig2類中加入PersonFactoryBean的聲明,如下所示。

@Bean
public PersonFactoryBean personFactoryBean(){
    return new PersonFactoryBean();
}

這裏需要小夥伴們注意的是:我在這裏使用@Bean註解向Spring容器中添加的是PersonFactory對象。那我們就來看看Spring容器中有哪些bean。接下來,運行SpringBeanTest類中的testAnnotationConfig7()方法,輸出的結果信息如下所示。

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
personConfig2
io.mykit.spring.plugins.register.bean.Department
io.mykit.spring.plugins.register.bean.Employee
io.mykit.spring.plugins.register.bean.User
io.mykit.spring.plugins.register.bean.Role
person
binghe001
personFactoryBean
company

可以看到,結果信息中輸出了一個personFactoryBean,我們看下這個personFactoryBean到底是個什麼鬼!此時,我們對SpringBeanTest類中的testAnnotationConfig7()方法稍加改動,添加獲取personFactoryBean的代碼,並輸出personFactoryBean實例的類型,如下所示。

@Test
public void testAnnotationConfig7(){
    ApplicationContext context = new AnnotationConfigApplicationContext(PersonConfig2.class);
    String[] names = context.getBeanDefinitionNames();
    Arrays.stream(names).forEach(System.out::println);

    Object personFactoryBean = context.getBean("personFactoryBean");
    System.out.println("personFactoryBean實例的類型為:" + personFactoryBean.getClass());
}

再次運行SpringBeanTest類中的testAnnotationConfig7()方法,輸出的結果信息如下所示。

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
personConfig2
io.mykit.spring.plugins.register.bean.Department
io.mykit.spring.plugins.register.bean.Employee
io.mykit.spring.plugins.register.bean.User
io.mykit.spring.plugins.register.bean.Role
person
binghe001
personFactoryBean
company
personFactoryBean實例的類型為:class io.mykit.spring.plugins.register.bean.Person

可以看到,雖然我在代碼中使用@Bean註解注入的PersonFactoryBean對象,但是,實際上從Spring容器中獲取到的bean對象卻是調用PersonFactoryBean類中的getObject()獲取到的Person對象。

看到這裏,是不是有種豁然開朗的感覺!!!

在PersonFactoryBean類中,我們將Person對象設置為單實例bean,接下來,我們在SpringBeanTest類中的testAnnotationConfig7()方法多次獲取Person對象,並輸出多次獲取的對象是否為同一對象,如下所示。

@Test
public void testAnnotationConfig7(){
    ApplicationContext context = new AnnotationConfigApplicationContext(PersonConfig2.class);
    String[] names = context.getBeanDefinitionNames();
    Arrays.stream(names).forEach(System.out::println);

    Object personFactoryBean1 = context.getBean("personFactoryBean");
    Object personFactoryBean2 = context.getBean("personFactoryBean");
    System.out.println(personFactoryBean1 == personFactoryBean2);
}

運行testAnnotationConfig7()方法輸出的結果信息如下所示。

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
personConfig2
io.mykit.spring.plugins.register.bean.Department
io.mykit.spring.plugins.register.bean.Employee
io.mykit.spring.plugins.register.bean.User
io.mykit.spring.plugins.register.bean.Role
person
binghe001
personFactoryBean
company
true

可以看到,在PersonFactoryBean類的isSingleton()方法中返回true時,每次獲取到的Person對象都是同一個對象,說明Person對象是單實例bean。

這裏,可能就會有小夥伴要問了,如果將Person對象修改成多實例bean呢?別急,這裏我們只需要在PersonFactoryBean類的isSingleton()方法中返回false,即可將Person對象設置為多實例bean,如下所示。

//bean是否為單例;true:是;false:否
@Override
public boolean isSingleton() {
    return false;
}

再次運行SpringBeanTest類中的testAnnotationConfig7()方法,輸出的結果信息如下所示。

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
personConfig2
io.mykit.spring.plugins.register.bean.Department
io.mykit.spring.plugins.register.bean.Employee
io.mykit.spring.plugins.register.bean.User
io.mykit.spring.plugins.register.bean.Role
person
binghe001
personFactoryBean
company
false

可以看到,最終結果返回了false,說明此時Person對象是多實例bean。

如何在Spring容器中獲取到FactoryBean對象?

之前,我們使用@Bean註解向Spring容器中註冊的PersonFactoryBean,獲取出來的確實Person對象。那麼,小夥伴們可能會問:我就想獲取PersonFactoryBean實例,該怎麼辦呢?

其實,這也很簡單, 只需要在獲取bean對象時,在id前面加上&符號即可

打開我們的測試類SpringBeanTest,在testAnnotationConfig7()方法中添加獲取PersonFactoryBean實例的代碼,如下所示。

@Test
public void testAnnotationConfig7(){
    ApplicationContext context = new AnnotationConfigApplicationContext(PersonConfig2.class);
    String[] names = context.getBeanDefinitionNames();
    Arrays.stream(names).forEach(System.out::println);

    Object personFactoryBean1 = context.getBean("personFactoryBean");
    Object personFactoryBean2 = context.getBean("personFactoryBean");
    System.out.println("personFactoryBean1類型:" + personFactoryBean1.getClass());
    System.out.println("personFactoryBean2類型:" + personFactoryBean2.getClass());
    System.out.println(personFactoryBean1 == personFactoryBean2);

    Object personFactoryBean3 = context.getBean("&personFactoryBean");
    System.out.println("personFactoryBean3類型:" + personFactoryBean3.getClass());
}

運行SpringBeanTest類中的testAnnotationConfig7()方法,輸出的結果信息如下所示。

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
personConfig2
io.mykit.spring.plugins.register.bean.Department
io.mykit.spring.plugins.register.bean.Employee
io.mykit.spring.plugins.register.bean.User
io.mykit.spring.plugins.register.bean.Role
person
binghe001
personFactoryBean
company
personFactoryBean1類型:class io.mykit.spring.plugins.register.bean.Person
personFactoryBean2類型:class io.mykit.spring.plugins.register.bean.Person
false
personFactoryBean3類型:class io.mykit.spring.plugins.register.bean.PersonFactoryBean

可以看到,在獲取bean時,在id前面加上&符號就會獲取到PersonFactoryBean實例對象。

那問題又來了!!為什麼在id前面加上&符號就會獲取到PersonFactoryBean實例對象呢?

接下來,我們就揭開這個神秘的面紗,打開BeanFactory接口,

package org.springframework.beans.factory;
import org.springframework.beans.BeansException;
import org.springframework.core.ResolvableType;
import org.springframework.lang.Nullable;

public interface BeanFactory {
	String FACTORY_BEAN_PREFIX = "&";
    /**************以下省略n行代碼***************/
}

看到這裏,是不是明白了呢?沒錯,在BeanFactory接口中定義了一個&前綴,只要我們使用bean的id來從Spring容器中獲取bean時,Spring就會知道我們是在獲取FactoryBean本身。

好了,咱們今天就聊到這兒吧!別忘了給個在看和轉發,讓更多的人看到,一起學習一起進步!!

項目工程源碼已經提交到GitHub:https://github.com/sunshinelyz/spring-annotation

寫在最後

如果覺得文章對你有點幫助,請微信搜索並關注「 冰河技術 」微信公眾號,跟冰河學習Spring註解驅動開發。公眾號回復“spring註解”關鍵字,領取Spring註解驅動開發核心知識圖,讓Spring註解驅動開發不再迷茫。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※別再煩惱如何寫文案,掌握八大原則!

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※超省錢租車方案

※教你寫出一流的銷售文案?

網頁設計最專業,超強功能平台可客製化

聚甘新

Netty中的這些知識點,你需要知道!

一、Channel

Channel是一個接口,而且是一個很大的接口,我們稱之為“大而全”,囊括了server端及client端接口所需要的接口。

Channel是一個門面,封裝了包括網絡I/O及相關的所有操作。

Channel聚合了包括網絡讀寫、鏈路管理、網絡連接信息、獲取EventLoop、Pipeline等相關功能類;統一分配,調度實現相應場景的功能。

一個Channel 對應一個物理連接,是基於物理連接上的操作包裝。

二、EventLoop

EventLoop,Event意為事件、Loop意為環,EventLoo即為事件環

EventLoop是一種程序設計結構等待以及分發事件。

NioEventLoop,是一個Netty工作線程,又不僅僅是一個Netty工作線程。

標準的netty線程模型 中我們講過Netty的標準線程池模型,池子里的每個線程對象就是一個NioEventLoop對象。或負責接受連接,或負責網絡I/O

說它不僅僅是一個Netty線程,因為它實現了很多功能,我們可以看下它的繼承圖:

它的上方有兩個枝丫,一個線程屬性,一個EventLoop,它是Netty的Reactor線程

既然是Reactor線程,那麼首先我們需要一個多路復用器。在Netty NioEventLoop中,包就含一個 Selector,它的操作對象是Channel。

NioEventLoop的主要邏輯在它的run()方法,方法體內是一個無限循環 for (;;),循環體內實現Loop功能。這也是通用的NIO線程實現方式。

 

Loop 從任務隊列里獲取任務,然後檢查多路復用器中就緒的Channel進行處理。

三、Unsafe

Netty中的Unsafe,一個Channel內部聚合接口,用以處理實際的網絡I/O讀寫。當然,取Unsafe命名,源碼中釋義:提供的網絡相關的操作方法,永遠不應該被開發人員操作使用。

它是Channel的一個輔助接口,主要方法:

1、register:註冊Channel

2、deregister:取消註冊

3、bind:綁定地址,服務端綁定監聽特定端口;客戶端指定本地綁定Socket地址。

4、connect:建立連接

5、disconnect:斷開連接

6、close:關閉連接

7、write:調度寫,將數據寫入buffer,並未真正進入Channel

8、flush:將緩衝區中的數據寫入Channel

四、AdaptiveRecvByteBufAllocator

動態緩衝區分配器,源碼說明:根據實時的反饋動態的增加或者減少預需的緩衝區大小。

如果一次分配的緩衝區被填滿了,則調高下一次分配的緩衝區大小。

如果連續兩次實際使用的容量低於分配的緩衝區大小特定比例,則減小下一次分配的緩衝區大小。

其它情景,保持分配大小不變。

Netty的這種“智能化”處理,可以說是相當有用的:

1、首先,實際的應用場景千差萬別,同一場景下不同時刻的緩衝區需求也是實時變化(一句話可以是一個字,也可能是1000個字),這就需要Netty動態調整緩衝分配大小以適應不同的業務場景,時刻場景

2、其次,過大的不必要的內存分配,會導致Buffer處理性能下降;過小的內存分配,則會導致頻繁的分配釋放。這都是一個優良的網絡框架不應該有的。 

3、最後,動態的調整最直接的好處就是內存的的高效使用,一定程度上做到了按需分配。 

五、ChannelPipeline

Pipeline 管道,Channel的數據流通管道,在這個管道中,可以做很多事情。

ChannelPipeline 是一種職責鏈,可以對其中流動的數據進行過濾、攔截處理,是一種插拔式的鏈路裝配器

1、ChannelPipline是一個容器

支持查詢、添加、刪除、替換等容器操作。

2、ChannelPipline支持動態的添加和刪除 Handler

ChannelPipline的這種特性給了我們相當的想象空間,例如動態的添加系統擁塞保護Handler,敏感數據過濾Handler、日誌記錄Handler、性能統計Handler等。

3、ChannelPipline 是線程安全的

ChannelPipline使用 synchronized 實現線程安全,業務線程可以併發的操作ChannelPipline。但需要注意的是,Handler是非線程安全的

六、HandlerAdapter

Adapter是一種適配器,對於用戶自定義的Handler,可以通過繼承HandlerAdapter,來規避不必要的接口實現

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※教你寫出一流的銷售文案?

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※回頭車貨運收費標準

※別再煩惱如何寫文案,掌握八大原則!

※超省錢租車方案

※產品缺大量曝光嗎?你需要的是一流包裝設計!

聚甘新

荷蘭開放首條塑膠再製自行車道 約含50萬個瓶蓋

摘錄自2018年09月18日科技新報報導

荷蘭人以愛好騎單車聞名,該國約 1,700 萬人,卻擁有超過 2,200 萬輛腳踏車,光是阿姆斯特丹就鋪設了近 800 公里的自行車道,東北部城鎮茲沃勒(Zwolle)日前又正式開放一條全由回收塑膠再製生成的自行車道。

該塑膠車道概念來自道路工程公司 KWS 的 Anne Koudstaal 和 Simon Jorritsma,道路全長 30 公尺,採用預製模塊,重量輕、易安裝,下方設計了排水系統讓管道、電纜通過,可讓水快速流通,遇到暴雨時還能充當臨時儲水槽、避免淹水。

據估計,這條自行車道包含了約 218,000 個塑膠杯,或 50 萬個塑膠瓶蓋,使用年限可比傳統道路長 2~3 倍(有待觀察),路面應該也不會出現裂縫或坑洞。

 

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

德國小城弗萊堡 交通轉型有成 35年私人汽車減半

環境資訊中心特約記者 陳文姿報導

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※台北網頁設計公司全省服務真心推薦

※想知道最厲害的網頁設計公司“嚨底家”!

※推薦評價好的iphone維修中心

聚甘新

維珍航空成功生產環保飛機燃料 減低環境影響

摘錄自2018年09月18日科技新報報導

維珍航空與 LanzaTech 從 2011 年開始研發環保飛機燃料技術,最近宣布終於開發成功,從鋼鐵煉製廠的工業廢氣提煉了 1,500 加侖飛機燃料。

此技術把原本排出大氣層的廢氣,透過發酵過程轉換成低碳乙醇 Lanzanol,首批 Lanzanol 在中國首鋼集團廠房生產。初步測試顯示,這種飛機燃料比傳統燃料減少 65% 碳排放,意味除了生產過程可持續,實際使用也相當環保。

兩家公司希望未來擴充生產,預計如果把計劃推展到全球鋼鐵煉製廠,可生產目前全球所有航班燃料的五分之一。維珍航空也希望明年可使用這種新燃料首次測試飛行。

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

台北網頁設計公司這麼多該如何選擇?

※智慧手機時代的來臨,RWD網頁設計為架站首選

※評比南投搬家公司費用收費行情懶人包大公開

※回頭車貨運收費標準

聚甘新

印度雨季後氣候乾燥 德里登革熱疫情飆升

摘錄自2018年09月18日中央社報導

「印度斯坦時報」(Hindustan Times)18日引述南德里市政機構(SDMC)彙整新德里、東德里和北德里等另3個市政機構的統計顯示,德里地區今年迄今的登革熱病例達243例。

在15日之前的一個星期,德里地區就通報了106起登革熱病例,高達全年迄今243例的近一半。這段時間是德里近2個月連續降雨以來,首個未降雨的星期。而雨季後出現的乾燥氣候,專家認為是登革熱病例突然飆升的主因。醫護人員和專家都擔心,最近登革熱病例的上升,現在只是開端。

為防止登革熱疫情傳布,南德里市政機構最近已對社區大規模噴灑殺蟲劑。北德里市政機構也表示,正派檢查員調查和處罰未清理積水者。

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

※教你寫出一流的銷售文案?

※超省錢租車方案

聚甘新

氣候模擬:廣設風光發電 有助撒哈拉沙漠綠化

環境資訊中心綜合外電;姜唯 編譯;林大利 審校

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※別再煩惱如何寫文案,掌握八大原則!

網頁設計最專業,超強功能平台可客製化

聚甘新

黑龍江大豆因霜害減產5.5億斤

摘錄自2018年9月18日大紀元報導

中國高度依賴進口大豆,中美貿易戰後,進口美國大豆數量驟減,黑龍江大豆主產區又遇9月上旬出現低溫霜凍天氣,導致近1,500萬畝大豆遭受凍害,估計減產5.5億斤。

中國農業農村部前(17)日通報,黑龍江省西北部地區9月9-10日出現低溫霜凍天氣,監測結果表明,大豆低溫霜凍面積約為1,478.5萬畝,產量損失預計為5.5億斤左右。大豆是喜溫作物,在整個生產期,大豆最適合生長的溫度是日平均氣溫20°~25°C,5-9月份氣溫平均降低1度,大豆畝產減產15-20斤。

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

南投搬家公司費用需注意的眉眉角角,別等搬了再說!

※教你寫出一流的銷售文案?

聚甘新

非洲豬瘟來源 陸專家疑世界盃肉品帶回病毒

摘錄自2018年9月19日中央社報導

針對非洲豬瘟傳進中國途徑,中國科學家現推斷懷疑,有可能是陸客前往俄羅斯觀看世界盃,所購買並帶回中國的肉製品帶有病毒,因未食用丟棄成為餿水,後被拿去餵養生豬引發疫情。

中國農業科學院哈爾濱獸醫研究所副研究員孫元指出,即便未通過俄羅斯世界盃這個可能管道擴散到中國,以後也會由其他路徑而來。他表示,2014年相關研究顯示中國當時確實沒有非洲豬瘟病毒,如今一個月內就在中國多地出現,蔓延之快令人警惕。

孫元也認為,蔓延原因或許跟病毒的生命力強有關。非洲豬瘟病毒耐高溫,耐pH值範圍廣,在血液、糞便和組織裡可長期存活,凍肉裡可存活數年乃至數十年,未熟肉、醃肉、泔水(餿水)、下腳料中可長時間存活。

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※想知道最厲害的網頁設計公司“嚨底家”!

※別再煩惱如何寫文案,掌握八大原則!

※產品缺大量曝光嗎?你需要的是一流包裝設計!

聚甘新

造假醜聞、禁令、民眾信心跌 德國柴油車榮景恐回不去了

環境資訊中心記者 陳文姿報導

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※別再煩惱如何寫文案,掌握八大原則!

※教你寫出一流的銷售文案?

※超省錢租車方案

FB行銷專家,教你從零開始的技巧

聚甘新