Spring IOC容器

本文详细介绍了Spring框架的核心概念,包括耦合与解耦、控制反转(IOC)、依赖注入(DI),以及Spring容器的配置和管理。涵盖了ApplicationContext和BeanFactory的关系,多配置文件加载,以及如何在实践中应用这些技术进行对象实例化和依赖管理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • 了解spring框架

  • 能够理解什么是耦合和解耦

  • 能够理解什么是控制反转

  • 能够使用spring实例化对象

  • 能够使用spring配置依赖注入

  • 了解ApplicationContext和BeanFactory的关系

  • 理解多配置文件加载

一、Spring框架

1、spring介绍

官网地址:https://spring.io

Spring是一个分层的JavaSE/EE应用full-stack 轻量级开源框架。 EJB重量级框架

Spring是实际意义上的Java编程语言中的行业标准,不学他别说找工作,你甚至不能说学过Java。

2、Spring的优势

Spring使每个人都可以更快,更轻松和更安全地进行Java编程。Spring对速度,简单性和生产效率的关注使其成为世界上最受欢迎 Java框架。

  • Spring无处不在(Spring is everywhere)

    Spring受到全世界开发人员的信任,广泛应用于互联网、物联网各大技术场景。

  • Spring弹性灵活(Spring is flexible)

    Spring 灵活而全面的扩展集和第三方库让开发人员可以构建几乎所有可以想象到的应用程序。

  • Spring生产效率高(Spring is productive)

    • 使用springboot和springcloud可以快速搭建微服务架构的应用程序并部署到云端。
    • 可以在几秒钟内使用Spring Initializr启动一个新的Spring项目
  • Spring就是快(Spring is fast)

    • Spring项目也越来越多地支持响应式(无阻塞)编程模型,以提高效率
  • Spring非常安全(Spring is secure)

    • Spring在快速负责地处理安全问题方面一直做得很好。
  • Spring是有支撑的((Spring is supportive)

    Spring的学习途径非常多,资料也非常齐全,可以通过文档教程、视频教程、社区等各种途径来学习Spring。

  1. Spring核心(当前)

    讲解spring的核心技术的使用及原理。

    spring课程中我们会学习到IOC(控制反转) 和AOP(面向切面编程)两大核心原理。

  2. SpringMVC

    JavaEE项目的技术解决方案。

  3. Springboot与Springcloud

    微服务架构的技术解决方案。

二、IOC

1、耦合和解耦的概念

  1. 什么是程序的耦合?

​ 耦合(Coupling)就是两个东西通过某种作用关联在了一起,例如两个子系统之间的关联程度,两个类之间的关联关系。耦合度就是程序中各个模块之间相互关联的度量。

​ 当一个子系统(或类)发生变化时对另一个子系统(或类)的影响很小,则称它们是松散耦合的;反之,如果变化的影响很大时,则称它们是紧密耦合的。

  1. 什么是解耦?

​ 字面意思就是解除耦合关系。程序间的解耦就是降低耦合度。模块间必然有依赖关系,零耦合是做不到的,可以将耦合度降到最低。

  1. 设计程序的目标

高内聚低耦合: 一个模块内的各个元素之间要高度紧密,但是各个模块之间的相互依存度却不要那么紧密。

2、代码中的耦合

1. 基础代码实现
  • 实体类
public class Account {
    public Account(Integer id, String name, double money) {
        this.id = id;
        this.name = name;
        this.money = money;
    }

    public Account() {
    }

    private Integer id;
    private String name;
    private double money;

		//此处省略set和get方法
}
  • 控制器
    • com.ithiema.controller.AccountController.java
public class AccountController {

    private AccountService accountService = new AccountServiceImpl();

    public void save(Account account) {
        accountService.save(account);
    }
}

  • service接口
    • com.ithiema.service.AccountService.java
public interface AccountService {
    /**
     *保存
     */
    void save(Account account);
}
  • serivce实现类
    • com.ithiema.service.impl.AccountServiceImpl.java
public class AccountServiceImpl implements AccountService {
    @Override
    public void save(Account account) {
       System.out.println("保存用户信息成功:"+account);
    }
}
  • 测试类
    • com.ithiema.controller.AccountControllerTest.java
    • 需要引入junit依赖
public class AccountControllerTest {

    @Test
    public void save() {
        AccountController accountController = new AccountController();
        accountController.save(new Account(1, "特朗普", 5000000000.0));
    }
}
2. 耦合分析与优化

耦合分析

如下图所示,AccountController中有三个耦合,分别是

  • 耦合1:AccountController与AccountService
  • 耦合2:AccountController与Account
  • 耦合3:AccountController与AccountServiceImpl

优化方案(解耦)

耦合1和耦合是无法避免的,但是耦合3(AccountController与AccountServiceImpl)是可以去除的。

  1. 修改AccountController

    /**
     * 账户控制器
     */
    public class AccountController {
    
        private AccountService accountService;
    
        public void save(Account account) {
            accountService.save(account);
        }
    
        public void setAccountService(AccountService accountService) {
            this.accountService = accountService;
        }
    }
    
  2. 修改测试方法

    public class AccountControllerTest {
    
        @Test
        public void save() {
            AccountService accountService = new AccountServiceImpl();
            AccountController accountController = new AccountController();
            accountController.setAccountService(accountService);
            accountController.save(new Account(1, "特朗普", 5000000000.0));
        }
    
    }
    

此时,即使我们把AccountServiceImpl删除掉,AccountController也不会编译报错,因为AccountController本来就和AccountServiceImpl没有直接关系,也就起到了解耦的效果。

3、使用IOC解决问题

1. 导入spring依赖
<!--spring 的ioc容器jar包-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.0.5.RELEASE</version>
</dependency>
2. 创建spring.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
        https://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--创建service对象-->
    <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl"></bean>
    <!--创建controller对象-->
    <bean id="accountController" class="com.itheima.controller.AccountController">
        <!--通过set方法给AccountService属性赋值-->
        <property name="accountService" ref="accountService"></property>
    </bean>
</beans>
3. 调整AccountControllerTest类
public class AccountControllerTest {

    @Test
    public void save() {
        //创建Account对象
        Account account = new Account(1, "特朗普", 5000000.0);
        //创建IOC容器
        ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
        //从容器中获取AccountController对象
        AccountController  accountController = (AccountController) context.getBean("accountController");
        //调用save方法
        accountController.save(account);
    }
}
4. 案例解析
  1. 在上述例子我们没有手动创建AccountService对象、AccountController对象。同时我们也没有手动给AccountController的AccountService属性赋值。我们直接通过下面的配置文件实现创建对象和赋值。

  2. 测试类中,实例化一个ApplicationContext(ClassPathXmlApplicationContext)对象,,通过该类读取配置文件,并执行配置文件里配置的内容。

  3. 创建的对象就放在容器(ApplicationContext)里,需要使用的时候直接获取即可。

4、总结

1. 控制反转(IOC)
  • 在上面的优化方案中,我们没有手动创建对象,成功做到了AccountController和AccountServiceImpl的解耦,而解耦的关键是:将Controller对servcie实现类的控制权(实例化)交给配置文件,通过创建容器实现对象的创建

  • 这种优化方案其实就是**控制反转(IOC,inverse of control )**的思想。

    控制即控制权

    控制反转==对象控制权交给别人来完成。

  • IoC对编程带来的最大改变不是从代码上,而是从思想上,发生了“主从换位”的变化。应用程序原本是老大,要获取什么资源都是主动出击,但是在IoC/DI思想中,应用程序就变成被动的了,被动的等待IoC容器来创建并注入它所需要的资源了。IoC很好的体现了面向对象设计法则之一——好莱坞法则:“Don’t call me; I’ll call you.”;即由IoC容器帮对象找相应的依赖对象并注入,而不是由对象主动去找。

2. 依赖注入(DI)
  • 在上面的案例中,成功做到了把AccountService对象赋值给了AccountController的属性;它们之间的关系是由spring配置实现的;
  • 这种优化方案其实就是依赖注入。
  • 依赖注入是控制反转的一种表现方式。
  • 依赖查找也是控制反转的一种表现方式

三、IOC配置文件详解

1、容器结构[了解]

BeanFactory 才是 Spring 容器中的顶层接口。ApplicationContext 是它的子接口。

ApplicationContext接口的实现类

​ ClassPathXMLApplicationContext 读取类路径下的配置文件

​ FileSystemXmlApplicationContext: 读取 绝对路径下的配置文件

​ AnnotationConfigApplicationContext: 纯注解模式使用创建容器

2、Bean标签详解

1. 环境介绍

​ 继续使用上述案例中的Account类

2. 创建和获取对象
  1. 需求

​ 剖析获取spring容器对象的方法

  1. 配置文件spring02.xml
<!--
    id: 唯一的标识
    class: 类的全限定名称,如果没有空的构造方法,需要其他的配置
-->
<bean id="account" class="com.itheima.pojo.Account"></bean>
  1. 测试方法
@Test
public void getBean(){
    //创建IOC容器
    ApplicationContext context = new ClassPathXmlApplicationContext("spring02.xml");
    //获取对象:根据id获取对象,返回的是Object对象,需要进行强制转换
    Object obj = context.getBean("account");
    Account account1 = (Account) obj;
    System.out.println(account1);
    //获取对象:根据class获取对象,返回Account类型对象,不需要进行强制转换
    Account account2  = context.getBean(Account.class);
    System.out.println(account2);
    //获取对象:根据id 和 class 获取对象,返回Account类型对象,不需要进行强制转换
    Account account3  = context.getBean("account", Account.class);
    System.out.println(account3);
}
  1. 总结
1. 根据id获取对象,返回的是Object对象,需要进行强制转换
   context.getBean("account");
    
2. 根据class获取对象,返回Account类型对象,不需要进行强制转换
    context.getBean(Account.class);
    
3. 根据id 和 class获取对象,返回Account类型对象,不需要进行强制转换(需要满足两个条件)
    context.getBean("account", Account.class);
3. 对象的作用范围
  1. 需求

    spring IOC容器可以帮助我们管理对象,那么每次获取的对象是相同的还是每次都创建一个新的对象呢?

    为了测试效果暂时注释掉toString方法

  2. 配置文件spring03.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
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="account1" class="com.itheima.pojo.Account" ></bean>
    <bean id="account2" class="com.itheima.pojo.Account" scope="singleton"></bean>
    <bean id="account3" class="com.itheima.pojo.Account" scope="prototype"></bean>

</beans>
  1. 测试类
@Test
public void testScope(){
    //创建IOC容器
    ApplicationContext context = new ClassPathXmlApplicationContext("spring03.xml");
    System.out.println("account1:"+context.getBean("account1",Account.class));
    System.out.println("account1:"+context.getBean("account1",Account.class));
    System.out.println("account1:"+context.getBean("account1",Account.class));
    System.out.println("account2:"+context.getBean("account2",Account.class));
    System.out.println("account2:"+context.getBean("account2",Account.class));
    System.out.println("account2:"+context.getBean("account2",Account.class));
    System.out.println("account3:"+context.getBean("account3",Account.class));
    System.out.println("account3:"+context.getBean("account3",Account.class));
    System.out.println("account3:"+context.getBean("account3",Account.class));
}
scope 属性可设置值
  singleton[重点]: 单例模式,全局唯一,只会实例化一次, 默认为单例模式
  prototype[重点]: 原型模式(多例模式),每次getBean都会实例化一个新的对象
  request:请求范围
  session:http Session范围
  application:servletContext范围
  websocket: websocket访问(网络套接字)  
4. 对象的生命周期【了解】
  1. 需求

    spring可以帮助我们创建对象,对象分为单例对象、多例对象,那么对象创建的时机是什么呢?

  2. 代码

    Account对象中添加init和destroy方法

<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean
            id="account1"
            class="com.itheima.pojo.Account"
            init-method="init"
            destroy-method="destroy"
            scope="singleton"></bean>
    <!--<bean-->
            <!--id="account2"-->
            <!--class="com.itheima.pojo.Account"-->
            <!--init-method="init"-->
            <!--destroy-method="destroy"-->
            <!--scope="prototype"></bean>-->
</beans>
  1. 测试
@Test
public void testInitDestroy(){
    //创建IOC容器
    ClassPathXmlApplicationContext context1 = new 			 		                        
      																ClassPathXmlApplicationContext("spring04.xml");
    Object account = context1.getBean("account2");
    System.out.println(account);
    context1.close();
}
  1. 总结
1. 单例模式
	创建容器时创建对象,容器销毁时 对象销毁
2. 原型模式
	创建容器时,对象不会创建,在第一次获取对象时创建对象
	对象不会随着容器的销毁而销毁
3. init-method:指定初始化时执行的方法
4. destory-method:指定销毁时执行的方法,只对scope为singleton的bean有效
  
5. 实例化Bean三种配置方法【了解】
  1. 需求

    我们已经可以通过bean方法创建自定义类的对象,那么如果是别人定义的工厂对象,为了兼容之前的系统,我们应该怎么获取对象呢?

  2. 代码

StaticBeanFactory

public class StaticBeanFactory {
    public static AccountService createAccountService(){
        return new AccountServiceImpl();
    }
}

InstanceBeanFactory

public class InstanceBeanFactory {
    public AccountService createAccountService(){
        return new AccountServiceImpl();
    }
}

配置文件spring-05.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
        https://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--常规方法创建对象-->
    <bean id="accountService"
          class="com.itheima.service.impl.AccountServiceImpl"></bean>
    
    <!--静态工厂的方法创建对象-->
    <bean id="accountService1"
          class="com.itheima.factory.StaticBeanFactory"
          factory-method="createAccountService"></bean>


    <!--创建实例工厂对象-->
    <bean id="beanFactory" class="com.itheima.factory.InstanceBeanFactory"></bean>
    <!--实例工厂的方法创建对象-->
    <bean id="accountService2" factory-bean="beanFactory" factory-method="createAccountService"></bean>

</beans>
  1. 测试
@Test
public void testCreateBean(){
    //创建IOC容器
    ClassPathXmlApplicationContext context1 = new 
      									ClassPathXmlApplicationContext("spring05.xml");
    AccountService account1 = 
      									context1.getBean("accountService1",AccountService.class);
    System.out.println(account1);
    AccountService account2 = 
      									context1.getBean("accountService2",AccountService.class);
    System.out.println(account2);
    AccountService account3 = 
      									context1.getBean("accountService3",AccountService.class);
    System.out.println(account3);
}
  1. 总结
1. bean标签(原始方法)
   class属性:配置类的全限定名(常规方式)
2. 配置静态工场
   classs属性:静态工厂类的全限定名
   factory-method属性:创建对象的静态方法名
3. 配置实例工场(创建先创建实例功能,再根据实例工厂,创建bean对象)
   factory-bean:实例工场bean的唯一标识
   factory-method:创建对象的方法名

四、依赖注入(DI)

1、环境介绍
1. 创建一个新的moudle  study_spring_01_03
2. 引入依赖:spring-context, junit
3. 导入Account类
4. 我们通过spring框架创建account对象,并给其中的属性赋值
2、set方法注入
  1. 需求

    通过set方法给account的属性赋值

  2. 代码

    配置文件spring.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
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="account" class="com.itheima.pojo.Account">
        <property name="id" value="1"></property>
        <property name="name" value="英国女王"></property>
        <property name="money" value="30000000"></property>
    </bean>
</beans>
  1. 测试
@Test
public void test(){
    //创建spring容器
    ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
    Account account = context.getBean("account", Account.class);
    System.out.println(account);
}
  1. 总结
1. property标签可以通过set方法给属性赋值
	 name 指定属性名称
	 value  给属性赋的值
2. 本质
	 虽然name指定的属性名,其实本质是调用的是对象的set方法, 如set方法不存在,配置文件会有编译错误
	 注意:set方法一定要符合格式
3、构造方法注入
  1. 需求

    在开发中,创建其他人定义的对象时,有些属性没有定义set方法,我们也可以采用构造方法注入

  2. 代码

Account类

public class Account {
    public Account(Integer id, String name, double money) {
        System.out.println("执行构造方法 -- 三个参数");
        this.id = id;
        this.name = name;
        this.money = money;
    }

    public Account(String name, double money) {
        System.out.println("执行构造方法 -- 两个参数");
        this.name = name;
        this.money = money;
    }
  
  	// 其他的属性和方法不变
}

spring配置文件

<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="account1" class="com.itheima.pojo.Account">
        <constructor-arg  value="1"></constructor-arg>
        <constructor-arg  value="比尔盖茨"></constructor-arg>
        <constructor-arg  value="999999999"></constructor-arg>
    </bean>

    <bean id="account2" class="com.itheima.pojo.Account">
        <constructor-arg name="name"  value="比尔盖茨"></constructor-arg>
        <constructor-arg name="money" value="999999999"></constructor-arg>
    </bean>

    <bean id="account3" class="com.itheima.pojo.Account">
        <constructor-arg index="0"  value="比尔盖茨"></constructor-arg>
        <constructor-arg index="1" value="999999999"></constructor-arg>
    </bean>

    <bean id="account4" class="com.itheima.pojo.Account">
        <constructor-arg type="java.lang.Integer"  value="2"></constructor-arg>
        <constructor-arg type="java.lang.String" value="李嘉诚"></constructor-arg>
        <constructor-arg type="double" value="999999999"></constructor-arg>
    </bean>
</beans>
  1. 测试
@Test
public void test(){
    //创建spring容器
    ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
    Account account1 = context.getBean("account1", Account.class);
    Account account2 = context.getBean("account2", Account.class);
    Account account3 = context.getBean("account3", Account.class);
    Account account4 = context.getBean("account4", Account.class);
    System.out.println(account1);
    System.out.println(account2);
    System.out.println(account3);
    System.out.println(account4);
}
  1. 总结
通过构造方法给属性赋值
	<constructor-arg name="name"  value="比尔盖茨"></constructor-arg>
1. 支持按照参数名注入
2. 支持按照类型注入
3. 支持按照索引注入
4. 支持按照顺序注入
4、注入引用数据类型
  1. 需求

    如果在Account对象中有一个日期类的属性,应该怎么注入呢?

  2. 代码

我们在Account中添加一个日期类型的属性,并添加set和get方法,修改toString方法

private Date birthday;

spring配置文件

<bean id="birthday" class="java.util.Date"></bean>
<bean id="account5" class="com.itheima.pojo.Account">
    <property name="birthday" ref="birthday"></property>
</bean>
  1. 测试
@Test
public void test(){
    //创建spring容器
    ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
    Account account5 = context.getBean("account5", Account.class);
    System.out.println(account5);
}
  1. 总结
注入引用数据类型:需要先用bean标签创建对象, 再使用ref引用对象
5、p名称空间注入[了解]
  1. 需求

    set方法的注入还有另一种形式

  2. 代码

    spring配置文件

<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="birthday" class="java.util.Date"></bean>
    <bean id="account6"
          class="com.itheima.pojo.Account"
          p:birthday-ref="birthday" p:id="6" p:name="马云" p:money="999999999">
    </bean>
</beans>
  1. 测试
@Test
public void test(){
    //创建spring容器
    ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
    Account account6 = context.getBean("account6", Account.class);
    System.out.println(account6);
}
  1. 总结
1. p名称空间是基于set方法实现的
2. 使用p名称空间注入,需要在头部引入p名称空间
3. p:name="" 注入基本数据类型   p:birthday-ref=""  注入引用数据类型
6、注入复杂类型
  1. 需求

    有时候我们需要注入一些其他的类型,例如list,set, map ,array 类型的对象

  2. 代码

Account.java 中添加属性

private String[] myStrs;//数组
private List<String> myList;//list集合
private Set<String> mySet;//set集合
private Map<String,String> myMap;//map
private Properties myProps;//Properties
//此处省略set和get方法
//修改toString方法

spring配置文件

<bean id="account7" class="com.itheima.pojo.Account">
    <property name="myStrs">
        <array>
            <value>mybatis</value>
            <value>spring</value>
            <value>springMVC</value>
        </array>
    </property>
    <property name="myList">
        <list>
            <value>表现层</value>
            <value>业务层</value>
            <value>持久层</value>
        </list>
    </property>
    <property name="mySet">
        <set>
            <value>模型层</value>
            <value>视图层</value>
            <value>控制层</value>
        </set>
    </property>
    <property name="myMap">
        <map>
            <entry key="M" value="Model"></entry>
            <entry key="V" value="View"></entry>
            <entry key="C" value="Controller"></entry>
        </map>
    </property>
    <property name="myProps">
        <props>
            <prop key="M">Model</prop>
            <prop key="V">View</prop>
            <prop key="C">Controller</prop>
        </props>
    </property>
</bean>
  1. 测试
@Test
public void test(){
    //创建spring容器
    ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
    Account account7 = context.getBean("account7", Account.class);
    System.out.println(account7);
}
  1. 总结
1. 注入set,list,array 属性,分别使用 set, list , array 标签;
		因为三种标签都是单列数据,可以交换使用,建议按照对应标签配置
2. 注入map,properties 属性,分别使用 map,props 标签	
		因为都是键值对数据,可以交换使用,建议按照对应标签配置
7、SpEL表达式
  1. 需求

    通过上面配置发现,关联属性值,可以用value属性和ref属性, SpEL提供一种固定的格式

  2. 代码

<bean id="account8" class="com.itheima.pojo.Account">
    <property name="id" value="#{8}"></property>
    <property name="name" value="#{'马化腾'}"></property>
    <property name="money" value="#{999999}"></property>
    <property name="birthday" value="#{birthday}"></property>
</bean>
  1. 测试
@Test
public void test(){
    //创建spring容器
    ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
    Account account8 = context.getBean("account8", Account.class);
    System.out.println(account8);
}
  1. 总结
通过 #{} 提供了一种统一的注入方式, 统一使用value属性即可
需要注意的是, 注入字符串需要手动添加  单引号

五、加载Properties

  1. 需求

    spring框架对很多很底层的技术提供了支持,让我们不必再为单例模式类、属性文件解析等学习新的API。

    我们前面已经学习过了单例模式, 下面我们看看怎么引入属性文件。

  2. 代码

data.properties

account.id=1
account.name=刘强东
account.money=3000000

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

    <contxt:property-placeholder location="classpath:data.properties"
                                 file-encoding="UTF-8"></contxt:property-placeholder>
    <bean id="account9" class="com.itheima.pojo.Account">
        <property name="id" value="${account.id}"></property>
        <property name="name" value="${account.name}"></property>
        <property name="money" value="${account.money}"></property>
    </bean>
</beans>
  1. 测试
@Test
public void test(){
    //创建spring容器
    ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
    Account account9 = context.getBean("account9", Account.class);
    System.out.println(account9);
}
  1. 总结
1. <contxt:property-placeholder> 需要新增名称空间,具体看下图
2. 通过<contxt:property-placeholder> 标签加载属性文件
		location属性指定 属性文件的位置
		属性文件中如果有中文,需要指定加载的编码格式
3. 如果要加载多个属性文件,location属性中提供一个或多个位置作为逗号分隔的列表。
4. 加载类路径下的资源,需要添加字符串前缀:classpath: 

六、多配置文件

  1. 需求

    在开发中会有很多配置信息,经常会按照类型分成多个文件,如果有多个文件,那我们的配置方式有什么要注意的呢,怎么共同加载呢?

  2. 代码

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

    <bean id="birthday" class="java.util.Date"></bean>

</beans>

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

    <bean id="account9" class="com.itheima.pojo.Account">
        <property name="birthday" ref="birthday"></property>
    </bean>
</beans>
  1. 测试
public class AccountBeanTest {
    @Test
    public void test(){
        //创建spring容器
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-01.xml","spring-02.xml");
        Account account9 = context.getBean("account9", Account.class);
        System.out.println(account9);
    }
}
  1. 总结
1. 方法一:如果有多个配置文件,可以在创建容器时加载多个配置文件
2. 方法二:也可以在spring-02.xml 中引入spring-01.xml文件,此时测试类只需要加载spring-02.xml即可
3. 方法三:也可以直接创建一个新的配置文件,同时引入spring-01.xml和spring-02.xml ,测试测试类只需要加载新的配置文件即可
4. 注意:如果有多个配置文件,不同的配置文件中有相同的id,后面加载的配置文件会覆盖前面的对象。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值