IOC
,全稱Inversion of Control
,控制反轉。也算是老生常談了。java
老生常談:原指老書生的平凡議論;今指常講的沒有新意的老話。
同時另外一個話題,依賴注入,用什麼就聲明什麼,直接就聲明,或者構造函數或者加註解,控制反轉是實現依賴注入的一種方式。程序員
經過依賴注入:咱們無需管理對象的建立,經過控制反轉:咱們能夠一鍵修改注入的對象。spring
最近在作Android
實驗與小程序相關的開發,發現用慣了IOC
的咱們再去手動new
對象的時候總感受內心不舒服,之後改起來怎麼辦呢?既然沒有IOC
,咱們就本身寫一個吧。小程序
就像我在標題中描述的同樣,我先給你們講解一下標配IOC
的原理,使你們更清晰明瞭,可是受Android
與小程序相關的限制,我具體的實現,是低配版IOC
。服務器
不論是Spring
仍是Angular
,要麼是開源你們,要麼是商業巨頭,具體的框架實現都是至關優秀。我還沒水平也沒精力去研讀源碼,只但願分享本身對IOC
的理解,幫到更多的人。網絡
畢竟如今小學生都開始寫Python
,之後的框架設計會愈來愈優秀,學習成本愈來愈低,開發效率愈來愈高。多是我的報個培訓班學個倆月也會設計微服務,也能成爲全棧工程師。因此咱們應該想的是如何設計框架,而不是僅停留在使用的層面,漸漸地被只會寫增刪改查每天搬磚的人取代。框架
996
加班的工程師都開始擠時間寫框架擴大影響力,讓社會聽到程序員的吶喊,咱們還有什麼不努力的理由?ide
IOC
不論是Spring
仍是Angular
,它們的核心是什麼呢?打上mvn spring-boot:run
後臺就Started Application in xxx seconds
了,它到底幹什麼了呢?函數
Spring
與Angular
就是一個大的IOC
容器,因此應用啓動的過程,其實就是構造容器的過程。spring-boot
容器,確定是裝東西的啊?IOC
容器裏裝的是什麼?
裝的是對象。控制器Controller
,服務Service
,自定義的組件Component
,全部被Spring
管理的對象都將被放進IOC
容器裏。
因此,你們應該能明白,爲何IOC
是依賴注入的一種實現方式?
由於這個對象不是你本身new
的,是從容器中拿的,容器初始化的時候,就已經把這個對象構造好了,該注的都注進來了。
從上面你們能夠看到,依賴注入的前提是什麼?是要求這個對象必須是從容器中拿的,因此才能依賴注入成功。
Spring Boot
中沒問題,Tomcat
轉發的路由直接交給容器中相應的對象去處理,同理,Angular
也同樣。
Android
呢?
手機調用的並非咱們構造的Activity
,而是它本身實例化的,小程序也與之相似,Page
的實例化不歸咱們管。
因此「標配」IOC
在這裏不適用,因此我設計了「低配」IOC
容器。
IOC
找點本身能管得了的對象放在IOC
容器裏,這樣再須要對象就不用去new
了,Service
有變動直接修改注入就好了。
受咱們管理的只有Service
,計劃設計一個管理全部Service
的IOC
容器,而後Activity
或Page
裏用的時候,直接從容器中拿。(低配在這裏,不能依賴注入了,得本身拿)。
Android
端一個單例的Configuration
負責註冊Bean
和獲取Bean
,存儲着一個context
上下文。看着挺高級的,其實就是一個HashMap
存儲着接口類型
到容器對象
的映射。
/** * 全局配置類 */ public class Configuration { private static Map<Class<?>, Object> context = new HashMap<>(); private static final class Holder { private static final Configuration INSTANCE = new Configuration(); } public static Configuration getInstance() { return Holder.INSTANCE; } public Configuration registerBean(Class<?> clazz, Object bean) { context.put(clazz, bean); return this; } public <T> T getBean(Class<?> clazz) { return (T) context.get(clazz); } }
寫一個靜態方法,更加方便配置。
/** * 雲智,全局配置輔助類 */ public class Yunzhi { ... public static <T> T getBean(Class<?> clazz) { return Configuration.getInstance().getBean(clazz); } }
一個Application
負責容器中全部對象的建立。
public class App extends Application { @Override public void onCreate() { super.onCreate(); Yunzhi.init() .setApi("http://192.168.2.110:8888") .setTimeout(1L) .registerBean(AuthService.class, new AuthServiceImpl()) .registerBean(LetterService.class, new LetterServiceImpl()); } }
使用方法和原來就同樣了,一個接口,一個實現類。這裏用到了RxJava
,看上去卻是相似咱們的Angular
了。
public interface AuthService { Observable<Auth> login(String username, String password); }
public class AuthServiceImpl implements AuthService { private static final String TAG = "AuthServiceImpl"; @Override public Observable<Auth> login(String username, String password) { Log.d(TAG, "BASIC 認證"); String credentials = username + ":" + password; String basicAuth = "Basic " + Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP); Log.d(TAG, "請求登陸"); return HttpClient.request(AuthRequest.class) .login(basicAuth) .subscribeOn(Schedulers.io()) // 在IO線程發起網絡請求 .observeOn(AndroidSchedulers.mainThread()); // 在主線程處理 } }
由於Activity
咱們管不着,因此在Activity
裏用不了依賴注入,須要手動從容器裏拿。
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.authService = Yunzhi.getBean(AuthService.class); }
這裏有一處沒考慮到的問題,就是手機端的性能問題,手機和服務器的處理能力確定是比不了的,服務器在初始化的時候把全部對象都建立處理無可厚非,可是感受手機端這樣作仍是會對性能產生必定影響的。
應該是某些對象用到的時候再建立,實驗要求時間很緊,這個就先這樣吧,不改了。
小程序是在Android
以後寫的,想到了以前設計的部分缺陷,對容器
使用了另外一種思想進行實現。
export class YunzhiService { private static context = new Map<string, object>(); public static getBean(beanName: string): object { // 從context裏拿對象 let bean = this.context.get(beanName); // 若是沒有,構造一個,並放進context if (!bean) { bean = this.createBeanByName(beanName); this.context.set(beanName, bean); } // 返回 return bean; } public static createBeanByName(beanName: string): object { // 根據不一樣名稱構造不一樣的Bean switch (beanName) { case Bean.AUTH_SERVICE: return new AuthServiceImpl(); case Bean.SCORE_SERVICE: return new ScoreServiceImpl(); case Bean.SEMESTER_SERVICE: return new SemesterServiceImpl(); default: throw '錯誤,未註冊的bean'; } } }
Spring Boot
真厲害,何時咱們也能寫出如此優秀的框架?