跳至主要內容

基于注解+配置类方式整合三层架构组件

Ek0wraith大约 5 分钟

项目实践:基于注解+配置类方式整合三层架构组件

1.需求案例:搭建一个三层架构案例,模拟查询全部用户(用户表)信息,持久层使用JdbcTemplate和Druid技术,使用注解方式进行组件管理,使用Java配置类代替XML配置文件。

2.项目架构:参考借鉴《Spring项目实践——IoC/DI案例》

3.数据模型:

CREATE TABLE user (

id INT(11) NOT NULL AUTO_INCREMENT,

username VARCHAR(50) NOT NULL,

password VARCHAR(50) NOT NULL,

PRIMARY KEY (id)

) ENGINE=INNODB AUTO_INCREMENT=1

DEFAULT CHARSET=utf8

4.实践要求:

(1) 参考借鉴《Spring项目实践——IoC/DI案例》实现

(2) 使用Junit5以上版本完成测试。

项目实现

项目目录

image-Spring-practice1
image-Spring-practice1

一、数据库

1、添加新的数据库(usermis):
SET NAMES utf8mb4;

SET FOREIGN_KEY_CHECKS = 0;



-- ----------------------------

-- Table structure for user

-- ----------------------------

DROP TABLE IF EXISTS user;

CREATE TABLE user (

 id int NOT NULL AUTO_INCREMENT,

 username varchar(50) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL,

 password varchar(50) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL,

 PRIMARY KEY (id) USING BTREE

) ENGINE = InnoDB AUTO_INCREMENT = 11 CHARACTER SET = utf8mb3 COLLATE = utf8mb3_general_ci ROW_FORMAT = Dynamic;



-- ----------------------------

-- Records of user

-- ----------------------------

INSERT INTO user VALUES (1, 'Peng Yuning', '8WvErMonB8');

INSERT INTO user VALUES (2, 'Takahashi Kasumi', 'YUEsievZJM');

INSERT INTO user VALUES (3, 'Bruce Rodriguez', 'oSKkZSv4wm');

INSERT INTO user VALUES (4, 'Lau Ching Wan', 'F0WfooyAy2');

INSERT INTO user VALUES (5, 'Lui Sze Kwan', 'Msou1bJ0vv');

INSERT INTO user VALUES (6, 'Ernest Crawford', '6BZpnzERaC');

INSERT INTO user VALUES (7, 'Juan Castillo', '8enHa9Ay1D');

INSERT INTO user VALUES (8, 'Fu Wing Kuen', 'kQbmCoKWxa');

INSERT INTO user VALUES (9, 'Valerie Harrison', 'MaIuoHAGHQ');

INSERT INTO user VALUES (10, 'Margaret Henderson', 'pBCv42yItl');



SET FOREIGN_KEY_CHECKS = 1;

二、项目创建

1、配置xml文件,导入Spring相关依赖和需求相关技术的依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>WebLesson</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>
    <modules>
        <module>Spring-Practice-01</module>
    </modules>

    <properties>
        <maven.compiler.source>19</maven.compiler.source>
        <maven.compiler.target>19</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>6.0.6</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api -->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>5.10.0</version>
            <scope>test</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/jakarta.annotation/jakarta.annotation-api -->
        <dependency>
            <groupId>jakarta.annotation</groupId>
            <artifactId>jakarta.annotation-api</artifactId>
            <version>2.1.1</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>6.0.6</version>
        </dependency>

        <!--数据库驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.33</version>
        </dependency>

        <!--数据库连接池-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.8</version>
        </dependency>

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

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.24</version>
        </dependency>

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

        <!--声明式事务依赖-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>6.0.6</version>
        </dependency>
    </dependencies>

</project>

2、构建三层架构,并编写相关代码,创建接口并重写方法,然后使用Spring框架标签进行托管。

User.java 实体类

