首页 > 其他分享 >Spring-day01

Spring-day01

时间:2023-03-11 16:35:24浏览次数:47  
标签:name 配置文件 Spring day01 bean UserService public

Spring-day01

# 前置课程
1. javase 
	1). 面向对象: 封装,继承,多态(面向接口)
	2). 反射
	3). 动态代理
2. javaweb
	1). servlet编程规范
	2). 网络编程
3. 数据库
	1). sql
	2). mybatis框架
	
# 框架阶段
1. 时间 (8天)
	1). spring : 3天  (IOC、AOP)
	2). springmvc : 2天 (底层封装Servlet)
	3). maven高级 : 1天
	4). springboot 1天 (基于SSM做简化)
	5). 综合案例: 1天
2. SSM
	1). springmvc (控制层/web层)
	2). spring (业务层)
	3). mybatis (持久层)

框架课:以练习为主(多写代码)

框架:就是第三方组织开发的半成品软件(我们就是学习软件的使用)

在开发中:新增类/方法、删除类/方法,比修改类或方法便捷

  • 尽量不修改源代码

01_Spring初体验

目标

  • 能够使用Spring框架初步改造案例代码

路径

  1. 综合案例中代码优化方式
  2. 使用Spring框架改造案例

综合案例中代码优化方式

在前面开发的web综合案例用户权限系统中,在web层调用业务层代码的优化使用了:"工厂类+反射+配置文件"的方式解决。

image-20220411185048142

只需要告知工厂,要使用哪个类,工厂类就自动创建该类对象并返回

  • 底层实现机制:工厂类 + 配置文件
    • 工厂类中使用反射技术

好处:

  1. 解耦(类和类之间没有直接关系)
  2. 便于程序的维护

image-20220411193124931

而这种工厂类+反射+配置文件的开发方式,已经有一个现成的框架(Spring)提供了。

使用Spring框架改造案例

使用Spring改造案例的步骤:

  1. 导入spring坐标(5.1.9.release)

  2. 编写业务层接口与实现类

  3. 建立Spring配置文件

  4. 配置所需资源(Service)为Spring控制的资源

  5. 表现层通过Spring获取资源(Service实例)

第1步:导入Spring坐标

<dependencies>
    <!-- spring依赖 -->      
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.1.9.RELEASE</version>
    </dependency>   
</dependencies>

第2步:编写业务层接口与实现类

//业务层接口
public interface UserService {
    //添加用户
    public abstract boolean addUser(User user);
    //查询用户数据
    public abstract List<User> findUsers();
}
//业务层实现类
public class UserServiceImpl implements UserService {
    @Override
    public boolean addUser(User user) {
        //省略代码...

        //模拟数据
        boolean saveResult = true;
        return saveResult;
    }
    @Override
    public List<User> findUsers() {
        //省略代码...

        //模拟数据
        List<User> userList = new ArrayList<>();
        userList.add(new User("用户名","密码"));
        userList.add(new User("itheima","123123"));
        
        return userList;
    }
}

第3步:建立Spring配置文件

  • 在maven工程的resources目录下创建:applicationContext.xml

第4步:配置所需资源(Service)为Spring控制的资源

  • 在applicationContext.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">
   <!-- 创建spring控制的资源
        id : 是这个bean(类)的标识。  【见名知其意】
        class : 指定实现类的全限定名。
    -->
    <bean id="userService" class="com.itheima.service.impl.UserServiceImpl"/>
</beans>

第5步:表现层通过Spring获取资源(Service实例)

@WebServlet("/user/*")
public class UserServlet extends BaseServlet {
    //业务层对象(父接口)
    private UserService userService;

    public UserServlet() {
        //1.加载配置文件
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        //2.获取资源: 通过配置文件中的id
        userService = (UserService) ctx.getBean("userService");
    }


    /**
     * 添加用户
     *
     * @param request
     * @param response
     * @throws IOException
     */
    private void addUser(HttpServletRequest request, HttpServletResponse response) throws IOException {
        //调用业务层功能: 添加用户
        boolean result = userService.addUser(new User("测试用户", "测试密码"));

        if (result) {
            response.getWriter().print("用户添加成功!");
        }
    }

    /**
     * 查询用户数据
     *
     * @param request
     * @param response
     * @throws IOException
     */
    private void queryUser(HttpServletRequest request, HttpServletResponse response) throws IOException {
        //调用业务层功能: 查询用户信息
        List<User> users = userService.findUsers();

        //测试:打印查询用户
        for (User user : users) {
            System.out.println(user);
        }
    }

}

小结

使用spring框架开发代码的步骤:

  1. 导入spring坐标

  2. 建立spring配置文件

  3. 在spring配置文件中配置所需资源(把类托管给spring来管理和创建对象)

  4. 通过spring获取资源(获取对象)

02_Spring简介

目标

  • 了解Spring技术的背景

路径

  1. 什么是Spring
  2. Spring的发展历史

什么是Spring

Spring是一个开源框架。简单来说,Spring是一个分层的JavaSE/EE 一站式(full-stack) 轻量级开源框架。

1590631495077
分层:每一个层都有提供的解决方案

  • web层:struts2,spring-MVC
  • service层:spring
  • dao层:mybatis , spring-data

一站式(full-stack):简单来讲就是将各层能够无缝的集成在一起,提高开发的效率

轻量级:与EJB(enterprice javabean)对比,依赖资源少,消耗的资源少。

官网:https://spring.io/

Spring的发展历史

Java语言分类 :

  1. JavaSE:java standard edition 标准
  2. JavaEE:java enterprice edition 企业
  3. JavaME:java micro edition 微型

Spring的发展历史:

  • 1997年IBM提出了EJB的思想(EJB是的Enterprise Java Beans技术的简称, 又被称为企业Java Beans)
  • 1998年,SUN制定开发标准规范EJB1.0
  • 1999年,EJB1.1发布
  • 2001年,EJB2.0发布
  • 2003年,EJB2.1发布
  • 2006年,EJB3.0发布

Rod Johnson(罗德·约翰逊) [Spring之父]
Expert One-to-One J2EE Design and Development(2002)
阐述了J2EE使用EJB开发设计的优点及解决方案

​ Expert One-to-One J2EE Development without EJB(2004)
​ 阐述了J2EE开发不使用EJB的解决方式(Spring雏形)

2017年9月份发布了spring的最新版本--spring 5.0通用版

小结

Spring技术:

  1. spring是一个开源框架
  2. spring可以把JavaEE开发中使用到的各种框架技术(如:mybatis等)整合在一起
  3. 现在使用的spring最新版本为:spring 5.x

03_Spring体系结构

目标

  • 能够说出Spring技术体系中的核心是什么

路径

  1. Spring体系结构
  2. Spring优势
  3. Spring核心

