四、Spring IoC实践和应用(基于注解方式管理 Bean)

news2025/2/2 11:06:07

本章概要

  • 基于注解方式管理 Bean
    • 实验一: Bean注解标记和扫描 (IoC)
    • 实验二: 组件(Bean)作用域和周期方法注解
    • 实验三: Bean属性赋值:引用类型自动装配 (DI)
    • 实验四: Bean属性赋值:基本类型属性赋值 (DI)
    • 实验五: 基于注解+XML方式整合三层架构组件

4.3 基于注解方式管理 Bean

4.3.1 实验一: Bean注解标记和扫描 (IoC)
4.3.1.1 注解理解

和 XML 配置文件一样,注解本身并不能执行,注解本身仅仅只是做一个标记,具体的功能是框架检测到注解标记的位置,然后针对这个位置按照注解标记的功能来执行具体操作。

本质上:所有一切的操作都是 Java 代码来完成的,XML 和注解只是告诉框架中的 Java 代码如何执行。
举例:元旦联欢会要布置教室,蓝色的地方贴上元旦快乐四个字,红色的地方贴上拉花,黄色的地方贴上气球。

在这里插入图片描述

班长做了所有标记,同学们来完成具体工作。墙上的标记相当于我们在代码中使用的注解,后面同学们做的工作,相当于框架的具体操作。

4.3.1.2 扫描理解

Spring 为了知道程序员在哪些地方标记了什么注解,就需要通过扫描的方式,来进行检测。然后根据注解进行后续操作。

4.3.1.3 准备Spring项目和组件
  1. 准备项目 spring-ioc-annotation-03

pom.xml

<dependencies>
    <!--spring context依赖-->
    <!--当你引入Spring Context依赖之后,表示将Spring的基础依赖引入了-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>6.0.6</version>
    </dependency>

    <!--junit5测试-->
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-api</artifactId>
        <version>5.3.1</version>
    </dependency>
</dependencies>
  1. 准备组件类

普通组件

/**
 * projectName: com.atguigu.ioc01
 *
 * description: 普通的组件
 */
public class CommonComponent {
}

Controller 组件

/**
 * projectName: com.atguigu.ioc01
 *
 * description: controller类型组件
 */
public class XxxController {
}

Service 组件

/**
 * projectName: com.atguigu.ioc01
 *
 * description: service类型组件
 */
public class XxxService {
}

Dao 组件

/**
 * projectName: com.atguigu.ioc01
 *
 * description: dao类型组件
 */
public class XxxDao {
}
4.3.1.4 组件添加标记注解
  1. 组件标记注解和区别Spring 提供了以下多个注解,这些注解可以直接标注在 Java 类上,将它们定义成 Spring Bean。
注解说明
@Component该注解用于描述 Spring 中的 Bean,它是一个泛化的概念,仅仅表示容器中的一个组件(Bean),并且可以作用在应用的任何层次,例如 Service 层、Dao 层等。 使用时只需将该注解标注在相应类上即可。
@Repository该注解用于将数据访问层(Dao 层)的类标识为 Spring 中的 Bean,其功能与 @Component 相同。
@Service该注解通常作用在业务层(Service 层),用于将业务层的类标识为 Spring 中的 Bean,其功能与 @Component 相同。
@Controller该注解通常作用在控制层(如SpringMVC 的 Controller),用于将控制层的类标识为 Spring 中的 Bean,其功能与 @Component 相同。

在这里插入图片描述

通过查看源码我们得知,@Controller、@Service、@Repository这三个注解只是在@Component注解的基础上起了三个新的名字。

对于 Spring 使用 IOC 容器管理这些组件来说没有区别,也就是语法层面没有区别。所以 @Controller、@Service、@Repository 这三个注解只是给开发人员看的,让我们能够便于分辨组件的作用。注意:虽然它们本质上一样,但是为了代码的可读性、程序结构严谨!我们肯定不能随便胡乱标记。

  1. 使用注解标记

普通组件

/**
 * projectName: com.atguigu.ioc01
 *
 * description: 普通的组件
 */
@Component
public class CommonComponent {
}

Controller 组件

/**
 * projectName: com.atguigu.ioc01
 *
 * description: controller类型组件
 */
@Controller
public class XxxController {
}

Service 组件

