0%

Spring对IoC的实现

  • Spring对IoC的实现
    • IoC控制反转
    • DI依赖注入
    • set注入专题
    • p命名空间注入
    • c命名空间注入
    • util命名空间注入
    • 基于XML的自动装配
    • spring引入外部属性配置文件

四、★★★Spring对IoC的实现

4.1 IoC控制反转

  • 控制反转是一种思想。
  • 控制反转是为了降低程序耦合度,提高程序扩展力,达到 OCP 原则,达到 DIP 原则。
  • 控制反转,反转的是什么?
    • 将对象的创建权利交出去,交给第三方容器负责。
    • 将对象和对象之间关系的维护权交出去,交给第三方容器负责。
  • 控制反转思想的实现:DIDependency Injection,依赖注入)。

4.2 DI依赖注入

  • 依赖注入实现了控制反转的思想。
  • Spring 通过依赖注入的方式来完成 Bean管理。
    • Bean管理:Bean对象的创建,以及 Bean 对象中属性的赋值(或者叫做 Bean 对象之间关系的维护)
  • 依赖注入:
    • 依赖指的是对象和对象之间的关联关系。
    • 注入指的是一种数据传递行为,通过注入行为来让对象和对象产生关系。
    • 依赖注入常见的实现方式包括两种:
      • 第一种:set注入
      • 第二种:构造注入