Spring体系结构

image-20220417141444051

Spring优势

Spring 出现是为了解决JavaEE 实际问题:

  • 方便解耦,简化开发 (IOC)

    Spring就是一个大工厂(容器)。
    通过Spring提供的容器,可以将对象的创建和对象间的依赖关系交由Spring进行管理,避免硬编码所造成的过度程序耦合。
    用户也不必再为单例模式类、属性文件解析等这些很底层的需求编写代码,可以更专注于上层的应用。
    
  • AOP编程的支持

    Spring提供面向切面(AOP)编程,可以方便的实现对程序进行权限拦截、运行监控等功能。	
    
  • 声明式事务的支持

    将程序员从单调烦闷的事务管理代码中解脱出来。
    只需要通过配置就可以完成对事务的管理,而无需手动编程。
    
  • 方便程序的测试

    Spring对Junit4支持,可以通过注解方便的测试Spring程序。
    
  • 方便集成各种优秀框架

    Spring可以降低各种框架的使用难度,提供了对各种优秀框架(如:Struts、Hibernate、MyBatis、Quartz(定时任务)等)的直接支持。
    
  • 降低JavaEE API的使用难度

    Spring对JavaEE开发中使用的一些API(如:JDBC、JavaMail、远程调用等),进行了封装,使这些API的应用难度大大降低。
    

基于这些特性,通常称Spring为开发架构的粘合剂

Spring核心

Spring为企业级开发提供了丰富的功能,这些功能的底层都依赖于它的两个核心特性:

  • 控制反转(Inversion of Control,IOC): 将对象创建权利交给Spring工厂进行管理
  • 面向切面编程(aspect-oriented programming,AOP): 基于动态代理的功能增强方式

