ioc初步理解

本文介绍了软件设计中的开闭原则,并通过对比传统代码实现与使用IoC(控制反转)的差异,展示了Spring框架如何实现IOC。通过示例展示了在Spring中配置XML文件以实现Bean的创建和依赖注入,以及如何通过XML配置改变需求实现,无需修改源代码。此外,还探讨了Spring如何托管实体类并进行属性注入。

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

1、理解

1.1 以前写代码

我们一般都是先写接口,再写实现类,需求改变了我我们再修改接口对应的实现类。
如我们现在有以下:
在这里插入图片描述
UserDao有两个实现类。

public interface UserDao {
    void getUser();
}

public class UserDaoMysqlImpl implements UserDao{
    public void getUser() {
        System.out.println("mysql的实现");
    }
}
public class UserDaoOracleImpl implements UserDao{
    public void getUser() {
        System.out.println("Oracle的实现");
    }
}

此时我们在业务层是这么使用的

public class UserServiceImpl implements UserService{
    UserDao userDao = new UserDaoMysqlImpl();
    public void getUser() {
        userDao.getUser();
    }
}

测试:

public class MyTest {

    public static void main(String[] args) {
        UserService userService = new UserServiceImpl();
        userService.getUser();
    }
}

结果为

mysql的实现

我们需求改变为Oracle,我们需要去service的实现类中修改我们实现的接口

public class UserServiceImpl implements UserService{
    UserDao userDao = new UserDaoOracleImpl();
    public void getUser() {
        userDao.getUser();
    }
}

结果为

Oracle的实现

这并不符合我们的开闭原则,我们需求改变了需要修改源代码,体验不好。

1.2 改良!

相较于上面的代码,我们给userServiceImpl中的UserDao接口加上了Set方法

public class UserServiceImpl implements UserService{
    private UserDao userDao;

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

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

在测试类中,手动给UserDao赋值,结果与我们之前的一样

public class MyTest {

    public static void main(String[] args) {
        UserServiceImpl userService = new UserServiceImpl();
        userService.setUserDao(new UserDaoMysqlImpl());
        userService.getUser();
    }
}

1.3 理解

这两个的结果虽然一样,但在思想上却发生了巨大的变化,测试类是我们的用户界面

在第一个例子中,用户需要改需求必须要去改UserServiceImpl中UserDao的实现类,也就是说具体实现哪个需求是UserServiceImpl说了算

在第二个例子中,我们用户只需要在使用是给UserDao以set的方式注入,UserServiceImpl无需改变任何代码,也就是说,此时需求是用户说了算

ioc控制反转,将实现的控制权交给用户去自定义

当然这样的理解是比较粗糙的,我们看一下在spring中如何实现了ioc原理

2、spring中的ioc

2.1 我们原有的代码不用动,引入spring依赖

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.3.8</version>
</dependency>

用spring-webmvc的原因是,它可以帮助我们自动导入其他spring的东西
在这里插入图片描述

2.2 根据官网文档,我们需要创建一个beans.xml(自己命名的)文件来放入我们的bean

<?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="mysqlImpl" class="cn.butcher.dao.UserDaoMysqlImpl"/>
    <bean id="oracleImpl" class="cn.butcher.dao.UserDaoOracleImpl"/>

    <bean id="userServiceImpl" class="cn.butcher.service.UserServiceImpl">
        <property name="userDao" ref="mysqlImpl"/>
    </bean>

    
</beans>

此时我们在测试类中测试

public class MyTest {

    public static void main(String[] args) {
//        UserServiceImpl userService = new UserServiceImpl();
//        userService.setUserDao(new UserDaoMysqlImpl());
//        userService.getUser();

        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

        UserServiceImpl userServiceImpl = (UserServiceImpl) context.getBean("userServiceImpl");

        userServiceImpl.getUser();
    }
}

在这里插入图片描述
结果是我们所期待的,此时我们改变需求,只需要在xml里面配置以下就可以了,牛

<bean id="userServiceImpl" class="cn.butcher.service.UserServiceImpl">
     <property name="userDao" ref="oracleImpl"/>
 </bean>

重新运行测试类
在这里插入图片描述
在这里插入图片描述

3、再理解,使用spring托管实体类

创建User类

public class User {
    private String username ;
    private String password;

    public User() {
    }

    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

在我们的beans.xml中方注册

<bean id="user" class="cn.butcher.pojo.User">
    <property name="username" value="butcher"/>
    <property name="password" value="butcher123"/>
</bean>

此时我们来测试


public class MyTest2 {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

        User user = (User) context.getBean("user");

        System.out.println(user.toString());
    }
}

在这里插入图片描述
我们还可以以构造的形式给user注入值

    <bean id="user" class="cn.butcher.pojo.User">
        <constructor-arg name="username" value="butcher2"/>
        <constructor-arg name="password" value="butcher666"/>
    </bean>

再重新跑一下测试
在这里插入图片描述
总结

  • spring创建我们的bean默认是以无参构造创建的,如果没有无参构造,必须在标签中使用constructor-arg给bean注值
  • spring注入值得方式(property )是通过set方法注入的,如果我们没有set方法,spring就无法帮我们注入值。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值