Spring篇——带你推导、理解和使用Spring中的IOC,一篇文章搞定!

本文介绍了Spring框架中的IoC(InversionofControl)理论,包括set注入、原型模式和控制反转的应用,展示了如何通过XML配置文件动态替换实现类,降低代码耦合度。通过实例讲解了Spring容器管理和装配对象的过程,实现了被动接收对象而非主动创建,提高了代码灵活性和可维护性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

IOC理论推导

该模块涉及Spring中的set注入,IOC原型,实现控制反转,希望大家能够认真的理解!

一、常规的开发架构


1、编写Dao接口

public interface UserDao {
    //定义接口方法,获取用户数据
    void getUser();
}

2、编写接口实现类继承Dao接口

public class UserDaoImpl implements UserDao{
    @Override
    public void getUser() {
        System.out.println("获取用户数据!");
    }
}

3、编写service接口

public interface UserService {
    void getUser();
}

4、编写service实现类

public class UserServiceImpl implements UserService{
  //想要实现业务层调用Dao层,先在业务层创建Dao层对象(组合的理念)
   private UserDao userDao = new UserDaoImpl();

    @Override
    public void getUser() {
        userDao.getUser();
    }
}

5、测试

public class MyTest {
    public static void main(String[] args) {
        //创建业务层对象
        UserServiceImpl service = new UserServiceImpl();
        
        //调用业务层方法
        service.getUser();
    }
}

6、执行结果

7、新需求,如果我们想要在Dao层多加一个需求,需要怎么实现调用呢?
新需求:

public class UserDaoMysqlImpl implements UserDao{
    @Override
    public void getUser() {
        System.out.println("通过Mysql方法,获取用户数据!");
    }
}

8、在service实现类中创建UserDaoMysqlImpl对象

public class UserServiceImpl implements UserService{
  //想要实现业务层调用Dao层,先在业务层创建Dao层对象(组合的理念)
   private UserDao userDao = new UserDaoMysqlImpl();

    @Override
    public void getUser() {
        userDao.getUser();
    }
}

9、测试

public class MyTest {
    public static void main(String[] args) {
        //创建业务层对象
        UserServiceImpl service = new UserServiceImpl();

        //调用业务层方法
        service.getUser();
    }
}

10、执行结果

我们不难发现,service实现类中要重新创建DaoImpl对象,新需求的出现会改变原来代码的功能,耦合性极高!假设我们这样的需求成千上万,这种方式根本就无法实现,每次变动都需要改动大量的代码,牵一发而动全身!!!

二、新的开发理念


1、新需求中会有多个Dao的实现类

2、在service的实现类中使用set注入

public class UserServiceImpl implements UserService {
    //想要实现业务层调用Dao层,先在业务层创建Dao层对象(组合的理念)
    //这里直接创建接口的对象,便于调用接口实现类的方法(多态)
    private UserDao userDao;

    /* set注入:运用多态的理念,当有多个Dao实现类的时候,我们在Servlet中创建UserServiceImpl对象,
        直接调用这个setUserDao,动态传入需要用到的实现类对象
        就可以实现动态调用不同的Dao实现类*/
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    @Override
    public void getUser() {
        userDao.getUser();
    }
}

3、测试中如果我们想要调用其他的Dao实现类方法,可以这样调用

public class MyTest {
    public static void main(String[] args) {
        //创建业务层对象
        UserServiceImpl service = new UserServiceImpl();

        //调用set方法,将需要用到的实现类传进去,就可以实现不改动代态调用码,动
        service.setUserDao(new UserDaoOracleImpl());
        //调用业务层方法
        service.getUser();
    }
}

4、执行结果

总结二者的区别:
之前,在service实现类中,程序都是主动创建对象,控制权在程序员手上!
而现在我们使用了set注入,程序不在具有主动性,而是被动的接收对象!
仔细思考一下,之前所有的东西都是由程序进行控制创建,而现在是由我们自行控制创建对象,把主动权交给了调用者,程序不用再去管怎么创建,怎么实现,而是更多的关注业务的实现,它只负责提供一个set接口,这样耦合性大大的被降低了,这也就是我们的IOC原型理念!

三、案例完全按照IOC进行配置优化


1、配置Beans.xml文件(详情见代码中的注释)

<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--使用Spring来创建对象,在Spring中这些都称为Bean
    bean:相当于一个Hello对象,使用bean标签,相当于new出来一个对象
    id: 相当于new出来的对象名
    class:相当于new的对象
    property中 的name: 写属性名
                value: 写属性设置的值
    -->
<!--    创建UserDaoMysqlImpl、UserDaoOracleImpl和UserServiceImpl的对象-->
    <bean id="mysqlImpl" class="com.guohui.dao.UserDaoMysqlImpl"/>
    <bean id="oracleImpl" class="com.guohui.dao.UserDaoOracleImpl"/>
    <bean id="serviceImpl" class="com.guohui.service.UserServiceImpl">
<!--        通过set依赖注入,将mysqlImpl这个对象注入到serviceImpl的属性userDao中
            其中: value:是注入一个值
                   ref: 是注入一个对象-->
        <property name="userDao" ref="mysqlImpl"/>
    </bean>
</beans>

2、测试

