当前位置: 首页 > article >正文

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

目录

  • 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.kler.cn/a/371273.html

相关文章:

  • Golang | Leetcode Golang题解之第517题超级洗衣机
  • 【python GUI编码入门-03】掌握Tkinter如何高效绑定键盘和鼠标事件
  • asp.net WebForm GridView高级应用
  • 倪师学习笔记-天纪-易经八卦
  • Bug | 项目中数据库查询问题
  • Xcode文件默认存储位置-使用c++file保存文件默认路径以及设置为路径为当前项目路径
  • 短视频矩阵系统源代码开发|技术源代码部署/OEM贴牌搭建
  • electron知识整理和问题汇总
  • Data+AI时代下,如何做数字化转型升级!
  • 【MySQL】 运维篇—备份与恢复:使用mysqldump进行数据库备份与恢复
  • 开源一款前后端分离的企业级网站内容管理系统,支持站群管理、多平台静态化,多语言、全文检索的源码
  • IDEA连接EXPRESS版本的SQL server数据库
  • QT交互界面:实现按钮运行脚本程序
  • conda、virtualenv, venv分别是什么?它们之间有什么区别?
  • (青牛科技)双通道H桥电机驱动芯片GC8548 12V双通道全桥驱动芯片GC8548兼容LV8548
  • Skywalking教程一
  • HTML小阶段二维表和思维导图
  • Unity 两篇文章熟悉所有编辑器拓展关键类 (上)
  • 《机器学习by周志华》学习笔记-神经网络-03全局最小误差与局部极小误差
  • Java 中 JSONObject 遍历属性并删除的几种方法对比
  • [Vue warn]: Do not use built-in or reserved HTML elements as component id:
  • 分布式搜索引擎elasticsearch操作文档操作介绍
  • 在数学中体验逻辑与创造的乐趣20241029
  • Flutter动画容器
  • UI设计软件全景:13款工具助力创意实现
  • 正式入驻!上海斯歌BPM PaaS管理软件等产品入选华为云联营商品