/**
 * projectName: com.atguigu.ioc01
 *
 * description: service类型组件
 */
@Service
public class XxxService {
}

Dao 组件

/**
 * projectName: com.atguigu.ioc01
 *
 * description: dao类型组件
 */
@Repository
public class XxxDao {
}
4.3.1.5 配置文件确定扫描范围
  • 情况1:基本扫描配置 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: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 https://www.springframework.org/schema/context/spring-context.xsd">
  <!-- 配置自动扫描的包 -->
  <!-- 1.包要精准,提高性能!
  2.会扫描指定的包和子包内容
  3.多个包可以使用,分割 例如: com.atguigu.controller,com.atguigu.service等
  -->
  <context:component-scan base-package="com.atguigu.ioc01"/>

</beans>
  • 情况2:指定排除组件
<!-- 情况二:指定不扫描的组件 -->
<context:component-scan base-package="com.atguigu.ioc01">

  <!-- context:exclude-filter标签:指定排除规则 -->
  <!-- type属性:指定根据什么来进行排除,annotation取值表示根据注解来排除 -->
  <!-- expression属性:指定排除规则的表达式,对于注解来说指定全类名即可 -->
  <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
  • 情况3:指定扫描组件
<!-- 情况三:仅扫描指定的组件 -->
<!-- 仅扫描 = 关闭默认规则 + 追加规则 -->
<!-- use-default-filters属性:取值false表示关闭默认扫描规则 -->
<context:component-scan base-package="com.atguigu.ioc01" use-default-filters="false">

  <!-- context:include-filter标签:指定在原有扫描规则的基础上追加的规则 -->
  <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
4.3.1.6 组件 BeanName 问题

在我们使用 XML 方式管理 bean 的时候,每个 bean 都有一个唯一标识——id 属性的值,便于在其他地方引用。现在使用注解后,每个组件仍然应该有一个唯一标识。
默认情况:类名首字母小写就是 bean 的 id。例如:SoldierController 类对应的 bean 的 id 就是 soldierController。
使用value属性指定:

@Controller(value = "tianDog")
public class SoldierController {
}

当注解中只设置一个属性时,value 属性的属性名可以省略:

@Service("smallDog")
public class SoldierService {
}
4.3.1.7 总结
  1. 注解方式 IoC 只是标记哪些类要被 Spring 管理
  2. 最终,我们还需要XML方式或者后面讲解Java配置类方式指定注解生效的包
  3. 现阶段配置方式为 注解 (标记)+ XML(扫描)
4.3.2 实验二: 组件(Bean)作用域和周期方法注解
4.3.2.1 组件周期方法配置
  1. 周期方法概念

我们可以在组件类中定义方法,然后当IoC容器实例化和销毁组件对象的时候进行调用!这两个方法称为生命周期方法!
类似于 Servlet 的init/destroy 方法,我们可以在周期方法完成初始化和释放资源等工作。

  1. 周期方法声明
<!-- jsr-250注解 Java提供的注解, spring提供了一个 @Resource  -->
<dependency>
    <groupId>jakarta.annotation</groupId>
    <artifactId>jakarta.annotation-api</artifactId>
    <version>2.1.1</version>
</dependency>
package com.atguigu.ioc02;

import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import org.springframework.stereotype.Component;


@Component
public class JavaBean {

    //周期方法要求: 方法命名随意,但是要求方法必须是 public void 无形参列表
    @PostConstruct //注解制指定初始化方法
    public void init() {
        // 初始化逻辑
        System.out.println("init");
    }

    @PreDestroy //注解指定销毁方法
    public void destory() {
        // 释放资源逻辑
        System.out.println("destory");
    }

}

4.3.2.2 组件作用域配置
  1. Bean作用域概念

<bean 标签声明Bean,只是将Bean的信息配置给SpringIoC容器!在IoC容器中,这些<bean标签对应的信息转成Spring内部 BeanDefinition 对象,BeanDefinition 对象内,包含定义的信息(id,class,属性等等)!
这意味着,BeanDefinition与类概念一样,SpringIoC容器可以可以根据BeanDefinition对象反射创建多个Bean对象实例。
具体创建多少个Bean的实例对象,由Bean的作用域Scope属性指定!

  1. 作用域可选值
