资讯专栏INFORMATION COLUMN

手动实现“低配版”IOC

psychola / 1042人阅读

摘要:实现就像我在标题中描述的一样,我先给大家讲解一下标配的原理,使大家更清晰明了,但是受与小程序相关的限制,我具体的实现,是低配版。低配在这里,不能依赖注入了,得自己拿。

引言

IOC,全称Inversion of Control,控制反转。也算是老生常谈了。

老生常谈:原指老书生的平凡议论;今指常讲的没有新意的老话。

同时另一个话题,依赖注入,用什么就声明什么,直接就声明,或者构造函数或者加注解,控制反转是实现依赖注入的一种方式。

通过依赖注入:我们无需管理对象的创建,通过控制反转:我们可以一键修改注入的对象。

最近在做Android实验与小程序相关的开发,发现用惯了IOC的我们再去手动new对象的时候总感觉心里不舒服,以后改起来怎么办呢?既然没有IOC,我们就自己写一个吧。

实现

就像我在标题中描述的一样,我先给大家讲解一下标配IOC的原理,使大家更清晰明了,但是受Android与小程序相关的限制,我具体的实现,是低配版IOC

个人扯淡

不管是Spring还是Angular,要么是开源大家,要么是商业巨头,具体的框架实现都是相当优秀。我还没水平也没精力去研读源码,只希望分享自己对IOC的理解,帮到更多的人。

毕竟现在小学生都开始写Python,以后的框架设计会越来越优秀,学习成本越来越低,开发效率越来越高。可能是个人报个培训班学个俩月也会设计微服务,也能成为全栈工程师。所以我们应该想的是如何设计框架,而不是仅停留在使用的层面,渐渐地被只会写增删改查天天搬砖的人取代。

996加班的工程师都开始挤时间写框架扩大影响力,让社会听到程序员的呐喊,我们还有什么不努力的理由?

“标配”IOC

不管是Spring还是Angular,它们的核心是什么呢?打上mvn spring-boot:run后台就Started Application in xxx seconds了,它到底干什么了呢?

容器

SpringAngular就是一个大的IOC容器,所以应用启动的过程,其实就是构造容器的过程。

容器,肯定是装东西的啊?IOC容器里装的是什么?

装的是对象。控制器Controller,服务Service,自定义的组件Component,所有被Spring管理的对象都将被放进IOC容器里。

所以,大家应该能明白,为什么IOC是依赖注入的一种实现方式?

因为这个对象不是你自己new的,是从容器中拿的,容器初始化的时候,就已经把这个对象构造好了,该注的都注进来了。

思考

从上面大家可以看到,依赖注入的前提是什么?是要求这个对象必须是从容器中拿的,所以才能依赖注入成功。

Spring Boot中没问题,Tomcat转发的路由直接交给容器中相应的对象去处理,同理,Angular也一样。

Android呢?

手机调用的并不是我们构造的Activity,而是它自己实例化的,小程序也与之类似,Page的实例化不归我们管。

所以“标配”IOC在这里不适用,所以我设计了“低配”IOC容器。

“低配”IOC

找点自己能管得了的对象放在IOC容器里,这样再需要对象就不用去new了,Service有变更直接修改注入就行了。

受我们管理的只有Service,计划设计一个管理所有ServiceIOC容器,然后ActivityPage里用的时候,直接从容器中拿。(低配在这里,不能依赖注入了,得自己拿)。

Android

一个单例的Configuration负责注册Bean和获取Bean,存储着一个context上下文。看着挺高级的,其实就是一个HashMap存储着接口类型容器对象的映射。

/**
 * 全局配置类
 */
public class Configuration {

    private static Map, 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 getBean(Class clazz) {
        return (T) context.get(clazz);
    }
}

写一个静态方法,更加方便配置。

/**
 * 云智,全局配置辅助类
 */
public class Yunzhi {

    ...

    public static  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 login(String username, String password);
}
public class AuthServiceImpl implements AuthService {

    private static final String TAG = "AuthServiceImpl";

    @Override
    public Observable 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();

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

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/14849.html

相关文章

  • 模仿RequireJs的用法实现一个配版的模块加载器

    摘要:我想自己可以尝试一下写一个低配版的模块加载器来应付一下我这个单页网站,当然只是大致模仿了主要功能。是这样处理的模块依赖,同时依赖,这种情况下的模块函数被调用时,被传入的是,所以需要自己在里面手动一下。 Contents 前言 回顾RequireJs的基本用法 实现原理 使用方法 总结 前言 前段时间一直想用单页开发技术写一个自己的个人网站(使用es2015),写了一部分之后,发现单...

    WalkerXu 评论0 收藏0
  • 【教学向】再加150行代码教你实现一个配版的web component库(1) —设计篇

    摘要:为的内置一个方法,用法和原生的事件机制一毛一样。 前言 上两篇Mvvm教程的热度超出我的预期,很多码友留言表扬同时希望我继续出下一篇教程,当时我也半开玩笑说只要点赞超10就兑现承诺,没想到还真破了10,所以就有了今天的文章。 准备工作 熟读 【教学向】150行代码教你实现一个低配版的MVVM库(1)- 原理篇【教学向】150行代码教你实现一个低配版的MVVM库(2)- 代码篇 本篇是在...

    Clect 评论0 收藏0
  • 【教学向】150行代码教你实现一个配版的MVVM库(1)- 原理篇

    摘要:模块则负责维护,以及各个模块间的调度思考题了解了的实现机制,你能否自己动手也试着用百来行代码实现一个库呢好了本教程第一部分设计篇就写到这里,具体请移步下一篇教学向行代码教你实现一个低配版的库代码篇我会用给出一版实现。 适读人群 本文适合对MVVM有一定了解(如有主流框架ng,vue等使用经验配合本文服用则效果更佳),虽然会用这类框架,但是对框架底层核心实现又不太清楚,或者能说出个所以然...

    selfimpr 评论0 收藏0
  • 基于canvas和web audio实现配版MikuTap

    摘要:导言最近发掘了一个特别的网页小游戏。于是第二天我就继续沉迷,随着一阵抽搐,这个游戏索然无味之后,冷静的我决定用和开发出一个低配版。我的低配版在交互操作比较高的情况下,还是比较卡的,没有原网页的流畅性,可能后续考虑版本实现。 导言 最近发掘了一个特别happy的网页小游戏--MikuTap。打开之后沉迷了一下午,导致开发工作没做完差点就要删库跑路了,还好boss瞥了我一眼就没下文了。于是...

    Awbeci 评论0 收藏0
  • 基于canvas和web audio实现配版MikuTap

    摘要:导言最近发掘了一个特别的网页小游戏。于是第二天我就继续沉迷,随着一阵抽搐,这个游戏索然无味之后,冷静的我决定用和开发出一个低配版。我的低配版在交互操作比较高的情况下,还是比较卡的,没有原网页的流畅性,可能后续考虑版本实现。 导言 最近发掘了一个特别happy的网页小游戏--MikuTap。打开之后沉迷了一下午,导致开发工作没做完差点就要删库跑路了,还好boss瞥了我一眼就没下文了。于是...

    luffyZh 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<