02.spring-ioc概念

66 阅读2分钟

前言

这部分开始,主要接触的就是spring体系结构的这部分内容:

image-20230130134132555

这部分可以看成是IOC【Inversion of Control】。简单理解ioc就是对象由代码方式创建变成交给spring容器创建。

权威解释如下:

image-20230130135235879

IOC是控制反转,而DI【依赖注入】是IOC的一种实现方式。这里的反转可能理解起来有点抽象,那么有反转自然应该有正转。什么是正转呢?我们可以按照传统的JavaSE思想,在A类里,写代码B b = new B();,通过new关键字获取A类的依赖对象,或者通过工厂模式进行获取,当然还有等等其它方法。这些方法,就属于正转的方法,因为A类获取B类就是通过主动的方法进行获取的,统称为正转的方法。既然正转是主动的方式,那么反转就是被动的方式。也即我们要获取某个类的依赖对象,不需要类主动去创建。交由Spring框架来给我们进行创建。这就是反转的意思了。在Spring框架里,实现IOC,是通过IOC容器实现的,由IOC容器负责创建和获取依赖对象,对象只是被动地接受依赖对象。

正转的弊端

上面已经说了,正转就是自己new一个对象出来供自己使用,自己new对象有什么弊端呢?如下图:

image-20230228143445202

Spring-IOC反转的解耦

image-20230130164711311

自己实现IOC控制反转

1. 引入依赖

<dependencies>
    <dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.8.11</version>
    </dependency>

    <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13.2</version>
    <scope>test</scope>
    </dependency>
</dependencies>

2. 配置文件

<beans>
    <bean id="userDao" clazz="com.mayuanfei.springioc.dao.impl.UserDaoImpl"/>
</beans>

3. Bean配置对象

public class Bean {
    /**
     * bean的id
     */
    private String id;

    /**
     * bean的全路径名
     */
    private String clazz;
}

4. Bean容器

public class BeanContext {
    public Map<String, Object> beansMap = new ConcurrentHashMap<String, Object>();

    /**
     * 构造方法.把配置文件的类路径传入
     *
     * @param classPath 类路径文件名
     */
    public BeanContext(String classPath) {
        InputStream resource = BeanContext.class.getClassLoader().getResourceAsStream(classPath);
        Document document = XmlUtil.readXML(resource);
        List<Element> elements = XmlUtil.getElements(XmlUtil.getRootElement(document), "bean");
        for (Element element : elements) {
            beansMap.put(element.getAttribute("id"),
                    ReflectUtil.newInstance(element.getAttribute("clazz")));
        }

    }

    /**
     * 获得Bean实例对象
     *
     * @param id bean的id
     * @return 实例对象
     */
    public Object getBean(String id) {
        if (beansMap.containsKey(id)) {
            return beansMap.get(id);
        }
        return null;
    }
}

5. UserDao接口

public interface UserDao {
    /**
     * 添加数据
     */
    public void append();
}

6. UserDao两个实现类

public class UserDaoImpl implements UserDao {
    /**
     * 添加数据
     */
    @Override
    public void append() {
        System.out.println("UserDaoImpl 插入数据库");
    }
}

public class UserDaoImpl2 implements UserDao {
    /**
     * 添加数据
     */
    @Override
    public void append() {
        System.out.println("UserDaoImpl2 插入数据库");
    }
}

7. 测试类

@Test
public void testIoc() {
    BeanContext context = new BeanContext("BeanConfig.xml");
    UserDao userDao = (UserDao) context.getBean("userDao");
    userDao.append();
}

8.代码地址

gitee.com/mayuanfei/S… 下的SpringIoc01

记忆印记

  • 控制反转(IOC)是一个编程思想,而依赖注入(DI)是该思想的一个具体实现
  • IOC理解为:以前自己new对象,现在交给spring框架帮忙管理创建对象,用的时候让spring框架帮忙注入即可
  • IOC实现的核心为一个配置文件,一个维护id和实例对象的Map