面对iOC容器是什么,这样一个抽象的概念不同的时期有不同的理解。我也是尝试从我认识的角度去描述我所知道的冰山一角。我并不觉得这可以给大家很大的帮助,我只是自己做个笔记,随后想起来就修改一点,使之成为我的一笔财富。


一、接口存在的意义

现在大家都用电脑,也能接触到鼠标。鼠标是有可能会坏的,或者说,大家对鼠标都有不同的喜好。为了统一,所有鼠标厂商设计鼠标只要遵循一定的规则(接口),电脑就可以识别和使用。
同理
在dao层,要操作user表,为了方便后续更换数据库,就需要写一个IUserDao的接口

public interface IUserDao {
    public User getUserById(Integer id);
}

当使用Mysql数据库和Oracle数据库时,都实现这个接口就好了。

public class UserDaoMysqlImpl implements IUserDao{
    @Override
    public User getUserById(Integer id) {
        User u = new User();
        u.setId(id);
        u.setAge(18);
        u.setName("Mysql");
        return u;
    }
}
public class UserDaoOracleImpl implements IUserDao{
    @Override
    public User getUserById(Integer id) {
        User u = new User();
        u.setId(id);
        u.setAge(17);
        u.setName("Oracle");
        return u;
    }
}

在service层调用时如果使用mysql数据库

public class UserServiceImpl implements IUserService{
    /**
     * 使用mysql时
     */
    private IUserDao dao = new UserDaoMysqlImpl();
    @Override
    public void getUser() {
        User u = dao.getUserById(18);
        System.out.println(u);
    }
}

测试类

public class UserTest {
    public static void main(String[] args) {
        IUserService service = new UserServiceImpl();
        service.getUser();
    }
}

现在的整个包结构如下
在这里插入图片描述
现在运行这个测试类,可以看到控制太输出的是一下内容

User{name='Mysql', age=18, id=18}

如果使用oracle数据库,则需要修改UserServiceImpl

public class UserServiceImpl implements IUserService{
    /**
     * 使用Oracle时
     */
    private IUserDao dao = new UserDaoOracleImpl();
    @Override
    public void getUser() {
        User u = dao.getUserById(18);
        System.out.println(u);
    }
}

此时再次运行测试类,可以看到控制台输出。

User{name='Oracle', age=17, id=18}

二、问题

现在这种方式,就好像鼠标直接焊接再主板上,每次更换鼠标,都需要焊接一次,这种上层(主机)依赖下层(鼠标)的设计显然十分不方便。此时的电脑需要依赖鼠标才能启动,没有鼠标就没法启动了。

在这里插入图片描述

因此做成usb的形式,没有了鼠标,电脑依然可以启动,但是需要依赖USB才能插到电脑上使用。控制权转变了,原本是电脑依赖鼠标,现在是鼠标依赖USB。
在这里插入图片描述
那么实际上这种转变,称之为ioc(控制反转),这是一种思想,而后面要讲到的DI是这个思想的实现。

搭建spring环境

ioc思想是spring的核心思想,因此需要先把spring环境搭建好,继续介绍。
到仓库去下载好包。
同时,这一次没有采用maven的方式,配置也是采用xml的方式。因为xml的方式也比较直观。
spring仓库
在这里插入图片描述
引入包
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
暂且只是用到spring核心的部分,因此我们可以先只引入

beans、context、core、expression、jcl

在这里插入图片描述
导包成功之后,就可以新增一个spring.xml配置文件了
在这里插入图片描述
spring.xml配置文件中,这里创建两个bean,同时通过依赖注入的方式,将dao注入到service中

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

        <bean class="dao.UserDaoMysqlImpl" id="daoMysql"></bean>
        <bean class="service.UserServiceImpl" id="userService">
                <!--依赖注入-->
                <property name="dao" ref="daoMysql"></property>
        </bean>
</beans>

由于xml的方式使用依赖注入,需要有getset方法

public class UserServiceImpl implements IUserService{
    /**
     * 使用Oracle时
     */
    private IUserDao dao ;

    public IUserDao getDao() {
        return dao;
    }

    public void setDao(IUserDao dao) {
        this.dao = dao;
    }

    @Override
    public void getUser() {
        User u = dao.getUserById(18);
        System.out.println(u);
    }
}

最后修改一下测试类

public class UserTest {
    public static void main(String[] args) {
        ApplicationContext ioc = new ClassPathXmlApplicationContext("spring.xml");
        IUserService service = ioc.getBean(IUserService.class);
        service.getUser();
    }
}

最终也能够正常输出。
此时可以发现,如果更换了数据库,只需要在spring.xml中进行修改,这样即使有很多地方使用,也只需要更改一个地方就可以。十分方便,它们之间的耦合度大大降低了。

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