spring-IOC

IOC容器

简介

IoC(Inversion of Control)控制反转,是一种基于面向对象编程法则的设计思想,它设计出的程序具有松耦合、更优良的特点。
IoC容器是Spring框架中重要的核心组件之一,贯穿了Spring从出生到成长的整个过程,Spring通过IoC容器管理所有Java对象的实例化和初始化,控制对象与对象之间的实例化、初始化以及依赖关系。由IoC容器管理的Java对象称为Spring Bean,它与使用new 关键字创建的Java对象没有任何区别。

Bean管理:Bean对象的创建和Bean对象中属性的的赋值(或者叫Bean对象之间关系的维护)

控制反转,反转的是什么?

  • 将对象的创建权交出去,交给第三方容器负责。
  • 将对象和对象之间关系的维护权交出去,交给第三方容器负责。

如何实现控制反转?

DI(Dependency Injection) 依赖注入

依赖注入:指Spring创建对象的过程中,将对象依赖属性通过配置进行注入,它实现了控制反转的思想。当一个对象作为另一个对象的属性的时候,我们可以使用依赖注入的方式将对象的内容注入。

依赖注入的实现方式:①set注入、②构造注入


IoC在Spring中的实现

Spring的IoC容器中管理的组件叫做Bean, 在创建Bean之前,首先需要创建IoC容器,Spring提供的IoC容器有两种实现方式。

1、BeanFactory

这是IoC容器的基本实现,是Spring内部使用的接口

2、ApplicationContext
BeanFactory的子接口,提供了更多高级特性。面向Spring的使用者,几乎所有的场合都使用ApplicationContext而不是底层的BeanFactory

ApplicationContext的主要实现类

类名 简介
ClassPathXmlApplicationContext 通过类读取路径下的XML格式的配置文件创建IoC对象
FileSystemXmlApplicationContext 通过文件系统路径读取XML格式的配置文件创建IoC对象
ConfigurableApplicationContext ApplicationContext的子接口,包含一些扩展方法refresh()和close(),让ApplicationContext具有启动、关闭和刷新上下文功能
WebApplicationContex 专门为Web应用准备,基于Web环境创建的IoC容器对象,并将对象引入存入ServletContext域中

基于xml管理Bean

步骤

①导入相关依赖

xml 复制代码
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>6.0.9</version>
</dependency>
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13.2</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.20.0</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-slf4j2-impl</artifactId>
    <version>2.20.0</version>
</dependency>

②创建spring和log4j2的配置文件

spring.xml

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="user" class="com.louis.ioc_xml.User"></bean>
</beans>

log4j2的配置文件可从取:https://blog.csdn.net/xry12354/article/details/131647570

③创建User对象

java 复制代码
package com.louis.ioc_xml;

/**
 * @author XRY
 * @date 2023年06月22日13:58
 */
public class User {

    private String name;
    private Integer age;

    public void run(){
        System.out.println("run....");
    }
}

④获取Bean

方式一:根据id获取

由于id属性指定了bean的唯一标识,所以根据bean标签的id属性可以精确获取到一个组件对象。

写法:

xml 复制代码
<bean id="user" class="com.louis.ioc_xml.User"></bean>

id属性:唯一标识
class属性:要创建对象所在类的全路径(包名称+类名称)

java 复制代码
@Test
public void testBeanById(){
    ApplicationContext applicationContext =
            new ClassPathXmlApplicationContext("bean.xml");
    User user = (User)applicationContext.getBean("user");
    logger.info("user = " + user);
}
/*[2023-06-22 14:17:20:953] [INFO] - TestBeanById.testBeanById(TestBeanById.java:20) - user = com.louis.ioc_xml.User@77d2e85*/

方式二:根据类型获取

java 复制代码
@Test
public void testBeanByClass(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");
    User bean = applicationContext.getBean(User.class);
    logger.info("user"+bean);
}
/*[2023-06-22 14:22:24:009] [INFO] - TestBeanById.testBeanByClass(TestBeanById.java:29) - usercom.louis.ioc_xml.User@1a9c38eb*/

方式三:根据id和类型获取