小结

  • Spring技术的核心是:控制反转(IoC)面向切面(AOP

04_IOC介绍-解耦的思想

目标

  • 能够说出程序中代码解耦的思路

路径

  1. 优质程序代码的制作原则
  2. 耦合和解耦
  3. 解耦的思想

优质程序代码的制作原则

程序书写的目标:高内聚,低耦合

  • 耦合(Coupling):

  • 代码书写过程中所使用技术的结合紧密度,用于衡量软件中各个模块之间的互联程度

    A.jar
    |-- Hello.java
    
    B程序中导入A.jar后,书写代码:   Hello hello = new Hello(); //结合紧密度高(高耦合)
    
  • 内聚(Cohesion):

  • 代码书写过程中单个模块内部各组成部分间的联系,用于衡量软件中各个功能模块内部的功能联系

  • 结论:

    • 同一个模块内的各个元素之间要高度紧密(高内聚)
    • 不同模块之间的相互依赖程序不要过于紧密(低耦合)
  • 好处:

    • 便于代码的长期维护和扩展

耦合和解耦

问题:早期我们的 JDBC 操作,注册驱动时,我们为什么不使用 DriverManager 的 register 方法,而是采用 Class.forName 的方式?

public static void main(String[] args) throws SQLException {
        // 注册驱动(绑定死MySQL驱动类)
        DriverManager.registerDriver(new com.mysql.jdbc.Driver());

        //获取数据库连接
        String url="jdbc:mysql://127.0.0.1:3306/itheima";
        Connection con = DriverManager.getConnection(url, "root", "itheima");

        //后续代码省略......
}

原因就是:我们的类依赖了数据库的具体驱动类(MySQL),如果这时候更换了数据库(如:Oracle), 需要修改源码来重新数据库驱动。这显然不方便程序后期的维护。

存在的问题:耦合性高

解耦的思想

解决程序耦合问题的思路:

/**
 * 程序的耦合
 * 		耦合:程序间的依赖关系
 * 			包括:
 * 			 	类之间的依赖
 * 				方法间的依赖
 * 		解耦: 降低程序间的依赖关系
 * 	实际开发中:
 * 		应该做到:编译期不依赖,运行时才依赖。
 *  
 *  解耦的思路:
 *  	第一步:使用反射来创建对象,而避免使用 new 关键字。
 *	 	第二步:通过读取配置文件来获取要创建的对象全限定类名
 */

在讲解 jdbc 时,我们是通过反射技术来注册驱动的,代码如下:

Class.forName("com.mysql.jdbc.Driver"); //此处只是一个字符串
public class DecoupleDemo {
    public static void main(String[] args) throws SQLException, ClassNotFoundException {
        // 1. 加载数据库驱动
        Class.forName("com.mysql.jdbc.Driver"); //API: forName(String s)
        // 2. 建立数据库连接
        String url = "jdbc:mysql://127.0.0.1:3306/itheima";
        Connection con = DriverManager.getConnection(url, "root", "root");
        // 3. 获取数据库操作对象
        String sql = "select id,name from tb_user";
        PreparedStatement pstmt = con.prepareStatement(sql);
        // 4. 执行sql语句,并且获取结果
        ResultSet rs = pstmt.executeQuery();
        // 5. 处理结果
        while (rs.next()) {
            System.out.println(rs.getString("name"));
        }
        //6. 释放资源
        rs.close();
        pstmt.close();
        con.close();
    }
}

此时的好处是,我们的类中不再依赖具体的驱动类,此时就算删除mysql的驱动jar包,依然可以编译(运行就不要想了,没有驱动不可能运行成功的)。

同时,也产生了一个新的问题,mysql 驱动的全限定类名字符串是在 java 类中写死的,一旦要改还是要修改源码。

解决方案:使用配置文件 (jdbc程序中读取db.properties配置文件)

### db.properties ###
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/itheima
jdbc.name=root
jdbc.password=itheima

小结

  • 耦合:程序间的依赖关系(类之间的依赖、方法间的依赖)

  • 解耦:降低程序间的依赖关系

  • 解耦的思路:

    1. 第一步:使用反射来创建对象,而避免使用 new 关键字
    2. 第二步:通过读取配置文件来获取要创建的对象全限定类名
  • 在开发中应该做到:编译期不依赖,运行时才依赖

05_IOC介绍-IOC思想

目标

  • 能够说出IOC思想

路径

  1. IOC的定义
  2. IOC思想的代码演变

IOC的定义

IOC:控制反转。( 英文全称: inversion of control )

  • 控制:对象的控制权(如:创建、销毁)
  • 反转:对象的控制权从开发者手里转移到工厂中
由主动初始化到被动由工厂创建的这个过程,叫做控制反转(即IOC):工厂+反射+配置文件

以前:在获取对象时,都是采用new的方式(控制权在开发者手中。主动获取)

image-20220417184644406

现在:获取对象时,跟工厂要。有工厂为我们创建对象(控制权从开发者手里转移到工厂中。被动获取)

image-20220417184722599

这种被动获取对象的思想就是控制反转,它是spring框架的核心之一。

它的作用只有一个:削减计算机程序的耦合。

  • 解耦(不是解决当前问题,而是为了对未来兼容)

IOC思想的代码演变

从学习Java开始到现在,大家的编程思想一直在升级,现已升级到:使用工厂+反射+配置文件创建对象

image-20220411185048142

IOC思想代码演变:

//需求:创建service层对象

/* 1. 主动创建对象 */ 
   UserServiceImpl  userService = new UserServiceImpl();
   // 存在的问题:耦合严重。   当service层类需要变动,左右两遍都要修改。


/* 2. 面向接口编程 (多态) */ 
   UserSerivce  userService = new UserServiceImpl();
   // 好处:解耦。   当dao层实现类需要变动,等号左边代码不需要修改。
   // 缺点:等号右边代码还要变动。 
       

/* 3. 反射 + 配置文件 */ 
   ResourceBundle bundle = ResourceBundle.getBundle("service");//读取配置文件
   String userServiceClassName = bundle.getString("userService");//获取配置文件中信息
   Class userServiceCalss = Class.forName(userServiceClassName);//反射获取类的Class对象
   UserService userService = (UserService) userServiceCalss.newInstance();//实例化
   // 好处: 进一步解耦。  当service层实现类需要变动,不需要修改代码(直接修改配置文件即可)
   // 缺点: 代码多。 (对程序员来讲)


/* 4. 工厂模式 (工厂+反射+配置文件) */ 
   UserService userService = (UserService) BeanFactory.getBean("userService");
   // 好处: 封装了创建对象的方法,更好的管理对象。

小结

IOC思想:对象的控制权从开发者手里转移到工厂中

Spring框架的底层也是使用:工厂类、反射、配置文件

框架做的事:

  • 工厂类
  • 制定配置文件编写规范

框架的使用者做的事:

  • 编写实现类
  • 进行配置
  • 用工厂获取对象

06_Spring中的工厂

目标

  • 能够使用ApplicationContext加载配置文件

路径

  1. Spring工厂结构介绍
  2. 使用ApplicationContext工厂加载配置文件

Spring工厂结构介绍

image-20220417122831926

ApplicationContext是一个接口,提供了访问spring容器的API

  • BeanFactory接口是ApplicationContext的父接口
    • BeanFactory是spring容器中的顶层接口,定义了bean相关的最基本操作
    • ApplicationContext在BeanFactory基础上追加了若干新功能

ApplicationContext是一个接口实现类:

  • ClassPathXmlApplicationContext是ApplicationContext接口的实现类
    • 作用:加载类路径下xml配置文件
    • 实现技术:xml解析
  • AnnotationConfigApplicationContext是ApplicationContext接口的实现类
    • 作用:加载注解配置
    • 实现技术:反射
  • FileSystemXmlApplicationContext (了解即可)
    • 从磁盘路径上加载配置文件,配置文件可以在磁盘的任意位置

使用ApplicationContext工厂加载配置文件

配置文件:

<?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">
    <!-- 创建spring控制的资源
         id : 是这个bean(类)的标识。  【见名知其意】
         class : 指定实现类的全限定名。
     -->
    <bean id="userService" class="com.itheima.example.service.impl.UserServiceImpl"/>
    
    <!-- 新增的spring资源:学生业务类 -->
    <bean id="StudentService" class="com.itheima.spring.appcontext.impl.StudentServiceImpl"/>
</beans>

测试类代码:

package com.itheima.spring.appcontext;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class ApplicationContextDemo1 {

    @Test
    public void testApplicationContext(){
        /**
         * ApplicationContext : 父接口
         * ClassPathXmlApplicationContext :  ApplicationContext接口的实现类
         *                                   作用:加载类路径下xml配置文件
         *                                   实现技术: xml解析
         */
        //加载指定的xml配置文件
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

        //获取Spring管理的资源。   通过配置文件中的<bean>标签中的id属性值
        StudentService studentService = (StudentService) ctx.getBean("StudentService");

        //调用方法
        studentService.sayHello();
    }
}

小结:

  • ApplicationContext提供了访问Spring容器的API

  • 使用Spring工厂加载配置文件的方式:

     ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    

07_Spring的IOC配置-bean标签

目标

  • 能够在配置文件中使用bean标签配置Spring资源

路径

  1. bean标签的介绍
  2. 获取bean标签配置的Spring容器中的资源
  3. bean标签中id和name的区别

bean标签的介绍

在前面使用Spring编写代码时:通过ApplicationContext工厂,获取配置文件中所定义的资源

  • 资源的定义是使用<bean>标签

image-20220417200638804

bean标签:

  • 作用:

    • 定义spring中的资源,受此标签定义的资源将受到spring控制(用于配置让spring来创建的对象)
  • 书写格式:

    <beans>
        <!-- 定义spring中的资源 -->
        <bean></bean>
    </beans>
    
  • 基本属性:

    <bean id="beanId" name="beanName" class="ClassName"></bean>
    
    • id:bean的名称, 可以通过id值获取bean定义的资源。(唯一)
    • name:bean的名称,可以通过name值获取bean定义的资源。(唯一)【类似于别名】
    • class:bean的类型 (全限定名)

获取bean标签配置的Spring容器中的资源

案例:获取bean标签定义的资源

  • 第1步:配置文件

    <?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">
        
        <!-- name和id的作用相似, 可以通过name获取bean -->
        <bean id="userService2" name="userService3,userService4" class="com.itheima.spring.bean.UserServiceImpl"/>
    </beans>
    
    • 说明:name属性是定义别名的,可以指定多个名称。
  • 第2步:测试类

    public class SpringBeanDemo1 {
        @Test
        public void testBeanMethod1(){
            //加载指定的xml配置文件
            ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    
            //获取Spring容器中的资源(通过id 或 name都可以获取到)
            //通过id获取
    //        UserService userService = (UserService) ctx.getBean("userService2");
            //通过name获取
    //        UserService userService = (UserService) ctx.getBean("userService3");
            UserService userService = (UserService) ctx.getBean("userService4");
    
            //调用方法
            userService.save();
        }
    }
    

bean标签中id和name的区别

<bean id="userService2" class="com.itheima.spring.bean.UserServiceImpl"/>
<bean name="userService3" class="com.itheima.spring.bean.UserServiceImpl"/>
  • bean中的id属性:bean的唯一标识符(只能设置一个)
  • bean中的name属性:bean的别名(可以设置多个)

注意细节:

  • 不管是标识符,还是别名,在容器中必需唯一(如果不唯一,显然不知道获取的到底是哪一个bean)

  • 同时设置了id和name属性,那么id设置的即是唯一标识符,name设置的是别名

  • 同时设置了id和name属性,并且id和name的值相同,spring容器会自动检测并消除冲突,这个bean就只会有标识符,没有别名

  • 只设置了name属性(没有id属性),那么name属性就是作为bean的唯一标识符。并且name的值在spring容器中必须唯一

  • 没有设置id,而name属性设置了多个值,那么name的第一个值会被用作标识符,其他的值被视为别名

    • 如果设置了id,那么name的所有值都是别名

08_Spring的IOC配置-bean的作用域

目标

  • 能够使用Spring切换单例或多例

路径

  1. bean的作用域介绍
  2. 设置bean作用域的代码示例

bean的作用域介绍

在程序中,想要使用spring所创建的对象是单例模式,需要对bean标签进行作用域设置。

在bean标签中使用scope属性,可以设置bean的作用域范围:

<bean scope="singleton"></bean>
  • scope属性的取值:

    • singleton:设定创建出的对象保存在spring容器中,是一个单例的对象
    • prototype:设定创建出的对象保存在spring容器中,是一个非单例的对象
    • request、session、application、 websocket :设定创建出的对象放置在web容器对应的位置 (了解)

设置bean作用域的代码示例

配置文件:

<?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">
  
    <!--
        scope : 作用域范围
            1. singleton : 单例 (默认值)
                    1). 这个类在容器只会有一个实例
                    2). 饿汉单例 : 工厂加载配置文件的时候,实例就创建了
                        效率高
            2. prototype : 多例
                    1). 这个类在容器有多个实例
                    2). 懒汉多例 : 工厂加载配置文件的时候,没有实例, 获取的时候才创建

            3. 运用:
                1). 单例: 全工程只要一个实例 (例:连接池, 线程池, 工厂...)
                2). 多例: 全工程需要多个实例 (例:连接, 线程 ... )
    -->
    <bean id="singleUserService" scope="prototype" class="com.itheima.spring.bean.UserServiceImpl"/>
    
