zoukankan      html  css  js  c++  java
  • 自制IOC容器(4)

    本系列文章介绍ByxContainer的实现思路。

    ByxContainer是一个简单的轻量级IOC容器,具有以下特性:

    • 使用JSON格式的配置文件
    • 支持构造函数注入、静态工厂注入、实例工厂注入、属性注入、setter注入、条件注入
    • 组件的延迟加载和单例组件
    • 根据id注册、获取容器中的组件

    ByxContainer的设计借鉴了ajoo大神的博客

    项目地址:github 码云

    本篇文章介绍ByxContainer中的条件组件。

    需求

    假设现在有一个MyDao接口,以及它的两个实现类:

    public interface MyDao {...}
    public class MyDaoImpl1 implements MyDao {...}
    public class MyDaoImpl2 implements MyDao {...}
    

    这里还有一个MyService类,它需要使用一个MyDao,所以需要通过构造函数传进来:

    public class MyService
    {
        private final MyDao myDao;
    
        public MyService(MyDao myDao)
        {
            this.myDao = myDao;
        }
        ...
    }
    

    那么,应该如何创建一个MyService对象呢?显然,可以使用下面两种方式之一:

    MyService myService = new MyService(new MyDaoImpl1());
    

    MyService myService = new MyService(new MyDaoImpl2());
    

    假设现在需要根据某个标志位“动态地”决定应该用哪种方式来创建MyService对象,类似下面这样:

    boolean flag = ...;
    MyService myService;
    if (flag)
        myService = new MyService(new MyDaoImpl1());
    else
        myService = new MyService(new MyDaoImpl2());
    

    当然,这些逻辑最好不要直接写在代码里,因为这样会导致频繁修改代码和重新编译(当标志位条件改变时)。所以,我们考虑使用IOC容器来解决这个问题。

    ConditionComponent实现类

    根据上面的描述,可以知道,ByxContainer需要支持根据某个条件创建不同组件的功能,ConditionComponent就是用来完成这项功能的:

    public class ConditionComponent implements Component
    {
        private final Component predicate;
        private final Component c1;
        private final Component c2;
    
        public ConditionComponent(Component predicate, Component c1, Component c2)
        {
            this.predicate = predicate;
            this.c1 = c1;
            this.c2 = c2;
        }
    
        @Override
        public Object create()
        {
            Object p = predicate.create();
            if (p instanceof Boolean && (boolean) p) 
                return c1.create();
            return c2.create();
        }
    }
    
    public interface Component
    {
        ...
        static Component condition(Component predicate, Component c1, Component c2)
        {
            return new ConditionComponent(predicate, c1, c2);
        }
    }
    

    ConditionComponent包含三个子组件:predicatec1c2,表示的逻辑是:如果predicate创建的对象为Boolean类型并且值为true,则返回c1创建的对象,否则返回c2创建的对象。

    使用ConditionComponent

    有了ConditionComponent,上面的需求就可以这样来实现:

    Component flag = value(true);
    Component myService = condition(
        flag, 
        constructor(MyService.class, constructor(MyDaoImpl1.class)),
        constructor(MyService.class, constructor(MyDaoImpl2.class))
    );
    

    或者这样:

    Component flag = value(true);
    Component myDao = condition(
        flag,
        constructor(MyDaoImpl1.class),
        constructor(MyDaoImpl2.class)
    );
    Component myService = constructor(MyService.class, myDao);
    

    flag也可以是一个更复杂的组件定义,例如判断某个标志字符串是否是某个特定值:

    Component database = value("XXX");
    Component flag = instanceFactory(database, "equals", value("mysql"));
    Component myDao = condition(
        flag,
        constructor(MyDaoImpl1.class),
        constructor(MyDaoImpl2.class)
    );
    Component myService = constructor(MyService.class, myDao);
    

    等价于以下逻辑:

    String database = "XXX";
    boolean flag = database.equals("mysql");
    MyDao myDao = flag ? new MyDaoImpl1() : new MyDaoImpl2();
    MyService myService = new MyService(myDao);
    

    这些配置都可以写在配置文件中,然后让ByxContainer读取配置文件来初始化容器,这样就可以在不修改代码的情况下动态改变MyService的创建过程。

  • 相关阅读:
    nginx日志格式配置
    shell入门(一)
    shell批量创建随机文件名格式文件
    Centos7 下安装配置tomcat7
    Linux安装VM虚拟化软件
    mysql初探
    java.lang.ClassNotFoundException: org.apache.commons.collections.FastHashMap
    HTTP Status 500 ? Internal Server Error
    如何使用Chrome浏览器查看网页的响应头
    Servlet的API
  • 原文地址:https://www.cnblogs.com/baiyuxuan/p/14403484.html
Copyright © 2011-2022 走看看