java 复制代码
@Test
public void testBeanByClassAndId(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");
    User user = applicationContext.getBean("user", User.class);
    logger.info("user" + user);
}
/*[2023-06-22 14:25:27:189] [INFO] - TestBeanById.testBeanByClassAndId(TestBeanById.java:37) - usercom.louis.ioc_xml.User@77d2e85*/

获取bean的细节

根据类型获取Bean时,要求IoC容器中指定类型的bean有且只能有一个。

组件类实现了接口,如果实现类只有一个则可以通过类型获取bean,如果实现类有多个,即使这些实现类都配置了bean也不能够使用类型获取。

只有一个实现类

java 复制代码
//UserDaoImpl
package com.louis.bean;

/**
 * @author XRY
 * @date 2023年06月22日14:37
 */
public class UserDaoImpl implements UserDao{
    @Override
    public void run() {
        System.out.println("check the target");
    }
}

测试

java 复制代码
@Test
public void testInterface(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");
    UserDao userDao = applicationContext.getBean("userDao", UserDao.class);
    logger.info("userDao" + userDao);
    userDao.run();
}
/*[2023-06-22 14:43:27:092] [INFO] - TestBeanById.testInterface(TestBeanById.java:47) - userDaocom.louis.bean.UserDaoImpl@58ffcbd7
    check the target*/

User有多个实现类

java 复制代码
//PersonDaoImpl
package com.louis.bean;

/**
 * @author XRY
 * @date 2023年06月22日14:47
 */
public class PersonDaoImpl implements UserDao{
    @Override
    public void run() {
        System.out.println("person");
    }
}

测试

java 复制代码
@Test
public void testTwoInterface(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");
    UserDao personDao = (UserDao)applicationContext.getBean("personDao");
    logger.info("personDao" + personDao);
    UserDao bean = applicationContext.getBean(UserDao.class);
    logger.info("bean" + bean);
}
 /*[2023-06-22 14:55:05:632] [INFO] - TestBeanById.testTwoInterface(TestBeanById.java:57) - personDaocom.louis.bean.PersonDaoImpl@555cf22
    org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.louis.bean.UserDao' available: expected single matching bean but found 2: userDao,personDao*/
结论

根据类型来获取bean时,在满足bean唯一性的前提下,其实只是看instanceof指定的类型的返回结果,只要返回的结果是true就可以认定为和类型匹配,能够获取到。

java中instanceof运算符用来判断前面的对象是否是后面的类,或其子类、实现类的实例。如果是返回true,否则返回false。


依赖注入

创建对象过程中,给属性设置值。

原生方法实现

java 复制代码
package com.louis.di;

/**
 * @author XRY
 * @date 2023年06月23日9:46
 */
public class Book {
    private String name;
    private String author;

    public Book() {
    }

    public Book(String name, String author) {
        this.name = name;
        this.author = author;
    }

    public String getName() {
        return name;
    }

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

    public String getAuthor() {
        return author;
    }

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


    public static void main(String[] args){
        //使用原生方法实现值的设置
        //set
        Book book = new Book();
        book.setName("西游记");
        book.setAuthor("吴承恩");

        //构造器
        Book book1 = new Book("水浒传","施耐庵");
    }
}

基于setter注入

步骤

1、创建类,定义属性生成属性的set方法

java 复制代码
package com.louis.di;

/**
 * @author XRY
 * @date 2023年06月23日9:46
 */
public class Book {
    private String name;
    private String author;
    

    public String getName() {
        return name;
    }

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

    public String getAuthor() {
        return author;
    }

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

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

2、在spring的配置文件中进行配置

xml 复制代码
<!--基于set方法进行注入-->
<bean id="book" class="com.louis.di.Book">
<!--在使用property这个标签时,就会调用类中的set方法-->
    <property name="name" value="红楼梦"></property>
    <property name="author" value="曹雪芹"></property>
</bean>

3、测试

java 复制代码
@Test
public void testBook(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean-di.xml");
    Book book = applicationContext.getBean("book", Book.class);
    logger.info("set注入" + book);
}

/*[2023-06-23 10:02:10:517] [INFO] - TestBeanById.testBook(TestBeanById.java:72) - set注入Book{name='红楼梦', author='曹雪芹'}*/

基于构造器注入

步骤

1、创建类,定义属性,生成有参构造方法(可以没有无参)

java 复制代码
package com.louis.di;

/**
 * @author XRY
 * @date 2023年06月23日9:46
 */
public class Book {
    private String name;
    private String author;