</beans>

修改实现类:

public class UserServiceImpl implements UserService{
    //添加:构造方法
    public UserServiceImpl(){
        System.out.println("UserServiceImpl构造器");
    }
    public void save(){
        System.out.println("执行保存功能....");
    }
}

测试类:

public class SpringSingleBeanDemo {
    @Test
    public void testSingleBeanMethod(){
        //加载指定的xml配置文件
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

        //获取Spring容器中的资源
        UserService  userService1 = (UserService) ctx.getBean("singleUserService");
        UserService  userService2 = (UserService) ctx.getBean("singleUserService");

        //测试:输出
        System.out.println(userService1);
        System.out.println(userService2);
    }
}
//输出结果:
UserServiceImpl构造器
UserServiceImpl构造器
com.itheima.spring.bean.UserServiceImpl@3043fe0e
com.itheima.spring.bean.UserServiceImpl@78e67e0a

09_Spring的IOC配置-bean的生命周期

目标

  • 了解单例bean的生命周期和多例bean的生命周期的区别

路径

  1. bean的生命周期介绍
  2. bean生命周期的代码示例

bean的生命周期介绍

在程序中,一个对象从创建到销毁的过程,就是该对象的生命周期。

通过spring来创建的bean对象,也同样具有生命周期:

  • 单例对象:scope="singleton"
    • 一个应用只有一个对象实例。它的作用范围就是整个应用。
    • 生命周期:
      • 对象出生:当应用加载,创建容器时,对象就被创建了。
      • 对象活着:只要容器在,对象一直活着。
      • 对象死亡:当应用卸载,销毁容器时,对象就被销毁了。
  • 多例对象:scope="prototype"
    • 每次访问对象时,都会重新创建对象实例。
    • 生命周期:
      • 对象出生:当使用对象时,创建新的对象实例(getBean)。
      • 对象活着:只要对象在使用中,就一直活着。
      • 对象死亡:当对象长时间不用时,会被java的垃圾回收器回收。

可以在bean标签中,使用init-methoddestroy-method两个属性,分别定义bean对象在初始化或销毁时要完成的工作

<bean init-method="指定初始化方法" destroy-method="指定销毁方法"></bean>
  • init-method属性值: bean对应的类中初始化方法的名字
  • destroy-method属性值:bean对应的类中销毁方法的名字

注意事项:

  • 当scope=“singleton”时,spring容器中有且仅有一个对象,指定的初始化方法在创建容器时仅执行一次

  • 当scope=“prototype”时,spring容器要创建同一类型的多个对象,初始化方法在每个对象创建时均执行一次

  • 当scope=“singleton”时,关闭容器会导致bean实例的销毁,调用指定的销毁方法一次

  • 当scope=“prototype”时,对象的销毁由垃圾回收机制gc()控制,销毁方法将不会被执行

bean生命周期的代码示例

配置文件:

<?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的生命周期方法
          0. 概念
              生命周期: 从创建到销毁的整个过程
              bean的生命周期方法 : 在一个bean从创建到销毁的整个过程中执行的方法
  
          1. init-method : 用来指定bean的init方法(初始化)
              执行时机: 此方法bean创建的时候调用
              适合 : 初始化数据
  
          2. destroy-method : 用来指定bean的destroy方法(销毁)
              此方法bean销毁的时候调用
              适合 : 保存数据,释放资源
  
          底层原理:
              Class clazz = Class.forName("com.itheima.service.impl.UserServiceImpl");
              Object obj = clazz.newInstance(); // 通过空参构造创建实例
              //在类中,找到名为 myInit 的public空参方法
              Method method = clazz.getMethod("myInit");
              //调用方法
              method.invoke(obj);
  
         单例:
            1. 初始化:工厂(ioc容器)创建时bean就会被加载, bean的init方法就会执行
            2. 销毁:程序终止, 工厂(ioc容器)销毁,bean也会随之销毁,destroy方法就会执行
         多例:
            1. 初始化:每从ioc容器中获取一个bean,就会创建一个bean,init方法就会被调用一次
            2. 销毁:bean对象不由ioc容器管理, ioc容器销毁, bean不会随之销毁的,destroy不执行
                       由GC管理(垃圾回收器)
      -->
    <bean id="lifecycleUserService" scope="singleton" class="com.itheima.spring.bean.UserServiceImpl"
          init-method="myInit" 
          destroy-method="myDestroy"/>
    
</beans>

修改实现类:

public class UserServiceImpl implements UserService{
    public UserServiceImpl(){
        System.out.println("UserServiceImpl构造器");
    }
    @Override
    public void save(){
        System.out.println("执行保存功能....");
    }
    //添加:初始化方法
    public void myInit(){
        System.out.println("UserServiceImpl类中初始化方法");
    }
    //添加:销毁方法
    public void myDestroy(){
        System.out.println("UserServiceImpl类中销毁方法");
    }
}

测试类:

public class SpringBeanLifecycleDemo {
    @Test
    public void testLifecycleBeanMethod(){
        //加载指定的xml配置文件
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

        //获取Spring容器中的资源
        UserService userService1 = (UserService) ctx.getBean("lifecycleUserService");
        UserService userService2 = (UserService) ctx.getBean("lifecycleUserService");


         /* 工厂销毁 (当程序运行结束时,工厂就会销毁)
            1. 如果程序正常运行终止, 工厂是会销毁的,但是因为demo的运行太快, destroy有执行
                但是时间太短,看不到destroy,所以现在手动调用close方法
            2. close方法是属于 ClassPathXmlApplicationContext特有的(要强制类型转换)
         */
        ((ClassPathXmlApplicationContext)ctx).close();
    }
}
//运行结果:   当bean设置 scope="singleton"
UserServiceImpl构造器
UserServiceImpl类中初始化方法
UserServiceImpl类中销毁方法


//运行结果:   当bean设置 scope="prototype"
UserServiceImpl构造器
UserServiceImpl类中初始化方法
UserServiceImpl构造器
UserServiceImpl类中初始化方法

10_Spring的IOC配置-bean对象创建方式

目标

  • 能够通过配置的spring资源创建bean对象

路径

  1. 方式一:直接配置
  2. 方式二:静态工厂
  3. 方式三:实例工厂

方式一:直接配置

<!-- 将UserService实现类装配到容器中 -->
<bean id="userService" class="com.itheima.spring.bean.UserServiceImpl"/>

通过bean标签的配置,spring会利用反射来创建这个对象并装配到容器中,通过反射创建这个对象时是默认使用类的无参构造方法来实例化bean的

  • 应用场景:在配置的时候,知道实现类的全限定名 (一般自己写bean)
  • 底层原理:无参构造 (要求类中必须有无参构造方法)
  • 缺点:开发者需要知道类名

方式二:静态工厂

除了通过调用bean的无参构造方法创建对象之外,spring还提供了两种工厂创建方式:

  1. 静态工厂:创建对象的方法是静态
  2. 实例工厂:创建对象的方法是非静态的 (仅了解)

使用静态工厂的形式创建bean :

<!-- 通过静态工厂方法创建对象并装配到容器中 -->
<bean id="beanId" class="FactoryClassName" factory-method="factoryMethodName"></bean>
  • 注意事项:
    1. class属性值,必须配置成静态工厂的类名
    2. factory-method属性值,设置为工厂中的静态方法名

代码示例:

  • UserService实现类
/*
  UserService实现类:UserServiceImpl2  
*/
public class UserServiceImpl2 implements UserService {
    private int number;

    //有参构造方法
    public UserServiceImpl2(int number) {
        this.number = number;
    }
    //无参构造方法
    pubic UserServiceImpl2(){
        
    }

    @Override
    public void save() {
        System.out.println("执行保存功能....");
    }
}
  • 工厂类
/*
    静态工厂: 方法是静态的
*/
public class StaticFactory {
    //静态方法
    public static UserService getBean(){
        //UserService userService = new UserServiceImpl2(10);
        UserService userService = new UserServiceImpl2();
        return userService;
    }
}
  • 配置文件
<?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="" class="">方式配置。可以使用:
        1. 静态工厂
        2. 实例工厂

        # 静态工厂的原理
    Class clazz =  Class.forName("com.itheima.spring.bean.factory.StaticFactory");
    Method getBean = clazz.getMethod("getBean");
    UserService service = getBean.invoke(null);
    map.put("userService2",service);
    -->
    <bean id="userService2"
          class="com.itheima.spring.bean.factory.StaticFactory"
          factory-method="getBean"/>

</beans>
  • 测试类
public class StaticFactoryTest {
    @Test
    public void testStaticFactoryNewObject(){
        //加载指定的xml配置文件
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

        //获取Spring容器中的资源
        UserService userService = (UserService) ctx.getBean("userService2");

        //调用方法
        userService.save();
    }
}

方式三:实例工厂 (了解)

使用实例工厂的形式创建bean :

<!-- 通过实例工厂方法创建对象并装配到容器中 -->
<bean id="beanId" factory-bean="factoryBeanId" factory-method="factoryMethodName"></bean>

注意事项:

  1. factory-bean属性值,设置为实例工厂的beanId

    • 使用实例工厂创建bean,首先要配置实例工厂的bean交由spring进行管理

      <!-- 实例工厂对象 -->
      <bean id="beanId" class="com.itheima.spring.bean.factory.InstanceFactory"/>
      
  2. factory-method属性值,设置为工厂中的非静态方法名

代码示例:

  • 工厂类
/*
 *   实例工厂: 方法是非静态
 * */
public class InstanceFactory {
    //非静态方法
    public UserService getBean() {
        UserService userService = new UserServiceImpl2();
        return userService;
    }
}
  • 配置文件
<?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">
    <!--
        # 实例工厂的原理
            clazz =  Class.forName("com.itheima.factory.InstanceFactory");
            if = clazz.newInstance();
            getBean =  clazz.getMethod("getBean")
            UserService service = getBean.invoke(if);
            map.put("userService3",service);
    -->
    <!-- 实例工厂对象 -->
    <bean id="if" class="com.itheima.spring.bean.factory.InstanceFactory"/>
    <!-- UserService对象 -->
    <bean id="userService3" factory-bean="if" factory-method="getBean"/>

</beans>
  • 测试类
public class InstanceFactoryTest {
    @Test
    public void testInstanceFactoryNewObject(){
        //加载指定的xml配置文件
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

        //获取Spring容器中的资源
        UserService userService = (UserService) ctx.getBean("userService3");

        //调用方法
        userService.save();
    }
}

小结

  • 在开发中,通常就是使用:直接装配方式
    • 要求:装配的类,必须有无参构造方法
  • 当自定义类没有无参构造方法时,通常使用:静态工厂装配bean

11_Spring的IOC配置-依赖注入

目标

  • 能够使用Spring的依赖注入给成员变量赋值

路径

  1. 依赖注入的介绍
  2. setter注入
  3. 构造器注入
  4. 集合类型数据注入

依赖注入的介绍

在我们之前书写的程序中,是通过控制反转(IOC),把对象的创建交给了Spring,由Spring容器创建bean对象。但是这种方式仅仅是降低了代码中的依赖关系,并不会完全消除依赖。例如:业务层要调用dao层的方法

//业务层
public class UserServiceImpl3 implements UserService {
    //dao层对象
    private UserDao userDao;//成员变量

    //无参构造方法
    public UserServiceImpl3(){
        //1.加载配置文件
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

        //2.获取Spring容器中的资源
        userDao = (UserDao) ctx.getBean("userDao");//仅仅只是让Spring创建bean对象,降低了依赖关系。  但还是需要自己书写代码接收Spring创建的bean对象。
    }