取值含义创建对象的时机默认值
singleton在 IOC 容器中,这个 bean 的对象始终为单实例IOC 容器初始化时
prototype这个 bean 在 IOC 容器中有多个实例获取 bean 时

如果是在WebApplicationContext环境下还会有另外两个作用域(但不常用):

取值含义创建对象的时机默认值
request请求范围内有效的实例每次请求
session会话范围内有效的实例每次会话
  1. 作用域配置
package com.atguigu.ioc02;

import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;


@Component
// @Scope(scopeName = ConfigurableBeanFactory.SCOPE_SINGLETON) //单例,默认值
@Scope(scopeName = ConfigurableBeanFactory.SCOPE_PROTOTYPE) //多例  二选一
public class JavaBean {

    //周期方法要求: 方法命名随意,但是要求方法必须是 public void 无形参列表
    @PostConstruct //注解制指定初始化方法
    public void init() {
        // 初始化逻辑
        System.out.println("init");
    }

    @PreDestroy //注解指定销毁方法
    public void destory() {
        // 释放资源逻辑
        System.out.println("destory");
    }

}

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

    <context:component-scan base-package="com.atguigu.ioc02"/>

</beans>

SpringIocTest.java

@Test
public void testIoc_02(){
    //1.创建ioc容器
    ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-02.xml");

    JavaBean bean1 = applicationContext.getBean(JavaBean.class);
    JavaBean bean2 = applicationContext.getBean(JavaBean.class);

    System.out.println(bean1 == bean2);

    applicationContext.close();
}

在这里插入图片描述

4.3.3 实验三: Bean属性赋值:引用类型自动装配 (DI)
4.3.3.1 设定场景
  • SoldierController 需要 SoldierService
  • SoldierService 需要 SoldierDao 同时在各个组件中声明要调用的方法。
  • SoldierController 中声明方法
package com.atguigu.ioc03;

import org.springframework.stereotype.Controller;

@Controller(value = "tianDog")
public class SoldierController {

    private SoldierService soldierService;

    public void getMessage() {
        soldierService.getMessage();
    }

}
  • SoldierService 中声明方法
package com.atguigu.ioc03;

import org.springframework.stereotype.Service;

@Service("smallDog")
public class SoldierService {

    private SoldierDao soldierDao;

    public void getMessage() {
        soldierDao.getMessage();
    }
}
  • SoldierDao 中声明方法
package com.atguigu.ioc03;

import org.springframework.stereotype.Repository;

@Repository
public class SoldierDao {

    public void getMessage() {
        System.out.print("I am a soldier");
    }

}
4.3.3.2 自动装配实现
  1. 前提

参与自动装配的组件(需要装配、被装配)全部都必须在IoC容器中。
注意:不区分IoC的方式!XML和注解都可以!

  1. @Autowired注解

在成员变量上直接标记@Autowired注解即可,不需要提供setXxx()方法。以后我们在项目中的正式用法就是这样。

  1. 给 Controller 装配 Service
package com.atguigu.ioc03;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

@Controller(value = "tianDog")
public class SoldierController {

    @Autowired
    private SoldierService soldierService;

    public void getMessage() {
        soldierService.getMessage();
    }

}
  1. 给 Service 装配 Dao
package com.atguigu.ioc03;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service("smallDog")
public class SoldierService {

    @Autowired
    private SoldierDao soldierDao;

    public void getMessage() {
        soldierDao.getMessage();
    }
}

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

    <context:component-scan base-package="com.atguigu.ioc03" />

</beans>

SpringIocTest.java

    @Test
    public void testIoc_03(){
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-03.xml");

        SoldierController soldierController = applicationContext.getBean(SoldierController.class);

        //场景1: ioc容器中有一个UserService接口对应的实现类对象!
        soldierController.getMessage();
        applicationContext.close();
    }

在这里插入图片描述

4.3.3.3 @Autowired 注解细节
  1. 标记位置
  • 成员变量

这是最主要的使用方式!
与xml进行bean ref引用不同,他不需要有set方法!

@Service("smallDog")
public class SoldierService {
    
    @Autowired
    private SoldierDao soldierDao;
    
    public void getMessage() {
        soldierDao.getMessage();
    }
}
  • 构造器
@Controller(value = "tianDog")
public class SoldierController {
    
    private SoldierService soldierService;
    
