【Spring框架】Spring框架的开发方式

news2024/11/27 22:27:20

目录

  • Spring框架开发方式
    • 前言
    • 具体案例
      • 导入依赖
      • 创建数据库表结构
      • 创建实体类
      • 编写持久层接口和实现类
      • 编写业务层接口和实现类
      • 配置文件的编写
    • IoC注解开发
      • 注解开发入门(半注解)
      • IoC常用注解
      • Spring纯注解方式开发
    • Spring整合JUnit测试

Spring框架开发方式

前言

Spring开发主要依赖的就是IoC控制反转思想,将对象的创建权利移交给Spring框架,对各个模块之间进行解耦,实现方式就是DI——依赖注入,这里不清楚的可以看【Spring框架】Spring核心思想IoC以及依赖注入DI详解-CSDN博客这篇文章。

具体案例

我们创建我们项目的大致结构:实体类+业务层+持久层+测试类,这里我们为了清楚的理解Spring框架的开发方式,在持久层方面我们不引入MyBatis进行数据注入,而是选择原始的JDBC程序。好了我们先创建一个最普通的Maven项目,并引入我们的必要依赖(不会创建Maven项目可以看:【Maven】一篇带你了解Maven项目管理工具-CSDN博客):

导入依赖

<dependencies>
    <!-- Spring核心 -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.0.2.RELEASE</version>
    </dependency>
    <!-- slf4j接口https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>2.0.16</version>
    </dependency>
    <!-- log4j核心https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core -->
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>
        <version>2.24.0</version>
    </dependency>
    <!-- log4j2绑定到slf4j接口进行实现https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-slf4j-impl -->
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-slf4j2-impl</artifactId>
        <version>2.24.0</version>
        <scope>test</scope>
    </dependency>
    <!-- JUnit测试 -->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
    <!--Druid连接池-->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.1.10</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/com.mysql/mysql-connector-j -->
    <dependency>
        <groupId>com.mysql</groupId>
        <artifactId>mysql-connector-j</artifactId>
        <version>8.4.0</version>
    </dependency>
</dependencies>

创建数据库表结构

create database spring_db;
use spring_db;
create table account(
    id int primary key auto_increment,
    name varchar(40),
    money double
)character set utf8 collate utf8_general_ci;

insert into account(name,money) values('aaa',1000);
insert into account(name,money) values('bbb',1000);
insert into account(name,money) values('ccc',1000);

创建实体类

public class Account {

    private Integer id;
    private String name;
    private Double money;

    public Account() {
    }

    public Account(String name, Double money, Integer id) {
        this.name = name;
        this.money = money;
        this.id = id;
    }

    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 Double getMoney() {
        return money;
    }
    public void setMoney(Double money) {
        this.money = money;
    }

    @Override
    public String toString() {
        return "Account{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", money=" + money +
                '}';
    }
}

这里我们创建一个简单的账户类,和我们的数据库表结构向对应,有id、姓名、余额三个属性。

编写持久层接口和实现类

接口

public interface AccountDao {
    // 查询所有账户
    List<Account> findAll();
}

实现类

这里和之前没有引入Spring框架的时候是有区别的,我们可以将数据库连接池对象的创建权利移交给Spring框架,我们只需要在持久层注入连接池对象就可以进行使用,不需要再去new一个对象,我们来看一下对比:

在没有引入Spring之前:

public class AccountDaoImpl implements AccountDao {
    /**
     * 查询所有的数据
     * @return
     */
    @Override
    public List<Account> findAll() {
        // 手动创建连接池对象
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql:///spring_db");
        dataSource.setUsername("root");
        dataSource.setPassword("root");
        // 业务逻辑
        System.out.println("业务逻辑...");
        return list;
    }
}

我们通过手动创建链接池对象的方式进行数据库连接,也就是new一个新的连接池对象。

引入Spring之后:

public class AccountDaoImpl implements AccountDao {
    // 注入连接池对象
    private DataSource dataSource;
    public void setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    /**
     * 查询所有的数据
     * @return
     */
    @Override
    public List<Account> findAll() {

        /*
        不再使用手动的方式进行创建连接池对象
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName("com.mysql.jc.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql:///spring_db");
        dataSource.setUsername("root");
        dataSource.setPassword("root");
        */

        System.out.println("业务逻辑...");
        return list;
    }
}