    //保存用户
    public void save(User user) {
        //调用dao层对象中的添加用户方法
        userDao.save(user);
    }
}

问题:能否不让程序员书写接收Spring创建bean对象的代码?

解决方案:依赖注入(DI => Dependency Injection)

  • 所谓的依赖注入,可以先简单的理解为由spring框架以解耦的方式将dao对象传递到业务层中,简称依赖注入

image-20220420183520937

结论:IOC与DI是同一件事,只是站在不同角度看待问题

setter注入

问题:常用的给类中成员变量赋值的方式有几种?

答案:2种。    1:setter方法、    2:构造方法

依赖注入 - setter注入方式:

<bean id="beanId" class="ClassName">
    <!-- 给bean对象中的成员赋值(依赖注入) -->
	<property name="propertyName" value="propertyValue" ref="beanId"/>
</bean>
  • property标签:
    • name:对应bean中的属性名,要求该属性必须提供可访问的setter方法
    • value:设定非引用类型(8大基本类型和String)属性对应的值。【不能与ref同时使用】
    • ref:设定引用类型属性对应bean的id。【不能与value同时使用】
  • 注意:一个bean可以有多个property标签

代码演示:

  • 业务类
//业务层
public class UserServiceImpl3 implements UserService {
    private int num; //基本类型
    private String name; //String类型
    private UserDao userDao; //dao层对象
    private Date birthday; //Date类型

    //无参构造方法
    public UserServiceImpl3(){
    }

    public void save(User user) {
        System.out.println("成员变量 num:"+num);
        System.out.println("成员变量 name:"+name);
        System.out.println("成员变量 birthday:"+birthday);
        
        //调用dao层对象中的添加用户方法
        userDao.save(user);
    }

    //setter&getter方法
    public int getNum() {
        return num;
    }
    public void setNum(int num) {
        this.num = num;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public UserDao getUserDao() {
        return userDao;
    }
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
    public Date getBirthday() {
        return birthday;
    }
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
}
  • 配置文件
<?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">
    <!--
        set注入
        1. 原理 : 空参构造 + set方法
           clazz = Class.forName("com.itheima.service.impl.UserServiceImpl3");
           service = class.newInstance(); //
           setName = clazz.getMethod("setName")
           setName.invoke(service,"zs");
           // service.setName("zs");

        2. 配置 : bean标签内子标签property
            1). name : bean中的属性名
            2). 值
                  value : 写基本类型、字符串、包装类
                  ref: 引用类型
    -->
    <!-- UserDao对象 -->
    <bean id="userDao" class="com.itheima.spring.bean.UserDao"/>
    <!-- 日期类型 -->
    <bean id="birthday" class="java.util.Date"/>
    <!-- UserService对象 -->
    <bean id="userService4" class="com.itheima.spring.bean.UserServiceImpl3">
        <!-- 注入属性值 -->
        <property name="num" value="100"/>
        <property name="name" value="黑马"/>
        <property name="birthday" ref="birthday"/>
        <property name="userDao" ref="userDao"/>
    </bean>

</beans>
  • 测试类
public class SetterTest {
    @Test
    public void testPropertySetter(){
        //加载指定的xml配置文件
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

        //获取Spring容器中的资源
        UserService userService = (UserService) ctx.getBean("userService4");

        //调用方法
        userService.save(new User());
    }
}

//输出结果:
成员变量 num:100
成员变量 name:黑马
成员变量 birthday:Wed Apr 20 19:04:35 CST 2021
UserDao => 执行添加用户的功能...

构造器注入

依赖注入 - 构造器注入方式:

<bean id="beanId" class="ClassName">
	<constructor-arg name="argsName" value="argsValue" ref="beanId"/>
</bean>
  • constructor-arg标签:
    • name:对应bean中的构造方法所携带的参数名
    • value:设定非引用类型构造方法参数对应的值。【不能与ref同时使用】
    • ref:设定引用类型构造方法参数对应bean的id。【不能与value同时使用】

代码演示:

  • 前置要求:类中的必须有对应的构造方法(带参数的构造方法)

  • 业务类

public class UserServiceImpl3 implements UserService {
    private int num; //基本类型
    private String name; //String类型
    private UserDao userDao; //dao层对象
    private Date birthday; //Date类型

    //有参构造方法
    public UserServiceImpl3(int num , String name, UserDao userDao, Date date){
        this.num = num;
        this.name = name;
        this.userDao= userDao;
        this.birthday = date;
    }
    //无参构造方法
    public UserServiceImpl3(){
    }

    public void save(User user) {
        System.out.println("成员变量 num:"+num);
        System.out.println("成员变量 name:"+name);
        System.out.println("成员变量 birthday:"+birthday);

        //调用dao层对象中的添加用户方法
        userDao.save(user);
    }
}
  • 配置文件
<?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">
  
    <!--
        构造器注入 (了解)
        1. 原理
           clazz = Class.forName("com.itheima.service.impl.UserServiceImpl3");
           contructor = clazz.getConstructor(String.class,int.class,UserDao.class,Date.class);
           service = contructor.newInstance("zs",18,userDao,myDate);
           map.put("userService44",service);

        2. 配置:bean标签的子标签constructor-arg
                name属性 : 构造方法中参数的名字
                value属性: 非引用类型值
                ref属性:   引用类型值
    -->
    <bean id="userDao" class="com.itheima.spring.bean.UserDao"/>
    <bean id="birthday" class="java.util.Date"/>
    <bean id="userService4" class="com.itheima.spring.bean.UserServiceImpl3">
        <constructor-arg name="num" value="100"/>
        <constructor-arg name="name" value="黑马"/>
        <constructor-arg name="userDao" ref="userDao"/>
        <!-- 构造方法中参数名:date -->
        <constructor-arg name="date" ref="birthday"/>
    </bean>

</beans>
  • 测试类
public class ConstructorTest {
    @Test
    public void testPropertyConstructor(){
        //加载指定的xml配置文件
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

        //获取Spring容器中的资源
        UserService userService = (UserService) ctx.getBean("userService4");

        //调用方法
        userService.save(new User());
    }
}
//输出结果:
成员变量 num:100
成员变量 name:黑马
成员变量 birthday:Wed Apr 20 19:28:42 CST 2021
UserDao => 执行添加用户的功能...

集合类型数据注入

依赖注入 - 集合类型数据注入:

  • 集合:List、Set、Map、Properties
<!-- List类型数据注入 -->
<bean id="beanId" class="className">
    <property name="成员变量名">
        <list>
             <value>元素</value>
        </list>
    </property>
</bean>

<!-- Set类型数据注入 -->
<bean id="beanId" class="className">
    <property name="成员变量名">
        <set>
            <value>元素</value>
        </set>
    </property>