4.2.1 set注入

  • set注入,基于 set 方法实现的,底层会通过反射机制调用属性相对应的 set 方法来给属性赋值。

    • 这种方式要求属性必须对外提供 set 方法。
  • set注入的使用:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    package com.f.spring6.dao;


    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;

    /**
    * @author fzy
    * @date 2024/1/17 14:36
    */
    public class UserDao {
    private static final Logger logger = LoggerFactory.getLogger(UserDao.class);

    public void insert() {
    logger.info("数据库正在保存用户信息...");
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    package com.f.spring6.service;

    import com.f.spring6.dao.UserDao;

    /**
    * @author fzy
    * @date 2024/1/17 14:39
    */
    public class UserService {
    private UserDao userDao;

    // set注入的话,必须提供一个set方法
    // spring容器会调用这个set方法,来给userDao属性赋值
    // 下面这个set方法是IDEA工具生成的,符合javabean规范
    /*public void setUserDao(UserDao userDao) {
    this.userDao = userDao;
    }*/
    // 我自己写一个set方法,不使用IDEA工具生成的,不符合javabean的规范,可以吗?
    // 也可以,但没必要。这里是演示如果这么写了,相应地在spring配置文件中该怎么写。
    public void setXyz(UserDao xyz) {
    this.userDao = xyz;
    }

    public void saveUser() {
    userDao.insert();
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    <?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">
    <!--配置dao-->
    <bean id="userDaoBean" class="com.f.spring6.dao.UserDao"/>
    <!--配置service-->
    <bean id="userServiceBean" class="com.f.spring6.service.UserService">
    <!--想让spring调用对应的set方法,需要配置property标签-->
    <!--name属性怎么指定值:相应的set方法的方法名,去掉set,然后把剩下的单词的首字母变小写-->
    <!--ref翻译为引用,ref后面指定的是要注入的bean的id-->
    <property name="xyz" ref="userDaoBean"/>
    <!--如果用IDEA工具生成的set方法,那么直接将属性名写在name的位置即可-->
    <!--<property name="userDao" ref="userDaoBean"/>-->
    </bean>
    </beans>
    1
    2
    3
    4
    5
    6
    @Test
    public void testSetDI() {
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
    UserService userServiceBean = applicationContext.getBean("userServiceBean", UserService.class);
    userServiceBean.saveUser();
    }
  • 总结:为了让对象和对象之间能产生依赖关系,如果使用 set 注入的话,需要满足以下条件:

    1. 在类中需要提供 set 方法。
    2. 在 spring 配置文件中需要配置 property 标签,property 标签中:
      • name 属性指定相应的 set 方法,值为相应的 set 方法的方法名,去掉 set,然后把剩下的单词的首字母变小写。
      • ref 属性指定要注入的 beanid,也就是 set 方法要传参的对象。

4.2.2 构造注入

  • 通过调用构造方法来给属性赋值。

  • set 注入相比,构造注入是在创建对象的同时进行注入,进行属性的赋值,而 set 注入是在对象创建之后。

  • 构造注入的使用:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    package com.f.spring6.service;

    import com.f.spring6.dao.UserDao;

    /**
    * @author fzy
    * @date 2024/1/17 15:16
    */
    public class UserService2 {
    private UserDao userDao;

    public UserService2(UserDao userDao) {
    this.userDao = userDao;
    }

    public void saveUser() {
    userDao.insert();
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    <?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="userDaoBean" class="com.f.spring6.dao.UserDao"/>
    <bean id="userService2Bean" class="com.f.spring6.service.UserService2">
    <!--
    构造注入
    index属性指定参数下标,第一个参数是0,第二个参数是1...
    ref属性指定注入的bean的id
    -->
    <!--指定构造方法的第一个参数,下标是0-->
    <!--<constructor-arg index="0" ref="userDaoBean"/>-->
    <!--指定构造方法的第二个参数,下标是1-->
    <!--<constructor-arg index="1" ref=""/>-->
    <!--也可以用name属性来指定参数-->
    <constructor-arg name="userDao" ref="userDaoBean"/>
    </bean>
    </beans>
    1
    2
    3
    4
    5
    6
    @Test
    public void testConstructorDI() {
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring2.xml");
    UserService2 userService2Bean = applicationContext.getBean("userService2Bean", UserService2.class);
    userService2Bean.saveUser();
    }
    • 通过构造方法进行注入有三种形式:
      • 可以通过下标 index
      • 可以通过名称 name
      • 也可以不指定下标和参数名,让 spring 进行类型推断。

4.3 ★set注入专题

4.3.1 注入外部Bean(常用)

  • 外部 Bean:要进行注入的 Bean 定义在需要被注入的 Bean 的外面。

  • 对于外部 Bean,在 property 标签中使用 ref 属性进行注入,或者使用 ref 标签进行注入,其中通过 ref 属性进行注入更常用,就如 4.2.1 小节所用的那样。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <?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-->
    <bean id="userDaoBean" class="com.f.spring6.dao.UserDao"/>
    <bean id="userServiceBean" class="com.f.spring6.service.UserService">
    <!--使用ref属性来引入外部Bean,这就是注入外部Bean-->
    <property name="xyz" ref="userDaoBean"/>
    </bean>
    </beans>

4.3.2 注入内部Bean(少用)

  • 内部 Bean:在 Bean 标签中嵌套 Bean 标签,即需要进行注入的 Bean 通过 Bean 标签声明在需要被注入的 Bean 中,然后直接注入到需要被注入的 Bean 中。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    package com.f.spring6.dao;

    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;

    /**
    * @author fzy
    * @date 2024/1/17 15:37
    */
    public class OrderDao {
    private static final Logger logger = LoggerFactory.getLogger(OrderDao.class);

    public void generate() {
    logger.info("正在生成订单...");
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    package com.f.spring6.service;

    import com.f.spring6.dao.OrderDao;

    /**
    * @author fzy
    * @date 2024/1/17 16:05
    */
    public class OrderService {
    private OrderDao orderDao;

    // 通过set方法给属性赋值
    public void setOrderDao(OrderDao orderDao) {
    this.orderDao = orderDao;
    }

    public void generate() {
    this.orderDao.generate();
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <?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="orderServiceBean" class="com.f.spring6.service.OrderService">
    <property name="orderDao">
    <!--在property标签中使用嵌套的bean标签,这就是内部Bean-->
    <bean class="com.f.spring6.dao.OrderDao"/>
    </property>
    </bean>
    </beans>
    1
    2
    3
    4
    5
    6
    7
    @Test
    public void testSetDI2() {
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("set-di.xml");
    OrderService orderServiceBean = applicationContext.getBean("orderServiceBean", OrderService.class);
    System.out.println(orderServiceBean);
    orderServiceBean.generate();
    }

4.3.3 注入简单类型

  • 如果给简单类型赋值,即**给属性注入简单类型,使用 value 属性或 value 标签,而不是 ref**。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    package com.f.spring6.bean;

    /**
    * @author fzy
    * @date 2024/1/17 16:18
    */
    public class User {
    private String username;
    private String password;
    private int age;

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

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

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

    @Override
    public String toString() {
    return "User{" +
    "username='" + username + '\'' +
    ", password='" + password + '\'' +
    ", age=" + age +
    '}';
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <?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="userBean" class="com.f.spring6.bean.User">
    <!--如果是给简单类型赋值,就不能使用ref了,而是使用value-->
    <property name="username" value="root"/>
    <property name="password" value="root"/>
    <property name="age" value="100"/>
    </bean>
    </beans>
    1
    2
    3
    4
    5
    6
    @Test
    public void testSetDI3() {
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("set-di.xml");
    User userBean = applicationContext.getBean("userBean", User.class);
    System.out.println(userBean);
    }
String中的简单类型
  • 通过分析 org.springframework.beans.BeanUtils 的源码得知,简单类型包括:

    • 基本数据类型
    • 基本数据类型对应的包装类
    • String 或其他的 CharSequence 子类
    • Number 子类
    • Date 子类,java.util.Date 是简单类型
    • Enum 子类
    • URI
    • URL
    • Temporal 子类,Temporal 是 Java8 提供的时间和时区类型
    • Locale,Locale 是语言类,也是简单类型
    • Class
    • 另外还包括以上简单值类型对应的数组类型
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    public class BeanUtils{

    //.......

    /**
    * Check if the given type represents a "simple" property: a simple value
    * type or an array of simple value types.
    * <p>See {@link #isSimpleValueType(Class)} for the definition of <em>simple
    * value type</em>.
    * <p>Used to determine properties to check for a "simple" dependency-check.
    * @param type the type to check
    * @return whether the given type represents a "simple" property
    * @see org.springframework.beans.factory.support.RootBeanDefinition#DEPENDENCY_CHECK_SIMPLE
    * @see org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#checkDependencies
    * @see #isSimpleValueType(Class)
    */
    public static boolean isSimpleProperty(Class<?> type) {
    Assert.notNull(type, "'type' must not be null");
    return isSimpleValueType(type) || (type.isArray() && isSimpleValueType(type.getComponentType()));
    }

    /**
    * Check if the given type represents a "simple" value type: a primitive or
    * primitive wrapper, an enum, a String or other CharSequence, a Number, a
    * Date, a Temporal, a URI, a URL, a Locale, or a Class.
    * <p>{@code Void} and {@code void} are not considered simple value types.
    * @param type the type to check
    * @return whether the given type represents a "simple" value type
    * @see #isSimpleProperty(Class)
    */
    public static boolean isSimpleValueType(Class<?> type) {
    return (Void.class != type && void.class != type &&
    (ClassUtils.isPrimitiveOrWrapper(type) ||
    Enum.class.isAssignableFrom(type) ||
    CharSequence.class.isAssignableFrom(type) ||
    Number.class.isAssignableFrom(type) ||
    Date.class.isAssignableFrom(type) ||
    Temporal.class.isAssignableFrom(type) ||
    URI.class == type ||
    URL.class == type ||
    Locale.class == type ||
    Class.class == type));
    }

    //........
    }
    • 需要注意的是:
      • 如果把 Date 当做简单类型的话,日期字符串格式就不能随便写,格式必须符合 DatetoString() 方法格式。显然这就比较鸡肋了,如果我们提供一个这样的日期字符串:2010-10-11,那么是无法赋值给 Date 类型的属性的。所以一般就不会用简单类型来给 Dateset 注入,而是用 refDate 类型的属性赋值。
      • Spring6 之后,当注入的是 URL,那么这个 url 字符串是会进行有效性检测的。如果是一个存在的 url,那就没问题。如果不存在则报错。
注入简单类型的经典案例
  • 给数据源的属性注入值:

    • 假设我们现在要自己手写一个数据源,我们都知道所有的数据源都要实现 javax.sql.DataSource 接口,并且数据源中应该有连接数据库的信息,例如:driverurlusernamepassword 等。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      package com.f.spring6.jdbc;

      import javax.sql.DataSource;
      import java.io.PrintWriter;
      import java.sql.Connection;
      import java.sql.SQLException;
      import java.sql.SQLFeatureNotSupportedException;
      import java.util.logging.Logger;

      /**
      * 所有的数据源都要实现java规范:javax.sql.DataSource
      * 什么是数据源:能够给你提供Connection对象的,都是数据源
      *
      * @author fzy
      * @date 2024/1/17 19:26
      */
      public class MyDataSource implements DataSource { // 把数据源交给spring容器来管理
      private String driver;
      private String url;
      private String username;
      private String password;

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

      public void setDriver(String driver) {
      this.driver = driver;
      }

      public void setUrl(String url) {
      this.url = url;
      }

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

      public void setPassword(String password) {
      this.password = password;
      }
      ......
      }
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      <?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">
      <!--让spring来管理我们的数据源-->
      <bean id="myDataSourceBean" class="com.f.spring6.jdbc.MyDataSource">
      <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
      <property name="url" value="jdbc:mysql://localhost:3306/spring6"/>
      <property name="username" value="root"/>
      <property name="password" value="root"/>
      </bean>
      </beans>
      1
      2
      3
      4
      5
      6
      @Test
      public void testMyDataSourceDI() {
      ApplicationContext applicationContext = new ClassPathXmlApplicationContext("set-di.xml");
      MyDataSource myDataSourceBean = applicationContext.getBean("myDataSourceBean", MyDataSource.class);
      System.out.println(myDataSourceBean);
      }

4.3.4 注入数组

数组元素是简单类型
数组元素是非简单类型
  • 注入数组的时候使用 array 标签,如果数组中是简单类型使用 value 标签,反之使用 ref 标签。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.f.spring6.bean;

/**
* @author fzy
* @date 2024/1/17 20:02
*/
public class Pet {
private String name;

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

@Override
public String toString() {
return "Pet{" +
"name='" + name + '\'' +
'}';
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package com.f.spring6.bean;

import java.util.Arrays;

/**
* @author fzy
* @date 2024/1/17 19:55
*/
public class Person {
private String[] hobbies;
private Pet[] pets;

public void setHobbies(String[] hobbies) {
this.hobbies = hobbies;
}

public void setPets(Pet[] pets) {
this.pets = pets;
}

@Override
public String toString() {
return "Person{" +
"hobbies=" + Arrays.toString(hobbies) +
", pets=" + Arrays.toString(pets) +
'}';
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?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="personBean" class="com.f.spring6.bean.Person">
<!--注入数组,这个数组当中的元素类型是简单类型-->
<property name="hobbies">
<array>
<value>sing</value>
<value>dance</value>
<value>rap</value>
<value>basketball</value>
</array>
</property>
<!--注入数组,这个数组当中的元素类型是非简单类型-->
<property name="pets">
<array>
<ref bean="pet1"/>
<ref bean="pet2"/>
<ref bean="pet3"/>
</array>
</property>
</bean>

<bean id="pet1" class="com.f.spring6.bean.Pet">
<property name="name" value="小狗"/>
</bean>
<bean id="pet2" class="com.f.spring6.bean.Pet">
<property name="name" value="小猫"/>
</bean>
<bean id="pet3" class="com.f.spring6.bean.Pet">
<property name="name" value="小鸟"/>
</bean>
</beans>
1
2
3
4
5
6
@Test
public void testArrayDI() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("set-di.xml");
Person personBean = applicationContext.getBean("personBean", Person.class);
System.out.println(personBean);
}
  • 如果数组是简单类型,使用 <value>xxx</value> 标签。
  • 如果数组是非简单类型,使用 <ref bean="bean-id"/> 标签。

4.3.5 注入List、Set集合

  • List集合:有序可重复。
    • 注意:注入 List 集合的时候使用 list 标签,如果 List 集合中是简单类型使用 value 标签,反之使用 ref 标签。
  • Set集合:无序不可重复。
    • 注意:注入 set 集合的时候使用 set 标签,如果 set 集合中元素是简单类型使用 value 标签,反之使用 ref 标签。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.f.spring6.bean;

/**
* @author fzy
* @date 2024/1/17 20:15
*/
public class Address {
private String location;

public void setLocation(String location) {
this.location = location;
}

@Override
public String toString() {
return "Address{" +
"location='" + location + '\'' +
'}';
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.f.spring6.bean;

import java.util.List;
import java.util.Set;

/**
* @author fzy
* @date 2024/1/17 20:14
*/
public class People {
private List<String> names;
private Set<Address> addrs;

public void setNames(List<String> names) {
this.names = names;
}

public void setAddrs(Set<Address> addrs) {
this.addrs = addrs;
}

@Override
public String toString() {
return "People{" +
"names=" + names +
", addrs=" + addrs +
'}';
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<?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="peopleBean" class="com.f.spring6.bean.People">
<!--注入List集合-->
<property name="names">
<!--list集合有序可重复-->
<list>
<value>张三</value>
<value>张三</value>
<value>张三</value>
<value>李四</value>
<value>王五</value>
</list>
</property>
<!--注入Set集合-->
<property name="addrs">
<!--set集合无序不可重复-->
<set>
<ref bean="addr1"/>
<ref bean="addr2"/>
<ref bean="addr3"/>
</set>
</property>
</bean>
<bean id="addr1" class="com.f.spring6.bean.Address">
<property name="location" value="Shanghai"/>
</bean>
<bean id="addr2" class="com.f.spring6.bean.Address">
<property name="location" value="Beijing"/>
</bean>
<bean id="addr3" class="com.f.spring6.bean.Address">
<property name="location" value="Wuhan"/>
</bean>
</beans>
1
2
3
4
5
6
@Test
public void testListAndSetDI() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("collection.xml");
People peopleBean = applicationContext.getBean("peopleBean", People.class);
System.out.println(peopleBean);
}

4.3.6 注入Map集合

  • Map 集合:

    • 使用 map 标签嵌套 entry 标签
    • 如果 key 是简单类型,就使用 key 属性,反之使用 key-ref 属性。
    • 如果 value 是简单类型,就使用 value 属性,反之使用 value-ref 属性。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    package com.f.spring6.bean;

    import java.util.Map;

    /**
    * @author fzy
    * @date 2024/1/17 20:26
    */
    public class School {
    private Map<Clazz, Student> school;

    public void setSchool(Map<Clazz, Student> school) {
    this.school = school;
    }

    @Override
    public String toString() {
    return "School{" +
    "school=" + school +
    '}';
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    <?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="schoolBean" class="com.f.spring6.bean.School">
    <!--注入Map集合-->
    <property name="school">
    <map>
    <!--
    如果key和value是简单类型,就用这种配置:
    <entry key="" value=""/>
    -->
    <!--如果key和value是非简单类型,就用下面这种配置-->
    <entry key-ref="clazzBean" value-ref="studentBean"/>
    </map>
    </property>
    </bean>
    <bean id="clazzBean" class="com.f.spring6.bean.Clazz">
    <property name="name" value="高三一班"/>
    </bean>
    <bean id="studentBean" class="com.f.spring6.bean.Student">
    <property name="name" value="张三"/>
    <property name="clazz" ref="clazzBean"/>
    </bean>
    </beans>
    1
    2
    3
    4
    5
    6
    @Test
    public void testMapDI() {
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("collection.xml");
    School schoolBean = applicationContext.getBean("schoolBean", School.class);
    System.out.println(schoolBean);
    }

4.3.7 注入Properties

  • java.util.Properties 继承 java.util.Hashtable,所以 Properties 也是一个 Map 集合。

    • Properties 使用 props 标签嵌套 prop 标签完成。
    • Properties 中,keyvalue 的类型都是 String 类型
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    package com.f.spring6.bean;

    import java.util.Properties;

    /**
    * @author fzy
    * @date 2024/1/17 20:38
    */
    public class DataSourceProperties {
    // Properties本质上也是一个Map集合
    // Properties的父类Hashtable,Hashtable实现了Map接口
    // 虽然这个也是一个Map集合,但是和Map的注入方式不同
    // Properties的key和value只能是String类型
    private Properties properties;

    public void setProperties(Properties properties) {
    this.properties = properties;
    }

    @Override
    public String toString() {
    return "DataSourceProperties{" +
    "properties=" + properties +
    '}';
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    <?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="dataSourcePropertiesBean" class="com.f.spring6.bean.DataSourceProperties">
    <!--注入properties属性-->
    <property name="properties">
    <props>
    <prop key="driver">com.mysql.cj.jdbc.Driver</prop>
    <prop key="url">jdbc:mysql://localhost:8080/javaweb</prop>
    <prop key="username">root</prop>
    <prop key="password">root</prop>
    </props>
    </property>
    </bean>
    </beans>
    1
    2
    3
    4
    5
    6
    @Test
    public void testPropertiesDI() {
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("collection.xml");
    DataSourceProperties dataSourcePropertiesBean = applicationContext.getBean("dataSourcePropertiesBean", DataSourceProperties.class);
    System.out.println(dataSourcePropertiesBean);
    }

4.3.8 注入null和空字符串

  • 注入 null<null/> 或者不为该属性赋值。
  • 注入空字符串:<value/> 或者 value=""
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package com.f.spring6.bean;

/**
* @author fzy
* @date 2024/1/17 21:40
*/
public class Cat {
private String name;
private int age;

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

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

@Override
public String toString() {
return "Cat{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?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="catBean" class="com.f.spring6.bean.Cat">
<!--不给属性注入,属性的默认值就是null-->
<!--<property name="name" value="tom"/>-->
<!--手动给属性注入null-->
<!--<property name="name">-->
<!-- <null/>-->
<!--</property>-->
<!--给属性注入空字符串-->
<property name="name" value=""/>
<property name="age" value="1"/>
</bean>
</beans>
1
2
3
4
5
6
@Test
public void testNullDI() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("set-di.xml");
Cat catBean = applicationContext.getBean("catBean", Cat.class);
System.out.println(catBean);
}

4.3.9 注入的值中含有特殊符号

  • XML 中有 5 个特殊字符,分别是:<、>、’、”、&

    • 以上 5 个特殊符号在 XML 中会被特殊对待,会被当做 XML 语法的一部分进行解析,如果这些特殊符号直接出现在注入的字符串当中,会报错。

      ![](../../../../../Running Noob/计算机/Typora笔记/笔记-git仓库/Java-SSM-notebook/img/Spring/注入特殊符号.png)

  • 解决方案包括两种:

    • 第一种:特殊符号使用转义字符代替。

      特殊字符转义字符
      >&gt;
      <&lt;
      &apos;
      &quot;
      &&amp;
    • 第二种:将含有特殊符号的字符串放到: <![CDATA[]]> 当中。放在 CDATA 区中的数据不会被 XML 文件解析器解析,使用 CDATA 时,不能使用 value 属性,只能使用 value 标签。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    package com.f.spring6.bean;

    /**
    * @author fzy
    * @date 2024/1/17 21:56
    */
    public class Math {
    private String result;

    public void setResult(String result) {
    this.result = result;
    }

    @Override
    public String toString() {
    return "Math{" +
    "result='" + result + '\'' +
    '}';
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <?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="mathBean" class="com.f.spring6.bean.Math">
    <!--第一种方案:使用实体符号代替特殊符号-->
    <!--<property name="result" value="2 &lt; 3"/>-->
    <!--第二种方案:使用<![CDATA[]]>-->
    <property name="result">
    <!--只能使用value标签-->
    <value><![CDATA[2 < 3]]></value>
    </property>
    </bean>
    </beans>
    1
    2
    3
    4
    5
    6
    @Test
    public void testSpecial() {
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("set-di.xml");
    Object mathBean = applicationContext.getBean("mathBean", Math.class);
    System.out.println(mathBean);
    }

4.4 p命名空间注入

  • 目的:简化 set 注入。

  • p 命名空间实际上是对 set 注入的简化

    • p 命名空间注入底层还是 set 注入,只不过 p 命名空间注入可以让 spring 配置变得更加简单。
  • 使用 p 命名空间注入的前提条件包括两个:

    • 第一:在 XML 头部信息中添加 p 命名空间的配置信息:xmlns:p="http://www.springframework.org/schema/p"
    • 第二:p 命名空间注入是基于 setter 方法的,所以需要提供对应的属性的 setter 方法。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    package com.f.spring6.bean;

    import java.util.Date;

    /**
    * @author fzy
    * @date 2024/1/17 22:09
    */
    public class Dog {
    private String name;
    private int age;
    private Date birth;

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

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

    public void setBirth(Date birth) {
    this.birth = birth;
    }

    @Override
    public String toString() {
    return "Dog{" +
    "name='" + name + '\'' +
    ", age=" + age +
    ", birth=" + birth +
    '}';
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <?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:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--
    第一步:在spring的配置文件头部添加p命名空间:xmlns:p="http://www.springframework.org/schema/p"
    第二步:使用 p:属性名 = "属性值"
    -->
    <bean id="dogBean" class="com.f.spring6.bean.Dog" p:name="小黄" p:age="2" p:birth-ref="birthBean"/>

    <!--这里获取的是当前系统时间-->
    <bean id="birthBean" class="java.util.Date"/>
    </beans>
    1
    2
    3
    4
    5
    6
    @Test
    public void testP() {
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-p.xml");
    Dog dogBean = applicationContext.getBean("dogBean", Dog.class);
    System.out.println(dogBean);
    }

4.5 c命名空间注入

  • c 命名空间是简化构造方法注入的。

  • 使用 c 命名空间的两个前提条件:

    • 第一:需要在 xml 配置文件头部添加 c 命名空间的配置信息:xmlns:c="http://www.springframework.org/schema/c"
    • 第二:需要提供构造方法。

    c 命名空间是依靠构造方法的。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    package com.f.spring6.bean;

    /**
    * @author fzy
    * @date 2024/1/18 10:34
    */
    public class Bird {
    private String name;
    private String color;

    public Bird(String name, String color) {
    this.name = name;
    this.color = color;
    }

    @Override
    public String toString() {
    return "Bird{" +
    "name='" + name + '\'' +
    ", color='" + color + '\'' +
    '}';
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <?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:c="http://www.springframework.org/schema/c"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--
    第一步:在spring配置文件头部添加c命名空间:xmlns:c="http://www.springframework.org/schema/c"
    第二步:使用
    c:_0 下标方式
    c:name 参数名方式
    -->
    <bean id="birdBean" class="com.f.spring6.bean.Bird" c:name="黄雀" c:color="yellow"/>
    </beans>
    1
    2
    3
    4
    5
    6
    @Test
    public void testC() {
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-c.xml");
    Bird birdBean = applicationContext.getBean("birdBean", Bird.class);
    System.out.println(birdBean);
    }
  • 注意:不管是 p 命名空间还是 c 命名空间,注入的时候都可以注入简单类型以及非简单类型

4.6 util命名空间注入

  • 使用 util 命名空间可以让配置复用。

  • 使用 util 命名空间的前提是:在 spring 配置文件头部添加配置信息。

    • xmlns:util="http://www.springframework.org/schema/util"
    • http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    package com.f.spring6.jdbc;

    import javax.sql.DataSource;
    import java.io.PrintWriter;
    import java.sql.Connection;
    import java.sql.SQLException;
    import java.sql.SQLFeatureNotSupportedException;
    import java.util.Properties;
    import java.util.logging.Logger;

    /**
    * @author fzy
    * @date 2024/1/18 10:52
    */
    public class MyDataSource1 implements DataSource {
    // properties属性类对象,这是一个Map集合,key和value都是String类型
    private Properties properties;

    public void setProperties(Properties properties) {
    this.properties = properties;
    }

    @Override
    public String toString() {
    return "MyDataSource2{" +
    "properties=" + properties +
    '}';
    }

    ......
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    package com.f.spring6.jdbc;

    import javax.sql.DataSource;
    import java.io.PrintWriter;
    import java.sql.Connection;
    import java.sql.SQLException;
    import java.sql.SQLFeatureNotSupportedException;
    import java.util.Properties;
    import java.util.logging.Logger;

    /**
    * @author fzy
    * @date 2024/1/18 10:49
    */
    public class MyDataSource2 implements DataSource {
    // properties属性类对象,这是一个Map集合,key和value都是String类型
    private Properties properties;

    public void setProperties(Properties properties) {
    this.properties = properties;
    }

    @Override
    public String toString() {
    return "MyDataSource2{" +
    "properties=" + properties +
    '}';
    }

    ......
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    <?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/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
    <!--
    第一步:在spring配置文件头部添加:
    xmlns:util="http://www.springframework.org/schema/util"
    http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
    第二步:通过ref引用
    -->
    <util:properties id="p">
    <prop key="driver">com.mysql.cj.jdbc.Driver</prop>
    <prop key="url">jdbc:mysql://localhost:3306/javaweb</prop>
    <prop key="username">root</prop>
    <prop key="password">root</prop>
    </util:properties>
    <!--数据源1,不使用util命名空间-->
    <bean id="myDataSource1" class="com.f.spring6.jdbc.MyDataSource1">
    <property name="properties">
    <props>
    <prop key="driver">com.mysql.cj.jdbc.Driver</prop>
    <prop key="url">jdbc:mysql://localhost:3306/javaweb</prop>
    <prop key="username">root</prop>
    <prop key="password">root</prop>
    </props>
    </property>
    </bean>
    <!--数据源2,使用util命名空间-->
    <bean id="myDataSource2" class="com.f.spring6.jdbc.MyDataSource2">
    <property name="properties" ref="p"/>
    </bean>
    </beans>
    1
    2
    3
    4
    5
    6
    7
    8
    @Test
    public void testUtil() {
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-util.xml");
    MyDataSource1 myDataSource1 = applicationContext.getBean("myDataSource1", MyDataSource1.class);
    MyDataSource2 myDataSource2 = applicationContext.getBean("myDataSource2", MyDataSource2.class);
    System.out.println(myDataSource1);
    System.out.println(myDataSource2);
    }

4.7 基于XML的自动装配

  • Spring 还可以完成自动化的注入,自动化注入又被称为自动装配。

    • 它可以根据名字进行自动装配,也可以根据类型进行自动装配。

    建议还是少用,因为当数据多起来以后,可能容易出错。

4.7.1 根据名称自动装配

  • 如果根据名称装配 (autowire="byName"),底层会调用 set 方法进行注入

    • 根据名字进行自动装配的时候,被注入的对象的 beanid 不能随便写。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    package com.f.spring6.dao;

    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;

    /**
    * @author fzy
    * @date 2024/1/17 15:37
    */
    public class OrderDao {
    private static final Logger logger = LoggerFactory.getLogger(OrderDao.class);

    public void generate() {
    logger.info("正在生成订单...");
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    package com.f.spring6.service;

    import com.f.spring6.dao.OrderDao;

    /**
    * @author fzy
    * @date 2024/1/17 16:05
    */
    public class OrderService {
    private OrderDao orderDao;

    // 通过set方法给属性赋值
    public void setOrderDao(OrderDao orderDao) {
    this.orderDao = orderDao;
    }

    public void generate() {
    this.orderDao.generate();
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    <?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="orderServiceBean" class="com.f.spring6.service.OrderService" autowire="byName"/>
    <!--id一般也叫做bean的名称-->
    <!--根据名字进行自动装配的时候,被注入的对象的bean的id不能随便写。
    set方法的方法名去掉set,剩下单词首字母小写。-->
    <bean id="orderDao" class="com.f.spring6.dao.OrderDao"/>

    <!--<bean id="orderServiceBean" class="com.f.spring6.service.OrderService">-->
    <!-- <property name="orderDao" ref="orderDaoBean"/>-->
    <!--</bean>-->
    <!--<bean id="orderDaoBean" class="com.f.spring6.dao.OrderDao"/>-->
    </beans>
    1
    2
    3
    4
    5
    6
    @Test
    public void testAutoWire() {
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-autowire.xml");
    OrderService orderServiceBean = applicationContext.getBean("orderServiceBean", OrderService.class);
    orderServiceBean.generate();
    }

4.7.2 根据类型自动装配

  • 如果根据类型装配 (autowire="byType"),底层会调用 set 方法进行注入。即:无论是 byName 还是 byType,在装配的时候都是基于 set 方法的,所以 set 方法是必须要提供的,提供构造方法是不行的

  • 如果 byType,在根据类型装配时,如果配置文件中有两个类型一样的 bean 会报错。

    • 当使用 byType 进行自动装配的时候,配置文件中某种类型的 Bean 必须是唯一的,不能出现多个。

      如果存在多个类型一样的 Bean,则 Spring 会不知道使用哪个 Bean 进行注入。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    public class CustomerService {
    private UserDao userDao;
    private VipDao vipDao;

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

    public void setVipDao(VipDao vipDao) {
    this.vipDao = vipDao;
    }

    public void save(){
    userDao.insert();
    vipDao.insert();
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    <!--根据类型进行自动装配-->
    <!--自动装配是基于set方法的-->
    <!--根据类型进行自动装配的时候,在有效的配置文件当中,某种类型的实例只能有一个。-->
    <bean class="com.powernode.spring6.dao.VipDao"></bean>
    <bean id="x" class="com.powernode.spring6.dao.UserDao"></bean>
    <!--如果byType,根据类型装配时,如果配置文件中有两个类型一样的bean会报错-->
    <!--<bean id="y" class="com.powernode.spring6.dao.UserDao"></bean>-->
    <bean id="cs" class="com.powernode.spring6.service.CustomerService" autowire="byType"></bean>

4.8 spring引入外部属性配置文件

  • 我们都知道编写数据源的时候是需要连接数据库的信息的,例如:driver url username password 等信息。这些信息可以单独写到一个属性配置文件中,这样用户修改起来会更加的方便。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    package com.f.spring6.jdbc;

    import javax.sql.DataSource;
    import java.io.PrintWriter;
    import java.sql.Connection;
    import java.sql.SQLException;
    import java.sql.SQLFeatureNotSupportedException;
    import java.util.logging.Logger;

    /**
    * 所有的数据源都要实现java规范:javax.sql.DataSource
    * 什么是数据源:能够给你提供Connection对象的,都是数据源
    *
    * @author fzy
    * @date 2024/1/17 19:26
    */
    public class MyDataSource implements DataSource { // 把数据源交给spring容器来管理
    private String driver;
    private String url;
    private String username;
    private String password;

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

    public void setDriver(String driver) {
    this.driver = driver;
    }

    public void setUrl(String url) {
    this.url = url;
    }

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

    public void setPassword(String password) {
    this.password = password;
    }
    ......
    }
    1
    2
    3
    4
    jdbc.driver=com.mysql.cj.jdbc.Driver
    jdbc.url=jdbc:mysql://localhost:3306/javaweb
    jdbc.username=root
    jdbc.password=root
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    <?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:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    <!--
    引入外部的jdbc.properties文件:
    第一步:引入context命名空间
    xmlns:context="http://www.springframework.org/schema/context"
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
    第二步:使用标签context:property-placeholder的location属性来指定属性配置文件的路径
    location默认从类的根路径下开始加载资源
    第三步:从配置文件中取值:${key}
    ${key}会优先从系统环境变量中加载值,所以一般在properties中会给key加上前缀
    -->
    <context:property-placeholder location="jdbc.properties"/>
    <!--配置数据源-->
    <bean id="myDataSource" class="com.f.spring6.jdbc.MyDataSource">
    <property name="driver" value="${jdbc.driver}"/>
    <property name="url" value="${jdbc.url}"/>
    <property name="username" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>
    </bean>
    </beans>
    1
    2
    3
    4
    5
    6
    @Test
    public void testProperties() {
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-properties.xml");
    MyDataSource myDataSource = applicationContext.getBean("myDataSource", MyDataSource.class);
    System.out.println(myDataSource);
    }
---------------The End---------------