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
真厉害,何时咱们也能写出如此优秀的框架?