    @Autowired
    public SoldierController(SoldierService soldierService) {
        this.soldierService = soldierService;
    }
}
  • setXxx()方法
@Controller(value = "tianDog")
public class SoldierController {

    private SoldierService soldierService;

    @Autowired
    public void setSoldierService(SoldierService soldierService) {
        this.soldierService = soldierService;
    }
}
  1. 工作流程

在这里插入图片描述

  • 首先根据所需要的组件类型到 IOC 容器中查找
    • 能够找到唯一的 bean:直接执行装配
    • 如果完全找不到匹配这个类型的 bean:装配失败
    • 和所需类型匹配的 bean 不止一个
      • 没有 @Qualifier 注解:根据 @Autowired 标记位置成员变量的变量名作为 bean 的 id 进行匹配
        • 能够找到:执行装配
        • 找不到:装配失败
      • 使用 @Qualifier 注解:根据 @Qualifier 注解中指定的名称作为 bean 的id进行匹配
        • 能够找到:执行装配
        • 找不到:装配失败
@Controller(value = "tianDog")
public class SoldierController {

    @Autowired
    @Qualifier(value = "maomiService222")
    // 根据面向接口编程思想,使用接口类型引入Service组件
    private ISoldierService soldierService;
}
4.3.3.4 佛系装配

给 @Autowired 注解设置 required = false 属性,表示:能装就装,装不上就不装。
但是实际开发时,基本上所有需要装配组件的地方都是必须装配的,用不上这个属性

@Controller(value = "tianDog")
public class SoldierController {

    // 给@Autowired注解设置required = false属性表示:能装就装,装不上就不装
    @Autowired(required = false)
    private ISoldierService soldierService;
}
4.3.3.5 扩展 JSR-250 注解 @Resource
  1. 理解JSR系列注解

JSR(Java Specification Requests)是Java平台标准化进程中的一种技术规范,而JSR注解是其中一部分重要的内容。
按照JSR的分类以及注解语义的不同,可以将JSR注解分为不同的系列,主要有以下几个系列:

  • JSR-175: 这个JSR是Java SE 5引入的,是Java注解最早的规范化版本,Java SE 5后的版本中都包含该JSR中定义的注解。主要包括以下几种标准注解:
    • @Deprecated: 标识一个程序元素(如类、方法或字段)已过时,并且在将来的版本中可能会被删除。
    • @Override: 标识一个方法重写了父类中的方法。
    • @SuppressWarnings: 抑制编译时产生的警告消息。
    • @SafeVarargs: 标识一个有安全性警告的可变参数方法。
    • @FunctionalInterface: 标识一个接口只有一个抽象方法,可以作为lambda表达式的目标。
  • JSR-250: 这个JSR主要用于在Java EE 5中定义一些支持注解。该JSR主要定义了一些用于进行对象管理的注解,包括:
    • @Resource: 标识一个需要注入的资源,是实现Java EE组件之间依赖关系的一种方式。
    • @PostConstruct: 标识一个方法作为初始化方法。
    • @PreDestroy: 标识一个方法作为销毁方法。
    • @Resource.AuthenticationType: 标识注入的资源的身份验证类型。
    • @Resource.AuthenticationType: 标识注入的资源的默认名称。
  • JSR-269: 这个JSR主要是Java SE 6中引入的一种支持编译时元数据处理的框架,即使用注解来处理Java源文件。该JSR定义了一些可以用注解标记的注解处理器,用于生成一些元数据,常用的注解有:
    • @SupportedAnnotationTypes: 标识注解处理器所处理的注解类型。
    • @SupportedSourceVersion: 标识注解处理器支持的Java源码版本。
  • JSR-330: 该JSR主要为Java应用程序定义了一个依赖注入的标准,即Java依赖注入标准(javax.inject)。在此规范中定义了多种注解,包括:
    • @Named: 标识一个被依赖注入的组件的名称。
    • @Inject: 标识一个需要被注入的依赖组件。
    • @Singleton: 标识一个组件的生命周期只有一个唯一的实例。
  • JSR-250: 这个JSR主要是Java EE 5中定义一些支持注解。该JSR包含了一些支持注解,可以用于对Java EE组件进行管理,包括:
    • @RolesAllowed: 标识授权角色
    • @PermitAll: 标识一个活动无需进行身份验证。
    • @DenyAll: 标识不提供针对该方法的访问控制。
    • @DeclareRoles: 声明安全角色。但是你要理解JSR是Java提供的技术规范,也就是说,他只是规定了注解和注解的含义,JSR并不是直接提供特定的实现,而是提供标准和指导方针,由第三方框架(Spring)和库来实现和提供对应的功能。
  • JSR-250 @Resource注解@Resource注解也可以完成属性注入。那它和@Autowired注解有什么区别?
    • @Resource注解是JDK扩展包中的,也就是说属于JDK的一部分。所以该注解是标准注解,更加具有通用性。(JSR-250标准中制定的注解类型。JSR是Java规范提案。)
    • @Autowired注解是Spring框架自己的。
    • @Resource注解默认根据Bean名称装配,未指定name时,使用属性名作为name。通过name找不到的话会自动启动通过类型装配。
    • @Autowired注解默认根据类型装配,如果想根据名称装配,需要配合@Qualifier注解一起用。
    • @Resource注解用在属性上、setter方法上。
    • @Autowired注解用在属性上、setter方法上、构造方法上、构造方法参数上。@Resource注解属于JDK扩展包,所以不在JDK当中,需要额外引入以下依赖:【高于JDK11或低于JDK8需要引入以下依赖】