    public Book() {
    }

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

2、在spring中进行配置

xml 复制代码
<!--构造器注入-->
<bean id="bookConstructor" class="com.louis.di.Book">
    <constructor-arg name="name" value="三国演义"></constructor-arg>
    <constructor-arg name="author" value="罗贯中"></constructor-arg>
<!--也可以使用index这种类型<constructor-arg index="0" value="三国"></constructor-arg>-->
</bean>

3、测试

java 复制代码
@Test
public void testConstructor(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean-di.xml");
    Book bookConstructor = applicationContext.getBean("bookConstructor", Book.class);
    logger.info("bookCon" + bookConstructor);
}
/*有参构造方法执行了
[2023-06-23 10:13:15:457] [INFO] - TestBeanById.testConstructor(TestBeanById.java:81) - bookConBook{name='三国演义', author='罗贯中'}*/

注入过程中特殊值的处理

字面量赋值

字面量

如:int a = 1;直接赋值,表示我们看到的这个数据本身。

xml 复制代码
<!-- 使用value属性给bean的属性赋值时,Spring会把value属性的值看做字面量 -->
<property name="name" value="张三"/>

null值

xml 复制代码
<bean id="book" class="com.louis.di.Book">
<!--在使用property这个标签时,就会调用类中的set方法-->
    <property name="name" value="红楼梦"></property>
    <property name="author">
        <null></null>
    </property>
</bean>

xml实体

当设置的值中有类似<>的时候,需要进行转义处理。解决方案:用xml实体来代替

xml 复制代码
 <property name="name" value="&lt;&gt;"></property>

CDATA节

它是xml中一种特殊的写法,当设置的值中有类似<>的时候,就是要写<>时可以使用。

xml 复制代码
<property name="name">
    <!--CDATA节中写什么符号都随意-->
    <value><![CDATA[ < >]]></value>
</property>

不同类型进行依赖注入

对象类型属性注入

如:部门和员工

Department
java 复制代码
public class Department {
    private String dName;
    
    public void info(){
        System.out.println("Department name");
    }
}
Employee
java 复制代码
public class Employee {
    private String eName;
    private Integer age;
    private Department dept;


    public void work(){
        System.out.println("Employee working");
    }
}
方式一:引用外部bean
1、生成它们的set方法

Department

java 复制代码
//部门类
public class Department {
    private String dname;

    public String getDname() {
        return dname;
    }

    public void setDname(String dname) {
        this.dname = dname;
    }

    public void info(){
        System.out.println("Department name");
    }
}

Employee

java 复制代码
public class Employee {
    private String eName;
    private Integer age;
    private Department dept;

    public String geteName() {
        return eName;
    }

    public void seteName(String eName) {
        this.eName = eName;
    }

    public Integer getAge() {
        return age;
    }

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

    public Department getDept() {
        return dept;
    }

    public void setDept(Department dept) {
        this.dept = dept;
    }

