您的位置:首页 > 其它

Sping5---IOC理论推导再一步步深入

2020-03-24 12:24 363 查看

1、 IOC理论推导

原来的业务步骤:

1.UserDao接口

package edu.xalead.dao;

public interface UserDao {
void getUser();
}

2.UserDaoImpl实现类

package edu.xalead.dao;

public class UserDaoImp implements UserDao {
public void getUser(){
System.out.println("默认获取用户的数据");
}
}

package edu.xalead.dao;

public class UserDaoMySqlImp implements UserDao {
public void getUser() {
System.out.println("获取MySQL数据");
}
}

package edu.xalead.dao;

public class UserDaoOracleImp implements UserDao {
public void getUser() {
System.out.println("获取Oracle数据");
}
}

3.UserService业务接口

package edu.xalead.service;

public interface UserService {
void getUser();
}

4.UserServiceImpl业务实现类

package edu.xalead.service;

import edu.xalead.dao.UserDao;
import edu.xalead.dao.UserDaoImp;
import edu.xalead.dao.UserDaoMySqlImp;
import edu.xalead.dao.UserDaoOracleImp;

public class UserServiceImp implements UserService {
//有新的业务我们就要改代码去new一个让用户调用
private UserDao userDao = new UserDaoImp();
//    private UserDao userDao = new UserDaoMySqlImp();
//    private UserDao userDao = new UserDaoOracleImp();
public void getUser() {
userDao.getUser();
}
}

测试用户:

@Test
public void test1(){
UserServiceImp userServiceImp = new UserServiceImp();
userServiceImp.getUser();
}

比如用户又要访问sqlserver

我们需要加一个实现类

package edu.xalead.dao;

public class UserDaoSqlserverImpl implements  UserDao{

public void getUser() {
System.out.println("获取MySQL数据");
}
}

并且修改源码再new一个UserDaoSqlserverImpl:

private UserDao userDao = new UserDaoSqlserverImpl();

总结:在我们之前的业务中,用户的需求可能会影响我们原来的代码,我们需要根据用户的需求去修改源代码!如果程序代码量十分大,修改一次的成本代价十分昂贵!

现在:

我们使用一个Set接口实现,已经发生了革命性的变化!

private UserDao userDao;

//利用set进行动态实现值的注入!
public void setUserDao(UserDao userDao){
this.userDao = userDao;
}
@Test
public void test1(){
UserServiceImp userServiceImp = new UserServiceImp();
userServiceImp.setUserDao(new UserDaoImp());
userServiceImp.getUser();
}
  • 之前,程序是主动创建对象!控制权在程序员手上!
  • 使用了set注入后,程序不再具有主动性,而是变成了被动的接收对象!

这种思想,从本质上解决了问题,我们程序员不用再去管理对象的创建了。系统的耦合性大大降低,可以更加专注在业务的实现上。这是IOC的原型!

IOC本质

控制反转IOC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现IOC的一种方法。没有IOC的程序中,我们使用面向对象编程,对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,个人认为所谓控制反转就是:获得依赖对象的方式反转了。

采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的。

控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是IOC容器,其实现方式是依赖注入(Dependency Injection,DI)

2、 IOC创建对象的方式(DI中的构造器注入)

  1. 使用无参构造创建对象,默认方式!

  2. 假设我们要使用有参构造创建对象。

    1.下标赋值。

    <!--第一种,下标赋值!-->
    <bean id="user" class="com.kuang.pojo.User">
    <constructor-arg index="0" value="李四" />
    </bean>

    2.类型赋值。

    <!--第二种,通过类型创建,不建议使用,重复类型难以分辨-->
    <bean id="user" class="com.kuang.pojo.User">
    <constructor-arg type="java.lang.String" value="张三" />
    </bean>

    3.参数名赋值。

    <!--第三种,直接通过参数名来设置-->
    <bean id="user" class="com.kuang.pojo.User">
    <constructor-arg name="name" value="王五" />
    </bean>

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

3、 依赖注入

3.1 构造器注入

之前已经介绍过了

3.2 Set方式注入【重点】

  • 依赖注入:本质Set注入! 依赖:bean对象的创建依赖于容器!
  • 注入:bean对象中的所有属性,由容器来注入!

【环境搭建】

  1. 复杂类型

    public class Address {
    private String address;
    
    public String getAddress() {
    return address;
    }
    
    public void setAddress(String address) {
    this.address = address;
    }
    }
  2. 真实测试对象

    public class Student {
    private String name;
    private Address address;
    private String[] books;
    private List<String> hobbies;
    private Map<String,String> card;
    private Set<String> games;
    private String wife;
    private Properties info;
    }
    [ol]

    applicationContext.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 http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="student" class="com.kuang.pojo.Student">
    <!--第一种,普通值注入-->
    <property name="name" value="张三"/>
    </bean>
    </beans>
  3. 测试类

    public class MyTest {
    public static void main(String[] args) {
    ApplicationContext context = new 				ClassPathXmlApplicationContext("applicationContext.xml");
    Student student = (Student) context.getBean("student");
    System.out.println(student.getName());
    }
    }
[/ol]

完善注入:

<?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 id="address" class="com.kuang.pojo.Address"/>

<bean id="student" class="com.kuang.pojo.Student">
<!--第一种,普通值注入,value-->
<property name="name" value="憨批"/>
<!--第二种,Bean注入,ref-->
<property name="address" ref="address"/>
<!--数组注入-->
<property name="books">
<array>
<value>红楼梦</value>
<value>西游记</value>
<value>水浒传</value>
<value>三国演义</value>
</array>
</property>
<!--List注入-->
<property name="hobbies">
<list>
<value>听歌</value>
<value>敲代码</value>
<value>看电影</value>
</list>
</property>
<!--Map-->
<property name="card">
<map>
<entry key="身份证" value="1555555555"/>
<entry key="银行卡" value="5555555555"/>
</map>
</property>
<!--Set-->
<property name="games">
<set>
<value>lol</value>
<value>wow</value>
</set>
</property>
<!--null-->
<property name="wife">
<null/>
</property>
<!--Properties-->
<property name="info">
<props>
<prop key="driver">com.mysql.jdbc.Driver</prop>
<prop key="url">jdbc:mysql://localhost:3306/news</prop>
<prop key="root">root</prop>
<prop key="password">123456</prop>
</props>
</property>

</bean>

</beans>

3.3 拓展方式注入(其他)

我们可以使用c和p命令空间进行注入:

使用:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"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">

<!--p命名空间注入,可以直接注入属性的值:property-->
<bean id="user" class="com.kuang.pojo.User" p:name="李四" p:age="18"/>

<!--c命名空间注入,通过构造器注入:construct-args-->
<bean id="user2" class="com.kuang.pojo.User" c:age="18" c:name="张三"/>

</beans>

测试:

@Test
public void test2(){
ApplicationContext context = new ClassPathXmlApplicationContext("userbeans.xml");
User user = context.getBean("user2", User.class);
System.out.println(user.toString());
}

注意点:p和c命名空间不能直接使用,需要导入xml约束!

xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"

欢迎访问我的个人博客看完整版Spring5:http://www.ayjup.cn

  • 点赞
  • 收藏
  • 分享
  • 文章举报
AJ_007 发布了26 篇原创文章 · 获赞 1 · 访问量 435 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: