Spring学习(二)-IOC容器

一、IOC  &&  DI介绍

1.1、简介

1)IOC(Inversion of Control):其思想是反转资源获取的方向. 传统的资源查找方式要求组件向容器发起请求查找资源. 作为回应, 容器适时的返回资源. 而应用了 IOC 之后, 则是容器主动地将资源推送给它所管理的组件, 组件所要做的仅是选择一种合适的方式来接受资源. 这种行为也被称为查找的被动形式
2)DI(Dependency Injection) — IOC 的另一种表述方式:即组件以一些预先定义好的方式(例如: setter 方法)接受来自如容器的资源注入. 相对于 IOC 而言,这种表述更直接

1.2、IOC底层使用原理

1)XML解析技术

2)工厂方法

3)反射

二、IOC容器

2.1、BeanFactory

在 Spring IOC 容器读取 Bean 配置创建 Bean 实例之前, 必须对它进行实例化. 只有在容器实例化后, 才可以从 IOC 容器里获取 Bean 实例并使用.

image

Spring 提供了两种类型的 IOC 容器实现.

1)BeanFactory: IOC 容器的基本实现.

2)ApplicationContext: 提供了更多的高级特性. 是 BeanFactory 的子接口.

3)BeanFactory 是 Spring 框架的基础设施,面向 Spring 本身;ApplicationContext 面向使用 Spring 框架的开发者,几乎所有的应用场合都直接使用 ApplicationContext 而非底层的 BeanFactory

4)无论使用何种方式, 配置文件时相同的

2.2、ApplicationContext

image

ApplicationContext 的主要实现类:

1)ClassPathXmlApplicationContext:从 类路径下加载配置文件

2)FileSystemXmlApplicationContext: 从文件系统中加载配置文件

ConfigurableApplicationContext 扩展于 ApplicationContext,新增加两个主要方法:refresh() 和 close(), 让 ApplicationContext 具有启动、刷新和关闭上下文的能力

ApplicationContext 在初始化上下文时就实例化所有单例的 Bean

三、Bean管理(基于XML)

3.1、基于XML创建对象

<!--配置User对象-->
<bean id="user" class="com.dianchou.spring.User"></bean>

1)在 spring 配置文件中,使用 bean 标签,标签里面添加对应属性,就可以实现对象创建

2)在 bean 标签有很多属性,介绍常用的属性

  • id 属性:唯一标识
  • class 属性:类全路径(包类路径)

3)创建对象时候,默认也是执行无参数构造方法完成对象创建

3.2、基于XML注入属性

3.2.1、使用 set 方法进行注入

1)创建类,定义属性和对应的 set 方法

package com.dianchou.spring;

/**
 * @author lawrence
 * @create 2020-07-07 11:55
 */
public class Book {
    private String name;
    private String author;

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

    public void setAuthor(String author) {
        this.author = author;
    }

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

2)在 spring 配置文件配置对象创建,配置属性注入

<!--配置Book对象-->
<bean id="book" class="com.dianchou.spring.Book">
    <!--使用 property 完成属性注入
        name:类里面属性名称
        value:向属性注入的值
     -->
    <property name="name" value="红楼梦"></property>
    <property name="author" value="曹雪芹"></property>
</bean>

3)测试

@Test
public void testBook(){
    ApplicationContext ctx = new ClassPathXmlApplicationContext("bean1.xml");
    Book book = ctx.getBean("book", Book.class);
    System.out.println(book);
}

image

3.2.2、使用有参数构造进行注入

1)创建类,定义属性,创建属性对应有参数构造方法

package com.dianchou.spring;

/**
 * @author lawrence
 * @create 2020-07-07 14:06
 */
public class Order {
    private String name;
    private String address;

    public Order() {
    }

    public Order(String name, String address) {
        this.name = name;
        this.address = address;
    }

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

2)在 spring 配置文件中进行配置

<!--  配置Order对象  -->
<bean id="order" class="com.dianchou.spring.Order">
    <constructor-arg name="name" value="电脑"></constructor-arg>
    <constructor-arg name="address" value="深圳"></constructor-arg>
</bean>
3)测试
@Test
public void testOrder(){
    ApplicationContext ctx = new ClassPathXmlApplicationContext("bean1.xml");
    Order order = ctx.getBean("order", Order.class);
    System.out.println(order);
}
image

3.2.3、p名称空间注入

使用 p 名称空间注入,可以简化基于 xml 配置方式

1)在配置文件中添加p名称空间

image

2)在配置文件中进行属性注入

<bean id="book" class="com.dianchou.spring.Book" p:name="AAA" p:author="BBB"></bean>

3.2.4、字面量注入

1)null值注入

<!--配置Book对象-->
<bean id="book" class="com.dianchou.spring.Book">
    <property name="name" value="红楼梦"></property>
    <property name="author">
        <null/>
    </property>
</bean>

2)特殊符号注入

<!--配置Book对象-->
<bean id="book" class="com.dianchou.spring.Book">
    <!--属性值包含特殊符号
     1 把<>进行转义 &lt; &gt;
     2 把带特殊符号内容写到 CDATA
    -->
    <property name="name">
        <value><![CDATA[<<红楼梦>>]]></value>
    </property>
    <property name="author" value="曹雪芹"></property>
</bean>
image

3.2.5、外部bean注入

1)创建UserService类和UserDao接口及接口的实现类

UserDao接口:

package com.dianchou.spring.dao;

/**
 * @author lawrence
 * @create 2020-07-07 14:41
 */
public interface UserDao {
    public void add();
}

UserDaoImpl实现类:

package com.dianchou.spring.dao;

/**
 * @author lawrence
 * @create 2020-07-07 14:42
 */
public class UserDaoImpl implements UserDao{
    @Override
    public void add() {
        System.out.println("UserDaoImpl add....");
    }
}

UserService:

package com.dianchou.spring.service;

import com.dianchou.spring.dao.UserDao;

/**
 * @author lawrence
 * @create 2020-07-07 14:42
 */
public class UserService {
    private UserDao userDao;

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

    public void add(){
        System.out.println("UserService add...");
        userDao.add();
    }
}

2)spring配置文件中配置

<!--  注入userDaoImpl  -->
<bean id="userDaoImpl" class="com.dianchou.spring.dao.UserDaoImpl"></bean>
<!--注入UserService-->
<bean id="userService" class="com.dianchou.spring.service.UserService">
    <!--注入 userDao 对象
     name 属性:类里面属性名称
     ref 属性:创建 userDao 对象 bean 标签 id 值
     -->
    <property name="userDao" ref="userDaoImpl"></property>
</bean>

3)测试

@Test
public void testUserService(){
    ApplicationContext ctx = new ClassPathXmlApplicationContext("bean1.xml");
    UserService userService = ctx.getBean("userService", UserService.class);
    System.out.println(userService);
    userService.add();
}
image

3.2.6、内部bean注入

一对多关系:部门和员工 ,在实体类之间表示一对多关系,员工表示所属部门,使用对象类型属性进行表示

1)创建部门和员工类

部门类:

package com.dianchou.spring.dao;

/**
 * @author lawrence
 * @create 2020-07-07 15:00
 */
public class Department {
    private String departmentName;

    public void setDepartmentName(String departmentName) {
        this.departmentName = departmentName;
    }

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

员工类:

package com.dianchou.spring.dao;

/**
 * @author lawrence
 * @create 2020-07-07 15:01
 */
public class Employee {
    private String name;
    private String gender;
    //员工属于某一个部门,使用对象形式表示
    private Department department;

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

    public void setGender(String gender) {
        this.gender = gender;
    }

    public void setDepartment(Department department) {
        this.department = department;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "name='" + name + '\'' +
                ", gender='" + gender + '\'' +
                ", department=" + department +
                '}';
    }
}

2)spring配置文件