<dependency>
  <groupId>jakarta.annotation</groupId>
  <artifactId>jakarta.annotation-api</artifactId>
  <version>2.1.1</version>
</dependency>
  1. @Resource使用
@Controller
public class XxxController {
    /**
     * 1. 如果没有指定name,先根据属性名查找IoC中组件xxxService
     * 2. 如果没有指定name,并且属性名没有对应的组件,会根据属性类型查找
     * 3. 可以指定name名称查找!  @Resource(name='test') == @Autowired + @Qualifier(value='test')
     */
    @Resource
    private XxxService xxxService;

    //@Resource(name = "指定beanName")
    //private XxxService xxxService;

    public void show(){
        System.out.println("XxxController.show");
        xxxService.show();
    }
}
4.3.4 实验四: Bean属性赋值:基本类型属性赋值 (DI)

@Value 通常用于注入外部化属性

  1. 声明外部配置

application.properties

catalog.name=MovieCatalog
  1. xml 引入外部配置 spring-04.xml
<!-- 引入外部配置文件-->
<context:component-scan base-package="com.atguigu.ioc04" />
<context:property-placeholder location="classpath:application.properties" />
  1. @Value 注解读取配置
package com.atguigu.ioc04;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
 * projectName: com.atguigu.components
 * <p>
 * description: 普通的组件
 */
@Component
public class CommonComponent {

    /**
     * 情况1: ${key} 取外部配置key对应的值!
     * 情况2: ${key:defaultValue} 没有key,可以给与默认值
     */
    @Value("${catalog:hahaha}")
    private String name;

    public String getName() {
        return name;
    }

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

SpringIocTest.java

@Test
public void testIoc_04(){
    ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-04.xml");

    CommonComponent commonComponent = applicationContext.getBean(CommonComponent.class);

    //场景1: ioc容器中有一个UserService接口对应的实现类对象!
    String name = commonComponent.getName();
    System.out.println(name);
    applicationContext.close();
}

在这里插入图片描述

4.3.5 实验五: 基于注解+XML方式整合三层架构组件
4.3.5.1 需求分析

搭建一个三层架构案例,模拟查询全部学生(学生表)信息,持久层使用JdbcTemplate和Druid技术,使用XML+注解方式进行组件管理!
在这里插入图片描述

4.3.5.2 数据库准备
create database studb;

use studb;

CREATE TABLE students (
  id INT PRIMARY KEY,
  name VARCHAR(50) NOT NULL,
  gender VARCHAR(10) NOT NULL,
  age INT,
  class VARCHAR(50)
);

INSERT INTO students (id, name, gender, age, class)
VALUES
  (1, '张三', '男', 20, '高中一班'),
  (2, '李四', '男', 19, '高中二班'),
  (3, '王五', '女', 18, '高中一班'),
  (4, '赵六', '女', 20, '高中三班'),
  (5, '刘七', '男', 19, '高中二班'),
  (6, '陈八', '女', 18, '高中一班'),
  (7, '杨九', '男', 20, '高中三班'),
  (8, '吴十', '男', 19, '高中二班');
4.3.5.3 项目准备
  1. 项目创建 spring-annotation-practice-04
  2. 依赖导入
<dependencies>
      <!--spring context依赖-->
      <!--当你引入SpringContext依赖之后,表示将Spring的基础依赖引入了-->
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context</artifactId>
          <version>6.0.6</version>
      </dependency>

