IOC原理

151 阅读3分钟
  1. IOC理论的背景 我们都知道,在采用面向对象方法设计的软件系统中,它的底层实现都是由N个对象组成的,所有的对象通过彼此的合作,最终实现系统的业务逻辑。

image.png

2.对象多了之后,对象之间的关系依赖度非常高,维护起来成本高,迁一发动全身

image.png

3.IOC是Inversion of Control的缩写,多数书籍翻译成“控制反转”。 1996年,Michael Mattson在一篇有关探讨面向对象框架的文章中,首先提出了IOC 这个概念。对于面向对象设计及编程的基本思想,前面我们已经讲了很多了,不再赘述,简单来说就是把复杂系统分解成相互合作的对象,这些对象类通过封装以后,内部实现对外部是透明的,从而降低了解决问题的复杂度,而且可以灵活地被重用和扩展。IOC理论提出的观点大体是这样的:借助于“第三方”实现具有依赖关系的对象之间的解耦,如下图:

image.png

大家看到了吧,由于引进了中间位置的“第三方”,也就是IOC容器,使得A、B、C、D这4个对象没有了耦合关系,齿轮之间的传动全部依靠“第三方”了,全部对象的控制权全部上缴给“第三方”IOC容器,所以,IOC容器成了整个系统的关键核心,它起到了一种类似“粘合剂”的作用,把系统中的所有对象粘合在一起发挥作用,如果没有这个“粘合剂”,对象与对象之间会彼此失去联系,这就是有人把IOC容器比喻成“粘合剂”的由来。

4.IOC的好处是解耦 IOC原理:把创建、销毁、维护对象依赖关系,由原来服务调用方反转到第三方,如Spring IOC容器 IOC容器在启动时主要利用反射将所有被管理的对象纳入管理,并利用DI将被依赖的对象注入

5.IOC与DI区别:IOC是理论基础,DI是实现

6.用代码模拟IOC的原理

public interface UserDao {

    void save();
}
public class UserDaoImpl implements UserDao{
    public void save() {
        System.out.println("save user ...");
    }
}
public interface UserService {

    void save();
}
public class UserServiceImpl implements UserService{
    
    private UserDao userDao;

    //通过set方法注入依赖属性
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    public void save(){
        System.out.println("call userDao.save...");
        userDao.save();
    }
}

创建bean.xml

<beans>

    <bean id="userDao" class="cn.bintools.service.UserDaoImpl"></bean>
    <bean id="userService" class="cn.bintools.service.UserServiceImpl">
        <property name="userDao" ref="userDao"></property>
    </bean>
</beans>

创建BeanFactory

public class BeanFactory {

    private Map<String, Object> singleObjects = new ConcurrentHashMap<>();

    public void start(String xml) throws DocumentException, ClassNotFoundException, IllegalAccessException, InstantiationException {
        InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(xml);
        SAXReader reader = new SAXReader();
        Document read = reader.read(inputStream);

        Element rootElement = read.getRootElement();

        List elements = rootElement.elements();
        Iterator iterator = elements.iterator();
        while (iterator.hasNext()) {
            DefaultElement defaultElement = (DefaultElement) iterator.next();
            Attribute aClass = defaultElement.attribute("class");
            Attribute idAttr = defaultElement.attribute("id");
            String className = aClass.getValue();
            Object bean = null;
            try {
                bean = Class.forName(className).newInstance();
                singleObjects.put(idAttr.getValue(), bean);
            } catch (Exception ex) {
                ex.printStackTrace();
            }
            List properties = defaultElement.elements();
            if (properties != null && properties.size() > 0) {

                Iterator innerIterator = properties.iterator();
                while (innerIterator.hasNext()) {
                    DefaultElement property = (DefaultElement) innerIterator.next();
                    Attribute nameAttr = property.attribute("name");
                    Attribute refAttr = property.attribute("ref");
                    if (nameAttr == null || refAttr == null) {
                        continue;
                    }
                    String refName = refAttr.getValue();
                    String value = nameAttr.getValue();
                    //拼接属性对应的set方法
                    String setMethod = "set" + value.substring(0, 1).toUpperCase() + value.substring(1);
                    try {
                        //获取相应属性对应字段的类型
                        Class<?> fieldType = Class.forName(className).getDeclaredField(value).getType();

                        //反映调用set方法填入引用的属性
                        Class.forName(className).getMethod(setMethod,fieldType).invoke(bean, singleObjects.get(refName));
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    public Object getBean(String className) {
        return singleObjects.get(className);
    }
}

开始测试

public class Client {

    public static void main(String[] args) throws Exception{
        BeanFactory factory = new BeanFactory();
        factory.start("bean.xml");

        UserService userService = (UserService) factory.getBean("userService");
        userService.save();
    }
}

结果:

call userDao.save...
save user ...