Spring之理解IOC(控制反转)


一、IOC是什么?

控制反转IOC(Inversion of Control)是一个概念,是一种思想。由Spring容器进行对象的创建和依赖注入。程序员在使用时直接取出使用即可。
正转:由程序员进行对象的创建和依赖注入称为正转。程序员说了算。

Student stu = new Student(); =====>程序员创建对象
stu.setName("小明");         =====>程序员进行赋值
stu.setAge(22);

反转:由Spring容器创建对象和依赖注入称为反转,将控制权从程序员手中夺走,交给Spring容器,称为反转。

<bean id="stu" class="com.bjpowernode.pojo.Student"> ==>Spring容器创建对象
	<property name="name" value="小明">           ==>Spring容器依赖注入值
	<property name="age" value="22">
</bean>	

测试
学生实体类:

public class Student {
    private String name;
    private int age;

    public Student() {
        System.out.println("创建学生对象");
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

由程序员创建对象:

    @Test
    public void testStudent1(){
        Student stu = new Student();
    }

运行结果:
在这里插入图片描述

applicationContext.xml

    <bean id="stu" class="com.bjpowernode.pojo.Student"></bean>

由Spring容器创建对象:

 @Test
    public void testStudent2(){
        //由Spring容器进行对象创建
        //如果想从Spring容器中取出对象,则要先创建容器对象并启动才可以取对象
       ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
       //取对象
       Student stu = (Student) ac.getBean("stu");
    }

运行结果同上。

二、基于XML的IOC

2.1 创建对象

    <bean id="stu" class="com.bjpowernode.pojo.Student"></bean>

2.2 给创建的对象赋值

2.2.1 使用setter注入

注入分为简单类型注入和引用类型注入

2.2.1.1 简单类型注入使用value属性

同上。

2.1.1.2 引用类型注入使用ref属性

注意:使用setter注入必须提供无参的构造方法,必须提供setXXX()方法
引用类型注入代码(给学生添加一个学校属性,表明这个学生是哪个学校的):
School实体类:

public class School {
    private String name;
    private String address;

    //为了给成员变量注入值,必须提供无参构造方法和setXXX()方法


    public void setName(String name) {
        this.name = name;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public School(){
        System.out.println("学校的无参构造方法被调用。。。");
    }

    @Override
    public String toString() {
        return "School{" +
                "name='" + name + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}

applicationContext.xml文件,创建学校对象:

    <bean id="school" class="com.bjpowernode.pojo.School">
        <property name="name" value="西西大学"></property>
        <property name="address" value="西西区"></property>
    </bean>

Student实体类(加入学校属性以及set方法):

public class Student {
    private String name;
    private int age;
    private School school;

    public void setSchool(School school) {
        this.school = school;
    }
    public Student() {
        System.out.println("创建学生对象");
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", school=" + school +
                '}';
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

applicationContext.xml文件,创建学生对象,对于学校属性使用ref注入:

<bean id="stu" class="com.bjpowernode.pojo.Student">
        <property name="name" value="小明"></property>
        <property name="age" value="22"></property>
        <property name="school" ref="school"></property>
</bean>

测试:

    @Test
    public void testStudent2(){
        //由Spring容器进行对象创建
        //如果想从Spring容器中取出对象,则要先创建容器对象并启动才可以取对象
       ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        //取对象 
       Student stu =(Student) ac.getBean("stu");
       System.out.println(stu);
    }

运行结果:
在这里插入图片描述

2.2.2 使用构造方法注入

Student stu = new Student(“小明”,22);

2.2.2.1 使用构造方法的参数名称进行注入值

学校实体类(没有无参构造方法、没有set方法):

public class School {
    private String name;
    private String address;

    //使用带参构造方法注入值
    public School(String name, String address) {
        this.name = name;
        this.address = address;
    }

    @Override
    public String toString() {
        return "School{" +
                "name='" + name + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}

创建学校对象,并注入值:

    <bean id="school" class="com.bjpowernode.pojo.School">
       <constructor-arg name="name" value="西西大学"></constructor-arg>
        <constructor-arg name="address" value="西西区"></constructor-arg>
    </bean>
2.2.2.2 使用构造方法参数的下标注入值
 <bean id="school" class="com.bjpowernode.pojo.School">
       <constructor-arg index="0" value="西西大学"></constructor-arg>
        <constructor-arg index="1" value="西西区"></constructor-arg>
    </bean>
2.2.2.3 使用默认的构造方法的参数的顺序注入值
    <bean id="school" class="com.bjpowernode.pojo.School">
       <constructor-arg  value="西西大学"></constructor-arg>
        <constructor-arg value="西西区"></constructor-arg>
    </bean>

三、基于注解的IOC

也成为DI(Dependency Injection),它是IOC具体实现的技术。
基于注解的IOC,必须要在Spring的核心配置文件中添加包扫描。
当前实体类所在的包名:

<context:component-scan base-package="com.bjpowernode.pojo"></context:component-scan>

3.1 创建对象的注解

@Component:可以创建任意的对象

@Component
public class Student {
    private String name;
    private int age;

    public Student() {
        System.out.println("学生的无参构造方法调用了。。。");
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

测试类:

@Test
    public void testStudent1(){
       ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
    }

运行结果:
在这里插入图片描述

@Controller:专门用来创建控制器的对象,这种对象可以接受用户的请求,可以返回处理结果给客户端
@Service:专门用来创建业务逻辑层的对象,负责向下访问数据访问层,处理完毕后的结果返回给界面层
@Repository:专门用来创建数据访问层的对象,负责数据库中的增删改查所有操作

3.2 依赖注入的注解

3.2.1 值类型的注入:

@Value:用来给简单类型注入值

@Component("stu")
public class Student {
    @Value("小红")
    private String name;
    @Value("22")
    private int age;

    public Student() {
        System.out.println("学生的无参构造方法调用了。。。");
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

测试:

    @Test
    public void testStudent1(){
       ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
       Student stu = (Student) ac.getBean("stu");
       System.out.println(stu);
    }

运行结果:
在这里插入图片描述

3.2.1 引用类型的注入:

@Autowired:使用类型注入值,从整个Bean工厂中搜索同源类型的对象进行注入。
什么是同源类型:

  • 被注入的类型与注入的类型是完全相同的类型
  • 被注入的类型(父)与注入的类型(子)是父子类
    在有父子类的情况下,使用按类型注入,就意味着有多个可注入的对象,此时按照名称进行二次筛选,选中与被注入对象相同名称的对象进行注入。
  • 被注入的类型(接口)与注入的类型(实现类)是接口和实现的类型
    学校实体类:
@Component//交给spring去创建对象
public class School {//此时school对象的名称就是school
    @Value("西西西大学")
    private String name;
    @Value("西西西区")
    private String address;
    public School() {
        System.out.println("school的无参构造方法调用了。。。");
    }
    @Override
    public String toString() {
        return "School{" +
                "name='" + name + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}

学生实体类:

@Component("stu")//交给spring去创建对象
public class Student {
    @Value("小红")
    private String name;
    @Value("22")
    private int age;
    //引用类型按类型注入
    @Autowired
    private School school;
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", school=" + school +
                '}';
    }
}

XML文件中的包扫描记得添加
测试类同3.2.1中的测试
运行结果:
在这里插入图片描述

@Qualifier:使用名称注入值,从整个Bean工厂中搜索相同名称的对象进行注入
学生实体类 (多添加一个@Qualifier):

@Component("stu")
public class Student {
    @Value("小红")
    private String name;
    @Value("22")
    private int age;
    //引用类型按类型注入
    @Autowired
    private School school;
    @Override
    @Qualifier("school")
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", school=" + school +
                '}';
    }
}

其余都一样。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值