<bean id="employee" class="com.dianchou.spring.dao.Employee">
    <!--配置普通属性-->
    <property name="name" value="lawrence"></property>
    <property name="gender" value="男"></property>
    <!--配置对象属性-->
    <property name="department">
        <bean id="department" class="com.dianchou.spring.dao.Department">
            <property name="departmentName" value="研发部"></property>
        </bean>
    </property>
</bean>

3)测试

@Test
public void testEmployee() {
    ApplicationContext ctx = new ClassPathXmlApplicationContext("bean1.xml");
    Employee employee = ctx.getBean("employee", Employee.class);
    System.out.println(employee);
}
image

3.2.7、级联赋值

1)方式一

<bean id="employee" class="com.dianchou.spring.dao.Employee">
    <!--配置普通属性-->
    <property name="name" value="lawrence"></property>
    <property name="gender" value="男"></property>
    <!--配置对象属性-->
    <property name="department" ref="department"></property>
</bean>
<bean id="department" class="com.dianchou.spring.dao.Department">
    <property name="departmentName" value="研发部"></property>
</bean>

2)方式二

<bean id="employee" class="com.dianchou.spring.dao.Employee">
    <!--配置普通属性-->
    <property name="name" value="lawrence"></property>
    <property name="gender" value="男"></property>
    <!--配置对象属性-->
    <property name="department" ref="department"></property>
    <property name="department.departmentName" value="开发部"></property>
</bean>
<bean id="department" class="com.dianchou.spring.dao.Department"></bean>

3.2.8、注入数组,List,Map,Set类型属性

1)创建实体类

package com.dianchou.spring.dao;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @author lawrence
 * @create 2020-07-07 15:32
 */
public class Student {

    //1 数组类型属性
    private String[] courses;
    //2 list 集合类型属性
    private List<String> list;
    //3 map 集合类型属性
    private Map<String,String> maps;
    //4 set 集合类型属性
    private Set<String> sets;
    public void setSets(Set<String> sets) {
        this.sets = sets;
    }
    public void setCourses(String[] courses) {
        this.courses = courses;
    }
    public void setList(List<String> list) {
        this.list = list;
    }
    public void setMaps(Map<String, String> maps) {
        this.maps = maps;
    }

    @Override
    public String toString() {
        return "Student{" +
                "courses=" + Arrays.toString(courses) +
                ", list=" + list +
                ", maps=" + maps +
                ", sets=" + sets +
                '}';
    }
}

2)spring配置文件配置

<bean id="student" class="com.dianchou.spring.dao.Student">
    <!--数组类型属性注入-->
    <property name="courses">
        <array>
            <value>语文</value>
            <value>数学</value>
        </array>
    </property>
    <!--List集合类型注入-->
    <property name="list">
        <list>
            <value>AAA</value>
            <value>BBB</value>
        </list>
    </property>
    <!--map类型注入-->
    <property name="maps">
        <map>
            <entry key="JAVA" value="java"></entry>
            <entry key="PYTHON" value="python"></entry>
        </map>
    </property>
    <!--set类型注入-->
    <property name="sets">
        <set>
            <value>MySQL</value>
            <value>Redis</value>
        </set>
    </property>
</bean>

3)测试

@Test
public void testStudent(){
    ApplicationContext ctx = new ClassPathXmlApplicationContext("bean2.xml");
    Student student = ctx.getBean("student", Student.class);
    System.out.println(student);
}
image

相关细节

①在集合里面设置对象类型值

<!--创建多个 course 对象-->
<bean id="course1" class="com.dianchou.spring.dao.Course">
    <property name="name" value="Spring"></property>
</bean>
<bean id="course2" class="com.dianchou.spring.dao.Course">
    <property name="name" value="MyBatis"></property>
</bean>
<!--注入 list 集合类型,值是对象-->
<bean id="courseList" class="com.dianchou.spring.dao.CourseList">
    <property name="courseList">
        <list>
            <ref bean="course1"></ref>
            <ref bean="course2"></ref>
        </list>
    </property>

②把集合注入部分提取出来

image

posted @ 2020-07-07 11:15  运维人在路上  阅读(208)  评论(0编辑  收藏  举报