public class MyTest {
    public static void main(String[] args) {
        //获取Spring容器
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

        //容器获取到,需要哪个对象直接通过getBean获取即可
        UserServiceImpl serviceImpl = (UserServiceImpl) context.getBean("serviceImpl");
        
        //我们在配置文件中已经给serviceImpl的userdao属性注入了mysqlImpl对象,这里直接调用getUser方法即可
        serviceImpl.getUser();
    }
}

3、控制台打印结果

可见,通过由Spring容器统一对对象进行创建、管理和装配,使得调用者不需要去代码中修改,只在配置文件中按照需求修改即可,而我们的程序只需要被动的接收我们配置好的对象就可以,简单方便!!!!!!

HelloSpring

带你使用IOC容器编写第一个HelloSpring代码!

一、创建实体类

public class Hello {
    private String str;

    public String getStr() {
        return str;
    }

    public void setStr(String str) {
        this.str = str;
    }

    @Override
    public String toString() {
        return "Hello{" +
                "str='" + str + '\'' +
                '}';
    }
}

二、去Bean.xml文件配置实体类

<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--使用Spring来创建对象,在Spring中这些都称为Bean
    bean:相当于一个Hello对象,使用bean标签,相当于new出来一个对象
    id: 相当于new出来的对象名
    class:相当于new的对象
    property中 的name: 写属性名
                value: 写属性设置的值
    -->
    <bean id="hello" class="com.guohui.pojo.Hello">
    <!--property标签表示实体类的属性-->
    <property name="str" value="spring"/>

    </bean>
</beans>

三、测试

public class MyTest {
    public static void main(String[] args) {
        /*获取Application的上下文对象!!!
         *
         * */
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

        /*获取对象的方法
         * 由于我们已经将这个实体类在Bean.xml文件中配置,所以不需要再new对象
         * 直接通过Application的上下文对象调用getBean方法就能获得实体类对象
         * 里面传的参数是Bean.xml配置文件中实体类的id*/
        Hello hello = (Hello) context.getBean("hello");

        //测试调用实体类中的方法
        System.out.println(hello.toString());
    }
}

四、控制台结果

IOC控制反转

结合我们第一个HelloSpring程序,这个过程就叫做控制反转
控制:谁来控制对象的创建,传统应用程序的对象是由程序本身控制创建的,使用Spring后,对象是由Spring来创建的

<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--使用Spring来创建对象,在Spring中这些都称为Bean
    bean:相当于一个Hello对象,使用bean标签,相当于new出来一个对象
    id: 相当于new出来的对象名
    class:相当于new的对象
    property中 的name: 写属性名
                value: 写属性设置的值
    -->
    <bean id="hello" class="com.guohui.pojo.Hello">
    <!--property标签表示实体类的属性-->
    <property name="str" value="spring"/>

    </bean>
</beans>

反转:程序本身不创建对象,而变成了被动的接收对象

public class MyTest {
    public static void main(String[] args) {
        /*获取Application的上下文对象!!!
         *也就是获取Spring容器
         * */
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

        /*获取对象的方法
         * 由于我们已经将这个实体类在Bean.xml文件中配置,所以不需要再new对象
         * 直接通过Application的上下文对象调用getBean方法就能获得实体类对象
         * 里面传的参数是Bean.xml配置文件中实体类的id*/
        Hello hello = (Hello) context.getBean("hello");

        //测试调用实体类中的方法
        System.out.println(hello.toString());
    }
}

依赖注入:就是利用set方法进行注入
只有实体类中写了set方法,我们才能在Bean,xml配置文件中对实体类的属性进行修改

测试:
1、将实体类中的set方法删掉

2、bean.xml中的属性名爆红,意味着无法进行相关的操作

IOC是一种编程思想,由主动的编程变成被动的接收,由对象由Spring来创建、管理和装配!!!!!!

IOC创建对象的方式

一、IOC默认使用实体类的无参构造进行对象的创建
1、定义一个实体类

2、在bean.xml配置文件配置实体类

3、测试

4、控制台结果

二、如何用有参构造进行创建对象呢?
准备工作:
先在实体类中增加一个带参构造(声明了带参构造那么默认的无参构造就消失了),并且定义一个方法

1、通过实体类的属性下标index进行创建和赋值
按照属性的顺序从0开始,进行赋值

<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd">

<!--    带参构造创建对象-->
    <bean id="user" class="com.guohui.pojo.User">
       <constructor-arg index="0" value="李四"/>
    </bean>
</beans>

2、通过属性的类型进行赋值(有局限性,如果我的实体类中有多个相同类型的属性,那么就无法识别了)

<!--    带参构造创建对象-->
    <bean id="user" class="com.guohui.pojo.User">
       <constructor-arg type="java.lang.String" value="水水水水水水水"/>
    </bean>

控制台结果:

3、可以直接通过参数名对属性进行赋值

<!--    带参构造创建对象-->
    <bean id="user" class="com.guohui.pojo.User">
       <constructor-arg name="name" value="ogdadgadhaa"/>
    </bean>

控制台打印结果:

总结:在配置文件加载的时候,容器中管理的对象就已经被初始化了!!!

至此,你对IOC的概念、他究竟如何实现控制反转以及实现的方法已经掌握,后续会持续更新关于Spring的技术讲解,敬请期待!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Be explorer

若认可笔者文章,手头富裕望支持

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值