    public void work(){
        System.out.println("Employee working");
        //为了验证引入是否成功
        dept.info();
    }
}
2、编写配置文件
xml 复制代码
<!--引入外部bean
    1、创建两个类对象:department和employee
    2、在Employee标签里面,使用property引入两个类-->
<bean id="dept" class="com.louis.di_test.Department">
    <property name="dname" value="IT"></property>
</bean>
<bean id="emp" class="com.louis.di_test.Employee">
    <property name="eName" value="Alex"></property>
    <property name="age" value="18"></property>
<!--注入对象类型的熟属性-->
    <property name="dept" ref="dept"></property>
</bean>
3、测试
java 复制代码
@Test
public void testObj(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean-diTest.xml");
    Employee emp = applicationContext.getBean("emp", Employee.class);
    emp.work();
    logger.info("emp" + emp);
}
/*Employee working
Department name
[2023-06-23 11:45:56:941] [INFO] - TestBeanById.testObj(TestBeanById.java:92) - empEmployee{eName='Alex', age=18, dept=Department{dname='IT'}}
*/
方式二:内部bean
1、生成set方法
2、编写配置文件
xml 复制代码
<!--内部bean注入-->
<bean id="emp2" class="com.louis.di_test.Employee">
    <property name="eName" value="Louie"></property>
    <property name="age" value="20"></property>
    <!--内部bean-->
    <property name="dept">
        <bean id="dept2" class="com.louis.di_test.Department">
            <property name="dname" value="设计"></property>
         </bean>
    </property>
</bean>
3、测试
java 复制代码
@Test
public void testObj2(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean-diTest.xml");
    Employee emp2 = applicationContext.getBean("emp2", Employee.class);
    emp2.work();
    logger.info("emp2" + emp2);
}
/*
Employee working
Department name
[2023-06-23 11:54:58:543] [INFO] - TestBeanById.testObj2(TestBeanById.java:104) - emp2Employee{eName='Louie', age=20, dept=Department{dname='设计'}}
*/
方式三:级联属性赋值
1、创建实体对象,生成set方法
2、编写配置文件
xml 复制代码
<!--级联赋值-->
<bean id="dept3" class="com.louis.di_test.Department">
    <property name="dname" value="超人组"></property>
</bean>
<bean id="emp3" class="com.louis.di_test.Employee">
    <property name="eName" value="khan"></property>
    <property name="age" value="23"></property>
    <property name="dept" ref="dept3"></property>
    <property name="dept.dname" value="研发科"></property>
</bean>
3、测试
java 复制代码
@Test
public void testObj3(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean-diTest.xml");
    Employee emp3 = applicationContext.getBean("emp3", Employee.class);
    emp3.work();
    logger.info("emp3" + emp3);
}

/*Employee working
Department name
[2023-06-23 12:02:44:654] [INFO] - TestBeanById.testObj3(TestBeanById.java:118) - emp3Employee{eName='khan', age=23, dept=Department{dname='研发科'}}*/

为数组类型属性赋值

1、编写实体类
java 复制代码
public class Person {
    private String[] hobby;

    public String[] getHobby() {
        return hobby;
    }

    public void setHobby(String[] hobby) {
        this.hobby = hobby;
    }

    @Override
    public String toString() {
        return "Person{" +
                "hobby=" + Arrays.toString(hobby) +
                '}';
    }
}
2、编写配置文件
xml 复制代码
 <!--注入数组类型的属性-->
<bean id="person" class="com.louis.di_array.Person">
    <!--注入数组类型属性值-->
    <property name="hobby">
        <array>
            <value>eat</value>
            <value>sleep</value>
            <value>code</value>
        </array>
    </property>
</bean>
3、测试
java 复制代码
@Test
public void testArray(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean-diarray.xml");
    Person person = applicationContext.getBean("person", Person.class);
    logger.info("person" + person);
}

/*[2023-06-23 12:14:00:835] [INFO] - TestBeanById.testArray(TestBeanById.java:129) - personPerson{hobby=[eat, sleep, code]}*/

为集合类型属性赋值

(一)为list集合类型属性赋值
1、编写实体类并生成set方法

Department

java 复制代码
public class Department {
    private String dname;
    private List<Employee> empList;

    public List<Employee> getEmpList() {
        return empList;
    }

    public void setEmpList(List<Employee> empList) {
        this.empList = empList;
    }

    public String getDname() {
        return dname;
    }

    public void setDname(String dname) {
        this.dname = dname;
    }

    public void info(){
        System.out.println("Department name");
    }

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

Employee

java 复制代码
public class Employee {
    private String eName;
    private Integer age;
    private Department dept;

    public String geteName() {
        return eName;
    }

    public void seteName(String eName) {
        this.eName = eName;
    }

    public Integer getAge() {
        return age;
    }

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

    public Department getDept() {
        return dept;
    }

    public void setDept(Department dept) {
        this.dept = dept;
    }

    public void work(){
        System.out.println("Employee working");
        dept.info();
    }