      <!-- 数据库驱动和连接池-->
      <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
          <version>8.0.25</version>
      </dependency>

      <dependency>
          <groupId>com.alibaba</groupId>
          <artifactId>druid</artifactId>
          <version>1.2.8</version>
      </dependency>
      
      <dependency>
            <groupId>jakarta.annotation</groupId>
            <artifactId>jakarta.annotation-api</artifactId>
            <version>2.1.1</version>
       </dependency>

      <!-- spring-jdbc -->
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-jdbc</artifactId>
          <version>6.0.6</version>
      </dependency>

</dependencies>
  1. 实体类准备
public class Student {

    private Integer id;
    private String name;
    private String gender;
    private Integer age;
    private String classes;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public String getGender() {
        return gender;
    }

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

    public Integer getAge() {
        return age;
    }

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

    public String getClasses() {
        return classes;
    }

    public void setClasses(String classes) {
        this.classes = classes;
    }

    @Override
    public String toString() {
        return "Student{" +
        "id=" + id +
        ", name='" + name + '\'' +
        ", gender='" + gender + '\'' +
        ", age=" + age +
        ", classes='" + classes + '\'' +
        '}';
    }
}
4.3.5.4 三层架构搭建和实现
  1. 持久层
//接口
public interface StudentDao {

    /**
     * 查询全部学生数据
     * @return
     */
    List<Student> queryAll();
}
//实现类
@Repository
public class StudentDaoImpl implements StudentDao {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    /**
     * 查询全部学生数据
     * @return
     */
    @Override
    public List<Student> queryAll() {

        String sql = "select id , name , age , gender , class as classes from students ;";

        /*
          query可以返回集合!
          BeanPropertyRowMapper就是封装好RowMapper的实现,要求属性名和列名相同即可
         */
        List<Student> studentList = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(Student.class));

        return studentList;
    }
}
  1. 业务层
//接口
public interface StudentService {

    /**
     * 查询全部学员业务
     * @return
     */
    List<Student> findAll();

}
//实现类
@Service
public class StudentServiceImpl  implements StudentService {

    @Autowired
    private StudentDao studentDao;

    /**
     * 查询全部学员业务
     * @return
     */
    @Override
    public List<Student> findAll() {

        List<Student> studentList =  studentDao.queryAll();

        return studentList;
    }
}
  1. 表述层
@Controller
public class StudentController {

    @Autowired
    private StudentService studentService;

    public void  findAll(){
        List<Student> studentList =  studentService.findAll();
        System.out.println("studentList = " + studentList);
    }
}
4.3.5.5 三层架构IoC配置

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

  <!-- 导入外部属性文件 -->
    <context:property-placeholder location="classpath:jdbc.properties" />

    <!-- 配置数据源 -->
    <bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="url" value="${atguigu.url}"/>
        <property name="driverClassName" value="${atguigu.driver}"/>
        <property name="username" value="${atguigu.username}"/>
        <property name="password" value="${atguigu.password}"/>
    </bean>

    <bean class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="druidDataSource" />
    </bean>

    <!-- 扫描Ioc/DI注解 -->
    <context:component-scan base-package="com.atguigu.dao,com.atguigu.service,com.atguigu.controller" />

</beans>
4.3.5.6 数据库连接信息配置 jdbc.properties
atguigu.url=jdbc:mysql://localhost:3306/studb
atguigu.driver=com.mysql.cj.jdbc.Driver
atguigu.username=root
atguigu.password=root
4.3.5.7 运行测试
public class ControllerTest {

    @Test
    public  void testRun(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-ioc.xml");
        StudentController studentController = applicationContext.getBean(StudentController.class);
        studentController.findAll();
    }
}

在这里插入图片描述

4.3.5.8 注解 + XML IoC 方式问题总结
  1. 自定义类可以使用注解方式,但是第三方依赖的类依然使用XML方式!
  2. XML格式解析效率低!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1329060.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