</bean>

<!-- 数组类型数据注入 -->
<bean id="beanId" class="className">
    <property name="成员变量名">
         <array>
              <value>元素值</value>
         </array>
    </property>
</bean>


<!-- Map类型数据注入 -->
<bean id="beanId" class="className">
     <property name="成员变量名">
         <map>
             <entry key="key元素" value="value元素"/>
         </map>
     </property>
</bean>

<!-- Properties类型数据注入 -->
<bean id="beanId" class="className">
    <property name="成员变量名">
         <props>
              <prop key="key元素">value元素</prop>
         </props>
    </property>
</bean>

代码示例:

  • 业务类
public class UserServiceImpl4 implements UserService {
    private List list;//List集合
    private Set set;//Set集合
    private Map map;//Map集合
    private Properties properties;//属性集
    private int[] arrry;//数组

    //无参构造方法
    public UserServiceImpl4() {
    }
    @Override
    public void save(User user) {
        System.out.println("执行保存功能....");
        System.out.println("List集合:"+list);
        System.out.println("Set集合:"+set);
        System.out.println("Map集合:"+map);
        System.out.println("Properties集合:"+properties);
        System.out.println("数组:"+ Arrays.toString(arrry));
    }

    public List getList() {
        return list;
    }
    public void setList(List list) {
        this.list = list;
    }
    public Set getSet() {
        return set;
    }
    public void setSet(Set set) {
        this.set = set;
    }
    public Map getMap() {
        return map;
    }
    public void setMap(Map map) {
        this.map = map;
    }
    public Properties getProperties() {
        return properties;
    }
    public void setProperties(Properties properties) {
        this.properties = properties;
    }
    public int[] getArrry() {
        return arrry;
    }
    public void setArrry(int[] arrry) {
        this.arrry = arrry;
    }
}
  • 配置文件
<?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">
    <!--
     # 集合类型数据注入
       1. properties标签的name属性指定的是UserServiceImpl4中对应的成员变量名
       2. properties的子标签
           1). list : 声明该属性是List类型
           2). props : 声明该属性是Properties类型
           3). array : 声明该属性是数组类型
           4). set : 声明该属性是Set类型
           5). map : 声明该属性是Map类型

      原理:
         clazz = Class.forName("com.itheima.service.impl.UserServiceImpl5")
         service = clazz.newInstance();

         setList = service.getMethod("setList",List.class);

         List list = new ArrayList();
         list.add("zs");
         list.add("ls");
         list.add("ww");

         setList.invoke(service,list);// service.setList(list)
    -->
    <bean id="userService5" class="com.itheima.spring.bean.UserServiceImpl4">
        <!-- 注入:List集合 -->
        <property name="list">
            <list>
                <value>上海黑马</value>
                <value>北京黑马</value>
            </list>
        </property>
        <!-- 注入:Set集合 -->
        <property name="set">
            <set>
                <value>上海</value>
                <value>杭州</value>
            </set>
        </property>
        <!-- 注入:Map集合 -->
        <property name="map">
            <map>
                <entry key="sh" value="上海黑马程序员"/>
                <entry key="bj" value="北京黑马程序员"/>
            </map>
        </property>
        <!-- 注入:Properties属性集 -->
        <property name="properties">
            <props>
                <prop key="name">张三</prop>
                <prop key="age">20</prop>
            </props>
        </property>
        <!-- 注入:数组 -->
        <property name="arrry">
            <array>
                <value>100</value>
                <value>1000</value>
            </array>
        </property>
    </bean>

</beans>
  • 测试类
public class ContainerTest {
    @Test
    public void testPropertyContainer(){
        //加载指定的xml配置文件
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

        //获取Spring容器中的资源
        UserService userService = (UserService) ctx.getBean("userService5");

        //调用方法
        userService.save(new User());
    }
}
//输出结果:
执行保存功能....
List集合:[上海黑马, 北京黑马]
Set集合:[上海, 杭州]
Map集合:{sh=上海黑马程序员, bj=北京黑马程序员}
Properties集合:{age=20, name=张三}
数组:[100, 1000]

小结

依赖注入:给bean对象中的成员变量注入数据(由Spring IoC容器完成)

依赖注入的方式:

  1. Set方法注入

    • 通过property标签调用属性的setter方法将数据注入到目标类中
  2. 构造方法注入

    • 提供一个类的有参构造,通过construct-arg标签调用该有参构造将数据注入到目标类中
  3. 集合类型的注入

    • 通过对应的标签,可以给复杂类型的属性注入数据

12_Spring的IOC配置-EL表达式

目标

  • 能够在Spring的依赖注入中使用EL表达式

路径

  1. Spring的EL表达式介绍
  2. Spring的El表达式示例

Spring的EL表达式介绍

el : expression language 表达式语言

  • 含义: 就是数据引用

spring中el表达式:

  • {} //把指定的内容赋值给属性

  • ${} //用于加载外部文件中指定的Key值

spring依赖注入中EL表达式的书写格式:

<bean id="beanId" class="className">
    <property  name="成员变量名" value="EL表达式"/>
</bean>

  • 注意:所有成员变量的值不区分是否引用类型,统一使用value赋值

  • 示例:

    • 常量 : #{10} #{3.14} #

    • 引用bean : #

    • 引用bean属性 : #

    • 运算符支持 : #

    • 正则表达式支持 : #{user.name matches‘[a-z]{6,}’}

    • 集合支持 : #

Spring的El表达式示例

代码示例:

  • 业务类
//业务层
public class UserServiceImpl3 implements UserService {
    private int num; //基本类型
    private String name; //String类型
    private UserDao userDao; //dao层对象
    private Date birthday; //Date类型

    //无参构造方法
    public UserServiceImpl3(){
    }

    public void save(User user) {
        System.out.println("成员变量 num:"+num);
        System.out.println("成员变量 name:"+name);
        System.out.println("成员变量 birthday:"+birthday);

        //调用dao层对象中的添加用户方法
        userDao.save(user);
    }

    //setter&getter方法
    public int getNum() {
        return num;
    }
    public void setNum(int num) {
        this.num = num;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public UserDao getUserDao() {
        return userDao;
    }
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
    public Date getBirthday() {
        return birthday;
    }
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
}
  • 配置文件
<?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">
    <!--
        Spring EL
        1. ${表达式}
                  引入配置文件中的数据
        2. #{表达式}
                   强调的是把内容赋值给属性