    @Override
    public String toString() {
        return "Employee{" +
                "eName='" + eName + '\'' +
                ", age=" + age +
                ", dept=" + dept +
                '}';
    }
}
2、编写配置文件
xml 复制代码
<!--实现list集合注入-->
<bean id="emp" class="com.louis.di_test.Employee">
    <property name="eName" value="Louis"></property>
    <property name="age" value="23"></property>
</bean>
<bean id="empTwo" class="com.louis.di_test.Employee">
    <property name="eName" value="Alex"></property>
    <property name="age" value="22"></property>
</bean>
<bean id="dept" class="com.louis.di_test.Department">
    <property name="dname" value="研发科"></property>
    <property name="empList">
        <list>
<!--如果是字符串和基本数据类型,可以直接使用<value>标签-->
            <ref bean="emp"></ref>
            <ref bean="empTwo"></ref>
        </list>
    </property>
</bean>
3、测试
java 复制代码
@Test
public void testList(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean-dilist.xml");
    Department dept = applicationContext.getBean("dept", Department.class);
    dept.info();
    logger.info("dept" + dept);
}

/*Department name
employee.geteName() = Louis
employee.geteName() = Alex
[2023-06-23 12:31:05:121] [INFO] - TestBeanById.testList(TestBeanById.java:139) - deptDepartment{dname='研发科', empList=[Employee{eName='Louis', age=23, dept=null}, Employee{eName='Alex', age=22, dept=null}]}
*/
(二)为Map集合属性注入值
1、编写实体类并生成set方法

Student

java 复制代码
public class Student {
    private String sname;
    private String sid;
    //一个学生可能对应多个老师
    private Map<String, Teacher> teacherMap;

    public Map<String, Teacher> getTeacherMap() {
        return teacherMap;
    }

    public void setTeacherMap(Map<String, Teacher> teacherMap) {
        this.teacherMap = teacherMap;
    }

    public String getSname() {
        return sname;
    }

    public void setSname(String sname) {
        this.sname = sname;
    }

    public String getSid() {
        return sid;
    }

    public void setSid(String sid) {
        this.sid = sid;
    }
    
    public void learn(){
        System.out.println("学生姓名" + sname + "----" + "学号" + sid);
        System.out.println(teacherMap);
    }

    @Override
    public String toString() {
        return "Student{" +
                "sname='" + sname + '\'' +
                ", sid='" + sid + '\'' +
                ", teacherMap=" + teacherMap +
                '}';
    }
}

Teacher

java 复制代码
public class Teacher {
    private String tname;
    private String tid;

    public String getTname() {
        return tname;
    }

    public void setTname(String tname) {
        this.tname = tname;
    }

    public String getTid() {
        return tid;
    }

    public void setTid(String tid) {
        this.tid = tid;
    }

    @Override
    public String toString() {
        return "Teacher{" +
                "tname='" + tname + '\'' +
                ", tid='" + tid + '\'' +
                '}';
    }
}
2、编写配置文件
xml 复制代码
    <!--
    1、创建两个对象
    2、注入普通类型属性
    3、在学生bean注入map集合类型属性
    -->
<bean id="teacher" class="com.louis.di_map.Teacher">
    <property name="tid" value="110"></property>
    <property name="tname" value="Alex"></property>
</bean>
<bean id="teacher2" class="com.louis.di_map.Teacher">
    <property name="tid" value="120"></property>
    <property name="tname" value="Khan"></property>
</bean>
<bean id="student" class="com.louis.di_map.Student">
    <property name="sid" value="18162004"></property>
    <property name="sname" value="Louie"></property>
    <property name="teacherMap">
        <map>
            <entry>
                <key>
                    <value>key1</value>
                </key>
                <ref bean="teacher"></ref>
            </entry>
            <entry>
                <key>
                    <value>key2</value>
                </key>
                <ref bean="teacher2"></ref>
            </entry>
        </map>
    </property>
</bean>
3、测试
java 复制代码
@Test
public void testMap(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean-diMap.xml");
    Student student = applicationContext.getBean("student", Student.class);
    logger.info("student" + student);
    student.learn();
}

/*[2023-06-23 12:57:29:327] [INFO] - TestBeanById.testMap(TestBeanById.java:152) - studentStudent{sname='Louie', sid='18162004', teacherMap={key1=Teacher{tname='Alex', tid='110'}, key2=Teacher{tname='Khan', tid='120'}}}
学生姓名Louie----学号18162004
{key1=Teacher{tname='Alex', tid='110'}, key2=Teacher{tname='Khan', tid='120'}}*/
引用集合类型的bean

将list和map的实现方式换一种写法。

1、在原有的Student和Teacher的基础上,再添加一个Lesson类
java 复制代码
public class Lesson {
    private String lessonName;