01-基于粤嵌GEC6818实现屏幕的显示固定颜色进行自动切换

基于GEC6818实现屏幕颜色的切换 本文使用开发板GEC6818&#xff0c;实现屏幕显示特定颜色并且进行自动切换的功能。 文章目录 基于GEC6818实现屏幕颜色的切换一、 初始化开发板--&#xff08;开发板是新的则可以省略很多步骤&#xff09;1.1 **删除文件和文件夹**1.2 **查看磁盘…

STM32的以太网外设+PHY(LAN8720)使用详解(2):硬件设计

0 工具准备 1.野火 stm32f407霸天虎开发板 2.LAN8720数据手册 3.STM32F4xx中文参考手册1 PHY&#xff08;LAN8720&#xff09;硬件配置 1.1 硬件配置引脚说明 在LAN8720上电或复位时会读取一些特定引脚的电平&#xff0c;根据电平来进行硬件配置。LAN8720的引脚分布如下&…

在MongoDB中使用数组字段和子文档字段进行索引

本文主要介绍在MongoDB使用数组字段和子文档字段进行索引。 目录 MongoDB的高级索引一、索引数组字段二、索引子文档字段 MongoDB的高级索引 MongoDB是一个面向文档的NoSQL数据库&#xff0c;它提供了丰富的索引功能来加快查询性能。除了常规的单字段索引之外&#xff0c;Mong…

深度学习建模从零开始步骤流程

深度学习建模从零开始步骤流程 步骤如下&#xff1a; 环境准备三方库安装建模开发 环境准备 Anaconda安装&#xff1a; Anaconda下载网址&#xff0c;下载win10下的64位版本。 清华镜像站 下载完毕后点击安装&#xff0c;一直点确定或下一步 到上图点击 Just me&#xff…

基于SpringBoot的桃花峪滑雪场租赁系统 JAVA简易版

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 游客服务2.2 雪场管理 三、数据库设计3.1 教练表3.2 教练聘请表3.3 押金规则表3.4 器材表3.5 滑雪场表3.7 售票表3.8 器材损坏表 四、系统展示五、核心代码5.1 查询教练5.2 教练聘请5.3 查询滑雪场5.4 滑雪场预定5.5 新…

黑芝麻智能与亿咖通科技签署战略合作协议,深化协同助力智能驾驶量产落地

12月22日&#xff0c;全球智能汽车计算芯片引领者黑芝麻智能与全球出行科技企业亿咖通科技共同签署战略合作协议&#xff0c;通过深化合作&#xff0c;整合双方研发、产品和技术资源&#xff0c;联手打造领先智能驾驶系统解决方案&#xff0c;合力推进商业拓展和市场应用&#…

左值右值引用,完美转发

1.c98/03&#xff0c;类模板和函数模板只能含固定数量的模板参数&#xff0c;c11的新特性可以创建接受可变参数的函数模板和类模板 //Args是一个模板参数包&#xff0c;args是一个函数形参参数包 //声明一个参数包Args… args,这个参数包可以包括0到任意个模板参数 template&l…

Ignite数据流处理

数据流处理 #1.概述 Ignite提供了一个数据流API&#xff0c;可用于将大量连续的数据流注入Ignite集群&#xff0c;数据流API支持容错和线性扩展&#xff0c;并为注入Ignite的数据提供了至少一次保证&#xff0c;这意味着每个条目至少会被处理一次。 数据通过与缓存关联的数据…

【AI】YOLO学习笔记三-YOLOV5代码解析

YOLOv5是Glenn Jocher等人研发&#xff0c;它是Ultralytics公司的开源项目。YOLOv5根据参数量分为了n、s、m、l、x五种类型&#xff0c;其参数量依次上升&#xff0c;其效果也是越来越好。由于其代码是长期维护的且具有工程化的思维&#xff0c;所以方便应用在实际的项目中&…

【算法】使用二分查找解决算法问题:理解二分法思想,模板讲解与例题实践

文章目录 二分算法思想 / 性质 / 朴素模板二分查找的引入&#xff08;二段性&#xff09;704.二分查找 模板34.在排序数组中查找元素的第一个和最后一个位置 二分查找的前提条件 / 时间复杂度分析 算法题69.x的平方根35.搜索插入位置852.山脉数组的峰顶索引162.寻找峰值153.寻找…