            #{'字符串'}
            #{数字}
            #{beanId}
    -->
    <bean id="userDao" class="com.itheima.spring.bean.UserDao"/>
    <bean id="birthday" class="java.util.Date"/>
    <bean id="userService6" class="com.itheima.spring.bean.UserServiceImpl3">
        <!-- 使用EL表达式注入属性值 -->
        <property name="num" value="#{100}"/>
        <property name="name" value="#{'黑马'}"/>
        <property name="birthday" value="#{birthday}"/>
        <property name="userDao" value="#{userDao}"/>
    </bean>

</beans>
  • 测试类
public class SpringElDemo {
    @Test
    public void testSpringEl(){
        //加载指定的xml配置文件
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

        //获取Spring容器中的资源
        UserService userService = (UserService) ctx.getBean("userService6");

        //调用方法
        userService.save(new User());
    }
}
//输出结果:
成员变量 num:100
成员变量 name:黑马
成员变量 birthday:Wed Apr 20 21:25:41 CST 2021
UserDao => 执行添加用户的功能...

13_Spring的IOC配置-引入外部资源文件

目标

  • 能够通过读取外部资源文件,实现给bean对象的属性赋值

路径

  1. Spring中加载外部资源文件
  2. 示例:给bean对象属性注入外部资源文件中的数据

Spring中加载外部资源文件

Spring提供了读取外部properties文件的机制,使用读取到的数据为bean的属性赋值

操作步骤

  1. 准备外部properties文件

  2. 在XML中开启context命名空间支持

    xmlns:context="http://www.springframework.org/schema/context"
    
  3. 加载指定的properties文件

    <context:property-placeholder location="classpath:filename.properties"/>
    
  4. 使用加载的数据

    <property name="成员变量名" value="${propertiesName}"/>
    

注意事项:

  1. 如果需要加载所有的properties文件,可以使用*.properties表示加载所有的properties文件
  2. 读取数据使用${propertiesName}格式进行,其中propertiesName指properties文件中的属性名

示例:给bean对象属性注入外部资源文件中的数据

代码示例:

  • 外部资源文件(data.properties)

    image-20220420215659070

    name=heima
    num=10
    
  • 业务类

//业务层
public class UserServiceImpl3 implements UserService {
    private int num; //基本类型
    private String name; //String类型
    private UserDao userDao; //dao层对象
    private Date birthday; //Date类型

    //无参构造方法
    public UserServiceImpl3(){
    }

    public void save(User user) {
        System.out.println("成员变量 num:"+num);
        System.out.println("成员变量 name:"+name);
        System.out.println("成员变量 birthday:"+birthday);

        //调用dao层对象中的添加用户方法
        userDao.save(user);
    }

    //setter&getter方法
    public int getNum() {
        return num;
    }
    public void setNum(int num) {
        this.num = num;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public UserDao getUserDao() {
        return userDao;
    }
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
    public Date getBirthday() {
        return birthday;
    }
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
}
  • 配置文件
<?xml version="1.0" encoding="UTF-8"?>

<!--
    第1步:
        schema约束新增: 开启context命名空间支持

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

    <!-- 第2步:加载指定的properties文件 -->
    <context:property-placeholder location="classpath:data.properties"/>

    <bean id="userDao" class="com.itheima.spring.bean.UserDao"/>
    <bean id="birthday" class="java.util.Date"/>
    <bean id="userService7" class="com.itheima.spring.bean.UserServiceImpl3">
        <!--
          第3步: 使用外部资源文件中的数据
                 格式: ${外部文件中的key}
        -->
        <property name="num" value="${num}"/>
        <property name="name" value="${name}"/>
        <property name="birthday" value="#{birthday}"/>
        <property name="userDao" value="#{userDao}"/>
    </bean>

</beans>
  • 测试类
public class SpringPropertiesTest {
    @Test
    public void testSpringOuterProperties(){
        //加载指定的xml配置文件
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

        //获取Spring容器中的资源
        UserService userService = (UserService) ctx.getBean("userService7");

        //调用方法
        userService.save(new User());
    }
}
//输出结果:
成员变量 num:10
成员变量 name:heima
成员变量 birthday:Wed Apr 20 21:53:04 CST 2021
UserDao => 执行添加用户的功能...

小结

在Spring中,EL表达式有两种使用方式:

    • 把{ }中指定的内容,赋值给一个属性
  • $
    • 从外部资源文件中,获取数据,赋值给bean对象中的属性
    • { }中书写的是外部资源文件(.properties)中的key

标签:name,配置文件,Spring,day01,bean,UserService,public
From: https://www.cnblogs.com/-turing/p/17206348.html

相关文章

  • Spring-day02
    Spring-day0201_开启Spring注解目标能够设置Spring的注解扫描路径注解开发的意义在配置文件中开启Spring注解扫描注解开发的意义在Spring中除了可以使用xml......
  • Spring-day03
    Spring-day0301_Spring的AOP概述目标了解AOP存在的意义及方式路径AOP介绍AOP作用AOP优势Spring中AOP的实现方式在前面我们提到:Spring技术的两大核心就是Ioc(......
  • Kuboard安装并部署springcloud微服务项目
    Kuboard安装并部署springcloud微服务项目Kuboard是一款k8s的管理界面,我认为它有页面美观(颜值即正义)、操作简洁、系统配置要求不高、对新手友好的特点。开发者认为他们......
  • Spring-初始Spring
    Spring1、简介Spring:春天:----给软件行业带来了春天2002年,首次推出了Spring框架的雏形:interface21框架2004年3月24号诞生RodJohnson,SpringFramework创始人,......
  • Spring-IOC理论浅析
    IOC理论最开始时业务实现:UserDao接口UserDaoImpl实现类UserService业务接口UserServiceImpl业务实现类在我们之前的业务中,用户的需求可能会影响我们原来的代码,我们......
  • Spring-第一个Spring程序
    1、HelloSpring1、第一个Spring项目创建Spring配置文件XXX.xml(标准名称:ApplicationContext.xml)<?xmlversion="1.0"encoding="UTF-8"?><beansxmlns="http://www.spri......
  • Spring-DI(依赖注入)及Bean的作用域
    DI(依赖注入)1、构造器注入前面已经说过了2、set方式注入【重点】依赖注入:Set注入依赖:bean对象的创建依赖于容器注入:bean对象中的所有属性,由容器来注入【环境......
  • Spring-Bean的自动装配
    Bean的自动装配自动装配是Spring满足bean依赖的一种方式Spring会在上下文中自动寻找,并自动给bean装配属性在Spring中有三种装配的方式在xml中显式的配置在java中显......
  • springboot打包时遇到的问题
    第一个问题是Failedtoexecutegoalorg.apache.maven.plugins:maven-resources-plugin:3.3.0:resources(default-resources)onproject   我的springboot版本......
  • 2.HelloSpring
    2.HelloSpring思考问题?Hello对象是谁创建的?Hello对象是由Spring设置的Hello对象的属性是怎么设置的?Hello对象的属性是Spring容器设置的这个过程就叫控制反转......