    public String getLessonName() {
        return lessonName;
    }

    public void setLessonName(String lessonName) {
        this.lessonName = lessonName;
    }

    @Override
    public String toString() {
        return "Lesson{" +
                "lessonName='" + lessonName + '\'' +
                '}';
    }
}
2、再Student类中添加课程列表
java 复制代码
List<Lesson> list;

public List<Lesson> getList() {
    return list;
}

public void setList(List<Lesson> list) {
    this.list = list;
}
3、编写配置文件

加上util的命名空间引入

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"
       xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="
       http://www.springframework.org/schema/util
       http://www.springframework.org/schema/util/spring-util.xsd
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--
    1、创建三个对象
    2、注入普通类型属性
    3、使用util:类型 定义。需要更改命名空间引入
    4、在学生bean引入util:类型定义bean,完成list、map类型注入
    -->
    <bean id="lessonOne" class="com.louis.di_map.Lesson">
        <property name="lessonName" value="JAVA开发"></property>
    </bean>
    <bean id="lessonTwo" class="com.louis.di_map.Lesson">
        <property name="lessonName" value="Python 开发"></property>
    </bean>
    <bean id="teacherOne" class="com.louis.di_map.Teacher">
        <property name="tname" value="Louie"></property>
        <property name="tid" value="11011"></property>
    </bean>
    <bean id="teacherTwo" class="com.louis.di_map.Teacher">
        <property name="tname" value="Alex"></property>
        <property name="tid" value="12012"></property>
    </bean>
    <bean id="student" class="com.louis.di_map.Student">
        <property name="sname" value="khan"></property>
        <property name="sid" value="201811011"></property>
        <!--注入list、map类型的属性-->
        <property name="list" ref="lessonList"></property>
        <property name="teacherMap" ref="teacherMap"></property>
    </bean>
    <util:list id="lessonList">
        <ref bean="lessonOne"></ref>
        <ref bean="lessonTwo"></ref>
    </util:list>
    <util:map id="teacherMap">
        <entry>
            <key>
                <value>111</value>
            </key>
            <ref bean="teacherOne"></ref>
        </entry>
        <entry>
            <key>
                <value>222</value>
            </key>
            <ref bean="teacherTwo"></ref>
        </entry>
    </util:map>
</beans>
4、测试
java 复制代码
@Test
public void testUtil(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean-diRef.xml");
    Student student = applicationContext.getBean("student", Student.class);
    student.learn();
    logger.info("student" + student);
}

/*学生姓名khan----学号201811011
{111=Teacher{tname='Louie', tid='11011'}, 222=Teacher{tname='Alex', tid='12012'}}
[2023-06-23 14:28:04:062] [INFO] - TestBeanById.testUtil(TestBeanById.java:164) - studentStudent{sname='khan', sid='201811011', teacherMap={111=Teacher{tname='Louie', tid='11011'}, 222=Teacher{tname='Alex', tid='12012'}}, list=[Lesson{lessonName='JAVA开发'}, Lesson{lessonName='Python 开发'}]}
*/
p命名空间

命名空间:为避免命名时冲突,再命名后面加上:重命名的方式

xml 复制代码
xmlns:p = "http://www.springframework.org/schema/p"
编写配置文件
xml 复制代码
<!--p命名空间注入-->
<bean id="studentP" class="com.louis.di_map.Student" p:sid="201811" p:sname="Louis" p:list-ref="lessonList" p:teacherMap-ref="teacherMap">
</bean>
<util:list id="lessonList">
    <ref bean="lessonOne"></ref>
    <ref bean="lessonTwo"></ref>
</util:list>
<util:map id="teacherMap">
    <entry>
        <key>
            <value>111</value>
        </key>
        <ref bean="teacherOne"></ref>
    </entry>
    <entry>
        <key>
            <value>222</value>
        </key>
        <ref bean="teacherTwo"></ref>
    </entry>
</util:map>
测试
java 复制代码
@Test
public void testP(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean-diRef.xml");
    Student studentP = applicationContext.getBean("studentP", Student.class);
    studentP.learn();
    logger.info("studentP" + studentP);
}

/*学生姓名Louis----学号201811
{111=Teacher{tname='Louie', tid='11011'}, 222=Teacher{tname='Alex', tid='12012'}}
[2023-06-23 14:43:14:562] [INFO] - TestBeanById.testP(TestBeanById.java:176) - studentPStudent{sname='Louis', sid='201811', teacherMap={111=Teacher{tname='Louie', tid='11011'}, 222=Teacher{tname='Alex', tid='12012'}}, list=[Lesson{lessonName='JAVA开发'}, Lesson{lessonName='Python 开发'}]}
*/

引入外部属性文件

应用场景:在一个文件中如果出现多个bean的创建和注入,维护就会比较困难。可以将一些特定的文件放在特定位置在spring中进行引入,如数据库文件。

实现步骤(数据库的配置文件引入)

1、引入相关依赖
xml 复制代码
 <dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.2.16</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.33</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-dbutils/commons-dbutils -->
<dependency>
    <groupId>commons-dbutils</groupId>
    <artifactId>commons-dbutils</artifactId>
    <version>1.7</version>
</dependency>
2、创建Dbutils.properties
properties 复制代码
username=root
password=root
url=jdbc:mysql://localhost:3306/spring
driver=com.mysql.cj.jdbc.Driver
3、创建spring的配置文件

引入context命名空间,引入属性文件,使用表达式完成注入。

context命名空间

xml 复制代码
xmlns:contex="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd"

引入属性文件

xml 复制代码
<!--引入外部属性文件-->
<contex:property-placeholder location="classpath:Dbutils.properties"></contex:property-placeholder>

完整配置

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"
       xmlns:contex="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

<!--引入外部属性文件-->
    <contex:property-placeholder location="classpath:Dbutils.properties"></contex:property-placeholder>
<!--完成数据库信息注入-->
    <bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="url" value="${url}"></property>
        <property name="username" value="${username}"></property>
        <property name="password" value="${password}"></property>
        <property name="driver" value="${driver}"></property>
    </bean>
</beans>
4、测试
java 复制代码
@Test
public void testDbutils(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean-Dbutils.xml");
    DruidDataSource dataSource = applicationContext.getBean("druidDataSource", DruidDataSource.class);
    logger.info("dataSource" + dataSource);
}
/*
* [2023-06-23 15:36:52:008] [INFO] - TestBeanById.testDbutils(TestBeanById.java:189) - dataSource{
    CreateTime:"2023-06-23 15:36:51",
    ActiveCount:0,
    PoolingCount:0,
    CreateCount:0,
    DestroyCount:0,
    CloseCount:0,
    ConnectCount:0,
    Connections:[
    ]
}
* */
相关推荐
代码之光_198016 分钟前
保障性住房管理:SpringBoot技术优势分析
java·spring boot·后端
ajsbxi21 分钟前
苍穹外卖学习记录
java·笔记·后端·学习·nginx·spring·servlet
StayInLove40 分钟前
G1垃圾回收器日志详解
java·开发语言
对许44 分钟前
SLF4J: Failed to load class “org.slf4j.impl.StaticLoggerBinder“
java·log4j
鹿屿二向箔1 小时前
基于SSM(Spring + Spring MVC + MyBatis)框架的咖啡馆管理系统
spring·mvc·mybatis
无尽的大道1 小时前
Java字符串深度解析:String的实现、常量池与性能优化
java·开发语言·性能优化
小鑫记得努力1 小时前
Java类和对象(下篇)
java
binishuaio1 小时前
Java 第11天 (git版本控制器基础用法)
java·开发语言·git
zz.YE1 小时前
【Java SE】StringBuffer
java·开发语言
老友@1 小时前
aspose如何获取PPT放映页“切换”的“持续时间”值
java·powerpoint·aspose