Servlet-Filter 执行顺序测试

Servlet-Filter 执行顺序测试 对于 web.xml 文件注册过滤器这里就不多说了&#xff0c;就是谁声明的早&#xff0c;谁先被调用。因为在上面的过滤器信息最先被扫描到。 模型抽象 为了便于在实践中使用&#xff0c;结合部分底层原理&#xff0c;我们可以对 Filter 链的执行做…

【3D生成与重建】SSDNeRF:单阶段Diffusion NeRF的三维生成和重建

系列文章目录 题目&#xff1a;Single-Stage Diffusion NeRF: A Unified Approach to 3D Generation and Reconstruction 论文&#xff1a;https://arxiv.org/pdf/2304.06714.pdf 任务&#xff1a;无条件3D生成&#xff08;如从噪音中&#xff0c;生成不同的车等&#xff09;、…

PlatEMO UI 界面

&#x1f389; 博主相信&#xff1a; 有足够的积累&#xff0c;并且一直在路上&#xff0c;就有无限的可能&#xff01;&#xff01;&#xff01; &#x1f468;‍&#x1f393;个人主页&#xff1a; 青年有志的博客 &#x1f4af; Github 源码下载&#xff1a;https://github.…

【快速开发】使用SvelteKit

自我介绍 做一个简单介绍&#xff0c;酒架年近48 &#xff0c;有20多年IT工作经历&#xff0c;目前在一家500强做企业架构&#xff0e;因为工作需要&#xff0c;另外也因为兴趣涉猎比较广&#xff0c;为了自己学习建立了三个博客&#xff0c;分别是【全球IT瞭望】&#xff0c;【…

数据结构之进阶二叉树(二叉搜索树和AVL树、红黑树的实现)超详细解析,附实操图和搜索二叉树的实现过程图

绪论​ “生命有如铁砧&#xff0c;愈被敲打&#xff0c;愈能发出火花。——伽利略”&#xff1b;本章主要是数据结构 二叉树的进阶知识&#xff0c;若之前没学过二叉树建议看看这篇文章一篇掌握二叉树&#xff0c;本章的知识从浅到深的对搜索二叉树的使用进行了介绍和对其底层…

uniapp H5项目使用ucharts的Echart组件方式创建圆环

问题&#xff1a;没有报错但是图表不出来 【 调试了半天圆环图表没有不出来。是因为没有明示设置宽度与高度】 /* 请根据实际需求修改父元素尺寸&#xff0c;组件自动识别宽高 */ .charts-box { width: 100%; height: 300px; } 最终效果 先导入ucharts到项目 uniapp的项目…

hadoop集群的开启与关闭

背景 很久没完hadoopl,连怎么开启关闭都不会了qwq 1.进入安装hadoop的目录 我这里是已经进入了 2.开启集群 sbin/start-dfs.sh 3.关闭集群 sbin/stop-dfs.sh

NLP论文阅读记录 -| 对摘要评分的通用规避攻击

文章目录 前言0、论文摘要一、Introduction1.1目标问题1.2相关的尝试1.3本文贡献 二.相关工作三.本文方法3.1 问题表述3.2 对 ROUGE 和 METEOR 的白盒输入不可知攻击3.3BERTcore 上的黑盒通用触发器搜索 四 实验效果4.1数据集4.2 对比模型4.3实施细节4.4评估指标4.5 实验结果 五…

华为Harmony——ArkTs语言

文章目录 一、简单示例二、声明式UI描述创建组件无参有参数 配置属性配置事件配置子组件 三、自定义组件基本用法基本结构成员函数/变量 一、简单示例 我们以一个具体的示例来说明ArkTS的基本组成。如下图所示&#xff0c;当开发者点击按钮时&#xff0c;文本内容从“Hello Wo…

Python编写第一个APP自动化脚本,将脚本跑起来

一、前置说明 Python 使用 Appium 做 APP自动化的基本流程&#xff08;Android平台&#xff09;&#xff1a; 启动 Appium Serveradb 连接设备&#xff08;真机或模拟器&#xff09;uiautomatorviewer 连接设备&#xff0c;定位元素信息使用appium-python-client库&#xff0…