在引入Spring之后,我们只需要通过Spring注入bean对象就可以了,不需要每次创建新的持久层实现类的时候都去重复连接数据库。

编写业务层接口和实现类

public interface AccountService {
    // 查询所有用户
    List<Account> findAll();
}

同样的,在这里我们不需要再手动去创建持久层对象,我们只需要通过Spring框架创建对象,并进行依赖注入,就可以完成此功能:

public class AccountServiceImpl implements AccountService {
    // 依赖注入
    private AccountDao accountDao;
    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }

    /**
     * 查询所有的数据
     */
    @Override
    public List<Account> findAll() {
        return accountDao.findAll();
    }
}

现在我们的业务层和持久层逻辑都已经编写好了,并注入了相关依赖,但是我们这些依赖去哪里拿呢?我们需要一个配置文件:applicationConfig.xml,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:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
                    http://www.springframework.org/schema/beans
                    http://www.springframework.org/schema/beans/spring-beans.xsd
                    http://www.springframework.org/schema/context
                    http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- Spring配置数据源 -->
    <!-- 这里是将数据源的实例化交给Spring容器管理 -->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/spring_db?serverTimezone=UTC"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </bean>
    <!--管理bean-->
    <bean id="accountService" class="com.qcby.service.Impl.AccountServiceImpl">
        <property name="accountDao" ref="accountDao" />
    </bean>
    <bean id="accountDao" class="com.qcby.dao.Impl.AccountDaoImpl">
        <property name="dataSource" ref="dataSource" />
    </bean>
</beans>

最后我们编写我们的测试类,执行测试:

public class AccountServiceTest {
    @Test
    public void run1(){
        // 通过读取我们的配置文件
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
       	// 获取到对象
        AccountService accountService = (AccountService) ac.getBean("accountService");
        // 调用方法
        List<Account> list = accountService.findAll();
        for (Account account : list) {
            System.out.println(account);
        }
    }
}

测试结果:

在这里插入图片描述

以上我们就完成了使用Spring框架来对项目的管理。

IoC注解开发

注解开发入门(半注解)

Spring框架通过配置文件来管理我们移交的对象,我们同样也可以丢弃配置文件,使用springframework提供的注解来进行开发,比配置文件的方式更便捷,不需要在配置文件中再去配置SpringBean

再简单编写一个案例,不再添加实体类和持久层,这里我只写一个业务层的接口和实现类:

接口:

public interface RoomService {
    void hello();
}

实现类:

在我们需要Spring管理的类上添加@Component注解,这个注解的作用就相当于将这个类创建对象的权利移交给Spring框架去管理,也就是想当于我们配置文件中的:<bean id="rs" class="com.xxx.RoomService" />

@Component(value = "rs")
public class RoomServiceImpl implements RoomService {
    @Override
    public void hello() {
        System.out.println("Hello IOC注解...");
    }
}

开启注解扫描

我们加入了注解,但是此时我们的Spring框架并没有读取到,我们需要在配置文件中加入开启注解扫描,扫描我们加入注解的类所在的包:

<!--开启注解扫描 com.qcby 所有的包中的所有的类 -->
<context:component-scan base-package="com.qcby" />

如果不开启,就会提示我们找不到名为rs的这个SpringBean对象:

在这里插入图片描述

编写测试方法进行测试:

public class AnnotationTest {
    /**
     * 测试注解创建Bean对象
     */
    @Test
    public void run1() {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        RoomService roomService = (RoomService) applicationContext.getBean("rs");
        roomService.hello();
    }
}

在这里插入图片描述

IoC常用注解

注解说明
@Component用于实例化Bean对象 作用于实体类
@Controller用于实例化Bean对象 作用于web层
@Service用于实例化Bean对象 作用于service层
@Repository用于实例化Bean对象 作用于dao层
@Autowired使用在字段上用于根据类型依赖注入
@Qualifier必须和@Autowired一起使用用于根据名称进行依赖注入
@Resource相当于@Autowired+@Qualifier,使用name属性,按照名称进行注入
@Value注入普通属性
@Scope标注Bean的作用范围 声明Spring创建对象的模式 单例singleton|多例prototype
@PostConstruct使用在方法上标注该方法是Bean的初始化方法 相当于init-method
@PreDestroy使用在方法上标注该方法是Bean的销毁方法 destroy-method