package com.Ek0wraith.dao.pojo;
import lombok.Data;
/**
 * ClassName: User
 * Package: com.Ek0wraith.dao.pojo
 * Description:TODO
 *
 * @Author Ek0wraith
 * @Create 2024/5/8 15:56
 * @Version 1.0
 */
@Data
public class User {
    private Integer id;
    private String username;
    private String password;
}

UserDao.java 接口

package com.Ek0wraith.dao;

import com.Ek0wraith.dao.pojo.User;

import java.util.List;

/**
 * ClassName: UserDao
 * Package: com.Ek0wraith.dao
 * Description:TODO
 *
 * @Author Ek0wraith
 * @Create 2024/5/8 15:58
 * @Version 1.0
 */
public interface UserDao {
    List<User> queryAll();
}

UserDaoImpl.java

package com.Ek0wraith.dao;

import com.Ek0wraith.dao.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import java.util.List;

/**
 * ClassName: UserDaoImpl
 * Package: com.Ek0wraith.dao
 * Description:TODO
 *
 * @Author Ek0wraith
 * @Create 2024/5/8 15:56
 * @Version 1.0
 */
@Repository
public class UserDaoImpl implements UserDao{
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Override
    public List<User> queryAll() {
        String sql = "select * from users;";
        List<User> userList = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(User.class));
        return userList;
    }
}

UserService.java

package com.Ek0wraith.service;

import com.Ek0wraith.dao.pojo.User;

import java.util.List;

/**
 * ClassName: UserService
 * Package: com.Ek0wraith.service
 * Description:TODO
 *
 * @Author Ek0wraith
 * @Create 2024/5/8 16:13
 * @Version 1.0
 */
public interface UserService {
    List<User> findAll();
}

UserServiceImpl.java

package com.Ek0wraith.service;

import com.Ek0wraith.dao.UserDao;
import com.Ek0wraith.dao.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * ClassName: UserServiceImpl
 * Package: com.Ek0wraith.service
 * Description:TODO
 *
 * @Author Ek0wraith
 * @Create 2024/5/8 16:13
 * @Version 1.0
 */
@Service
public class UserServiceImpl implements UserService{
    @Autowired
    private UserDao userDao;

    @Override
    public List<User> findAll() {
        List<User> userList = userDao.queryAll();
        return userList;
    }
}

UserController.java

package com.Ek0wraith.controller;

import com.Ek0wraith.dao.pojo.User;
import com.Ek0wraith.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

import java.util.List;

/**
 * ClassName: UserController
 * Package: com.Ek0wraith.controller
 * Description:TODO
 *
 * @Author Ek0wraith
 * @Create 2024/5/8 16:12
 * @Version 1.0
 */
@Controller
public class UserController {
    @Autowired
    private UserService userService;
    public void findAll(){
        List<User> userList = userService.findAll();
        System.out.println("userList = " + userList);
    }
}

3、IoC配置

application.properties

college.name=usth

4、jdbc配置

jdbc.properties

Ek0wraith.url=jdbc:mysql://localhost:3306/usermis
Ek0wraith.driver=com.mysql.cj.jdbc.Driver
Ek0wraith.username=root
Ek0wraith.password=123456

5、基于配置类方式管理组件Bean(配置+注解)

CollegeConfiguration.java

package config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.annotation.Configuration;

/**
 * ClassName: Configuration
 * Package: com.Ek0wraith.config
 * Description:TODO
 *
 * @Author Ek0wraith
 * @Create 2024/5/8 16:30
 * @Version 1.0
 */


@Configuration
@PropertySource("classpath:application.properties")
@ComponentScan("demo")
public class CollegeConfiguration {
}

将Druid连接池对象存储到IoC容器

JavaConfiguration.java

package config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.*;
import org.springframework.jdbc.core.JdbcTemplate;

import javax.sql.DataSource;

/**
 * ClassName: JavaConfiguration
 * Package: com.Ek0wraith.config
 * Description:TODO
 *
 * @Author Ek0wraith
 * @Create 2024/5/8 16:37
 * @Version 1.0
 */