Spring纯注解方式开发

纯注解的方式是微服务架构开发的主要方式,所以非常重要。纯注解的目的就是要舍弃臃肿的配置文件,用相同作用的配置类进行代替。

首先编写我们的实体类:

@Component
public class Order {
    @Value("小明")
    private String name;
    @Value("1000")
    private Integer money;

    public String getName() {
        return name;
    }

    public Integer getMoney() {
        return money;
    }

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

编写持久层接口和实现类:

public interface OrderDao1 {
    void saveOrder(String name,Integer money);
}
@Component(value = "odi")
public class OrderDao1Impl implements OrderDao1 {
    // 注入dataSource
    @Autowired
    @Qualifier(value = "dataSource1")
    private DataSource dataSource;

    @Override
    public void saveOrder(String name,Integer money) {

        Connection connection = null;
        PreparedStatement stmt = null;
        ResultSet rs = null;
        int num;

        try {
            connection = dataSource.getConnection();
            String sql = "insert into account(name,money) values(?,?)";
            stmt = connection.prepareStatement(sql);
            stmt.setString(1, name);
            stmt.setInt(2, money);
            num = stmt.executeUpdate();
            if (num > 0) {
                System.out.println("插入数据成功");
            } else {
                System.out.println("插入数据失败");
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

编写业务层接口和实现类:

public interface OrderService1 {
    void saveOrder();
}
@Component(value = "aa")
public class OrderService1Impl implements OrderService1 {
    @Autowired
    @Qualifier(value = "odi")
    private OrderDao1 orderDao1;

    @Autowired
    @Qualifier(value = "order")
    private Order order;

    private String name;
    private Integer money;

    // 这里要延迟加载一下,不然会报空指针异常
    // 因为在注入order的时候,其中的name和money都还没注入进来
    @PostConstruct
    public void init() {
        this.name = order.getName();
        this.money = order.getMoney();
    }

    @Override
    public void saveOrder(){
        orderDao1.saveOrder(name, money);
    }
}

编写配置类:

@Configuration
@ComponentScan(value = "com.qcby")
public class SpringConfig {
    @Bean("dataSource1")
    public DataSource createDataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/spring_db?serverTimezone=UTC");
        dataSource.setUsername("root");
        dataSource.setPassword("20020322");
        return dataSource;
    }
}

这里使用@Configuration进行声明,声明这是一个配置类,并且用@ComponentScan注解对包进行扫描,最后编写测试类

// 加载我们的配置类,代替application.xml文件
@ContextConfiguration(classes = SpringConfig.class)
public class demo1Test {
    @Test
    public void run(){
		ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
		OrderService1 orderService = (OrderService1)applicationContext.getBean("aa");
        orderService.saveOrder();
    }
}

Spring整合JUnit测试

可以看到在测试类中,每次测试一个方法,我们都需要进行配置文件或者是配置类的读取,然后再通过依赖注入的方式获取到对象,最后通过对象对方法进行调用。Spring提供了整合Junit单元测试的技术,可以简化测试开发。

我们通过引入以下依赖,使用我们的Spring框架整合JUnit测试

<!-- Spring整合JUnit测试 -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>5.0.2.RELEASE</version>
    <scope>test</scope>
</dependency>

我们通过在测试类上添加注解:@RunWith(SpringJUnit4ClassRunner.class)来整合我们的JUnit测试,这个写法是固定的,当然你也可以通过配置文件的方式,在配置文件中添加对应的测试对象即可:

// 整合JUnit测试
@RunWith(SpringJUnit4ClassRunner.class)
// 加载我们的配置类,代替application.xml文件
@ContextConfiguration(classes = SpringConfig.class)
public class demo1Test {
	
    // 测试对象注入
    @Autowired
    private OrderService1 orderService;

    @Test
    public void run(){
//        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
//        OrderService1 orderService = (OrderService1)applicationContext.getBean("aa");
        orderService.saveOrder();
    }
}

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

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

相关文章

Mac开发环境配置- Shell/Homebrew/ruby

前言 从 macOS Catalina 开始&#xff0c;Mac 使用 zsh 作为默认登录 Shell 和交互式 Shell。当然你也可以修改默认Shell&#xff0c;但一般没这个必要。而实际开发中经常会遇到一些环境问题导致的报错&#xff0c;下面我们就讲一下一些常用库的环境配置以及原理。 一、Homeb…

苹果转向 Apple Silicon,Intel Mac 的支持时限倒计时

苹果已完成将 Mac 过渡至自家研发的 Apple Silicon 芯片&#xff0c;在过渡期间&#xff0c;苹果迅速停止对 Intel Mac 的新版本 macOS 的支持。 苹果通常为大多数设备提供约 5 年的软件更新。仍在使用 Intel 芯片的 Mac 机型包括&#xff1a; 2019 年款 Mac Pro2018 年款 Ma…

C++ TensorRT yolov8推理 CUDA核函数加速前处理

目录 效果 4K视频 CPU前处理效果 4K视频 CUDA核函数前处理效果 2K视频 CUDA核函数前处理效果 1080P 视频 CUDA核函数前处理效果 模型 电脑环境 项目 代码 下载 效果 C TensorRT yolov8推理 CUDA核函数加速前处理 4K视频 CPU前处理效果 4K视频 CUDA核函数前处理效果 …

自动化测试覆盖率提升的关键步骤

自动化测试覆盖不足的问题可以通过增加测试用例的数量和质量、引入代码覆盖率分析工具、加强团队的测试意识和技能、优化测试框架和工具、自动化测试与手动测试相结合等方式来解决。其中&#xff0c;引入代码覆盖率分析工具是关键&#xff0c;它可以帮助我们精准地识别未被测试…

STM32-Cube定时器TIM

一、内部时钟源 1、创建项目 File → New → STM32 project选择STM32F103C8T6单片机&#xff0c;命名TIM 2、配置单片机 1.打开USART1&#xff0c;方便我们与电脑连接查看数据 开启UART1并开启中断。 2、设置时钟源 开启外部高速晶振 将时钟频率设置为72MHz 设置调试模…

TCP全连接队列与 tcpdump 抓包

&#x1f351;个人主页&#xff1a;Jupiter. &#x1f680; 所属专栏&#xff1a;计算机网络高效通关之路 欢迎大家点赞收藏评论&#x1f60a; 目录 listen第二个参数详解 全连接队列与半连接队列半开放连接队列&#xff08;SYN队列&#xff09;全连接队列&#xff08;接受队列…

构建灵活、高效的HTTP/1.1应用:探索h11库

文章目录 构建灵活、高效的HTTP/1.1应用&#xff1a;探索h11库背景这个库是什么&#xff1f;如何安装这个库&#xff1f;库函数使用方法使用场景常见的Bug及解决方案总结 构建灵活、高效的HTTP/1.1应用&#xff1a;探索h11库 背景 在现代网络应用中&#xff0c;HTTP协议是基础…

Linux 安装MySQL(Cenots版本)

在Linux下安装mysql有很多方法&#xff0c;比如说&#xff1a; 压缩包解压&#xff08;一般为tar.gz&#xff09; 编译好的安装包&#xff08;RPM、DPKG等&#xff09; 在线安装&#xff08;YUM、APT等&#xff09; 在centos环境中&#xff0c;我们一般都用yum源安装。 一 删除…

2. Flink快速上手

文章目录 1. 环境准备1.1 系统环境1.2 安装配置Java 8和Scala 2.121.3 使用集成开发环境IntelliJ IDEA1.4 安装插件2. 创建项目2.1 创建工程2.1.1 创建Maven项目2.1.2 设置项目基本信息2.1.3 生成项目基本框架2.2 添加项目依赖2.2.1 添加Flink相关依赖2.2.2 刷新项目依赖3. 编写…

Docker使用-在Maven里面配置阿里云容器镜像仓库

准备环境 1.安装Dockerdesktop 参考文章&#xff1a;Docker Desktop安装 2.Windows 环境 3.IdeaMaven 4.阿里云容器镜像仓库.阿里云容器镜像仓库 5.SpringBoot 例子 通过网盘分享的文件&#xff1a;springboot-docker-demo.zip 链接: https://pan.baidu.com/s/1MD0uI1HG9SjYv…

群控系统服务端开发模式-应用开发-业务架构逻辑开发Redis封装

Redis是现代互联网开发世界不可缺少的一部分&#xff0c;比如登录token过期时间、系统配置等场所必用。 一、安装Redis扩展 composer require predis/predis 二、设置Redis参数 在根目录下config文件夹中找到cache.php文件&#xff0c;然后在stores数组下追加redis配置&#…

【机器学习】揭秘XGboost:高效梯度提升算法的实践与应用

目录 &#x1f354; XGBoost 原理 1.1 目标函数确定和树的复杂度介绍 1.2 XGBoost目标函数的推导 1.3 泰勒公式展开 1.4 化简目标函数 1.5 问题再次转换 1.6 对叶子结点求导 1.7 XGBoost的回归树构建方法 &#x1f354; XGBoost API 2.1 通用参数 2.2 Booster 参数 …

太速科技-430-基于RFSOC的8路5G ADC和8路10G的DAC PCIe卡

430-基于RFSOC的8路5G ADC和8路10G的DAC PCIe卡 一、板卡概述 板卡使用Xilinx的第三代RFSOC系列&#xff0c;单颗芯片包含8路ADC和DAC&#xff0c;64-bit Cortex A53系列4核CPU&#xff0c;Cortex-R5F实时处理核&#xff0c;以及大容量FPGA。 对主机接口采用PCIe Gen3x…

SpringBoot篇(运维实用篇 - 临时属性)

目录 一、临时属性设置 1. 简介 2. 属性加载优先级 那是否还有其他的配置方式呢&#xff1f; 3. 知识小结 二、开发环境中使用临时属性 1. 如何操作 2. 知识小结 3. 思考 三、配置文件分类 1. 简介 2. 4个级别 3. 为什么设计多种配置文件&#xff1f; 一个典型的应…

基于SSM+微信小程序的汽车维修管理系统(汽车5)

&#x1f449;文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1、项目介绍 基于SSM微信小程序的汽车维修管理系统实现了三个角色&#xff1a;管理员、员工、用户。 1、管理员实现了首页、管理员管理员、员工管理、用户管理、车辆信息管理、配件管理等 2、员工实…

【51 Pandas+Pyecharts | 深圳市共享单车数据分析可视化】

文章目录 &#x1f3f3;️‍&#x1f308; 1. 导入模块&#x1f3f3;️‍&#x1f308; 2. Pandas数据处理2.1 读取数据2.2 查看数据信息2.3 处理起始时间、结束时间2.4 增加骑行时长区间列2.5 增加骑行里程区间列 &#x1f3f3;️‍&#x1f308; 3. Pyecharts数据可视化3.1 各…

海亮科技亮相第84届中国教装展 尽显生于校园 长于校园教育基因

10月25日&#xff0c;第84届中国教育装备展示会&#xff08;以下简称“教装展”&#xff09;在昆明滇池国际会展中心开幕。作为国内教育装备领域规模最大、影响最广的专业展会&#xff0c;本届教装展以“数字赋能教育&#xff0c;创新引领未来”为主题&#xff0c;为教育领域新…

Mac 电脑 使用sudo创建项目后,给了读写权限,仍报权限问题

问题&#xff1a;sudo创建的项目&#xff0c;都已经改成读写权限了&#xff0c;但是修改项目中的内容还是报没权限。 原因&#xff1a;当你使用 sudo 创建项目时。这是因为 sudo 会以 root 用户的身份创建文件和目录&#xff0c;这些文件和目录默认属于 root 用户&#xff0c;…

vue封装信号强度

图标下载链接: https://pan.baidu.com/s/1828AidkCKU1KTkw1SvBwQg?pwd4k7n 共五格信号 信号5为绿色&#xff0c;信号4为绿色&#xff0c;信号3为黄色&#xff0c;信号2为黄色&#xff0c;信号1为红色&#xff0c;信号0为灰色。 子组件 /components/SignalStrength/index.vu…

【JavaScript】入门详解

JavaScript 作为 Web 开发的基石&#xff0c;赋予了网页动态交互的能力。本文将深入浅出地讲解 JavaScript 的核心概念&#xff0c;并结合最新用法进行详细解释和示例。 1. JavaScript 简介 JavaScript 是一种解释型脚本语言&#xff0c;也称弱类型语言&#xff0c;最初设计用…