/**
 * 第三方类进行IoC管理,无法直接使用@Component相关注解。
 * 解决方案1:XML方式可以使用<bean>标签
 * 解决方案2:配置类方式,可以使用方法返回值+@Bean注解
 * @Bean注解用于指示方法实例化、配置和初始化要由Spring IoC容器管理的新对象。@Bean注解==<bean/>
 */

@Configuration
@PropertySource("classpath:jdbc.properties")
@ComponentScan(basePackages = {"com.Ek0wraith"})
public class JavaConfiguration {
    @Value("${Ek0wraith.url}")
    private String url;
    @Value("${Ek0wraith.driver}")
    private String driverClassName;
    @Value("${Ek0wraith.username}")
    private String username;
    @Value("${Ek0wraith.password}")
    private String password;

    @Bean
    public DataSource dataSource() {
        //Java代码实例化
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUrl(url);
        dataSource.setDriverClassName(driverClassName);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        return dataSource;
    }

    @Bean
    //@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public JdbcTemplate jdbcTemplate(DataSource dataSource){
        JdbcTemplate jdbcTemplate = new JdbcTemplate();
        jdbcTemplate.setDataSource(dataSource);
        return jdbcTemplate;
    }
}

三、Spring—Test测试

1、导入依赖组件

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

2、构建元件

College.java

package demo;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
 * ClassName: College
 * Package: com.Ek0wraith.demo
 * Description:TODO
 *
 * @Author Ek0wraith
 * @Create 2024/5/8 16:25
 * @Version 1.0
 */
@Component
public class College {
    @Value("${college.name:黑科技}")
    private String collegeName;
    public String getCollegeName() {
        return collegeName;
    }
    public void setCollegeName(String collegeName) {
        this.collegeName = collegeName;
    }
}

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">
    <context:property-placeholder location="classpath:application.properties"/>
    <context:component-scan base-package="demo"/>

</beans>

3、编写测试类

IntegrationTest1.java

package demo;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;

/**
 * ClassName: IntergrationTest1
 * Package: demo
 * Description:TODO
 *
 * @Author Ek0wraith
 * @Create 2024/5/8 16:52
 * @Version 1.0
 */

@SpringJUnitConfig(locations = {"classpath:spring-01.xml"})
public class IntegrationTest1 {
    @Autowired
    private College college;
    @Test
    public void test1(){
        System.out.println("college.getCollegeName() = " +
                college.getCollegeName());
    }
}

IntegrationTest2.java

package demo;

import com.Ek0wraith.controller.UserController;
import config.JavaConfiguration;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;

/**
 * ClassName: IntergrationTest2
 * Package: demo
 * Description:TODO
 *
 * @Author Ek0wraith
 * @Create 2024/5/8 16:55
 * @Version 1.0
 */

@SpringJUnitConfig(value = {JavaConfiguration.class})
public class IntegrationTest2 {
    @Autowired
    private UserController userController;

    @Test
    public void test2() {userController.findAll();}
}

四、执行测试,查看是否通过

1、IntegrationTest1运行结果

college.getCollegeName() = usth

Process finished with exit code 0

2、IntegrationTest2运行结果

信息: {dataSource-1} inited
userList = [User(id=1, username=Peng Yuning, password=8WvErMonB8), User(id=2, username=Takahashi Kasumi, password=YUEsievZJM), User(id=3, username=Bruce Rodriguez, password=oSKkZSv4wm), User(id=4, username=Lau Ching Wan, password=F0WfooyAy2), User(id=5, username=Lui Sze Kwan, password=Msou1bJ0vv), User(id=6, username=Ernest Crawford, password=6BZpnzERaC), User(id=7, username=Juan Castillo, password=8enHa9Ay1D), User(id=8, username=Fu Wing Kuen, password=kQbmCoKWxa), User(id=9, username=Valerie Harrison, password=MaIuoHAGHQ), User(id=10, username=Margaret Henderson, password=pBCv42yItl)]

Process finished with exit code 0

测试通过。