SSM - Springboot - MyBatis-Plus 全栈体系(八)

2023-11-05

第二章 SpringFramework

四、SpringIoC 实践和应用

4. 基于 配置类 方式管理 Bean

4.4 实验三:高级特性:@Bean 注解细节

4.4.1 @Bean 生成 BeanName 问题
  • @Bean 注解源码:
public @interface Bean {
    //前两个注解可以指定Bean的标识
    @AliasFor("name")
    String[] value() default {};
    @AliasFor("value")
    String[] name() default {};

    //autowireCandidate 属性来指示该 Bean 是否候选用于自动装配。
    //autowireCandidate 属性默认值为 true,表示该 Bean 是一个默认的装配目标,
    //可被候选用于自动装配。如果将 autowireCandidate 属性设置为 false,则说明该 Bean 不是默认的装配目标,不会被候选用于自动装配。
    boolean autowireCandidate() default true;

    //指定初始化方法
    String initMethod() default "";
    //指定销毁方法
    String destroyMethod() default "(inferred)";
}
  • 指定@Bean 的名称:
@Configuration
public class AppConfig {

  @Bean("myThing") //指定名称
  public Thing thing() {
    return new Thing();
  }
}
  • @Bean 注释注释方法。使用此方法在指定为方法返回值的类型的 ApplicationContext 中注册 Bean 定义。缺省情况下,Bean 名称与方法名称相同。下面的示例演示 @Bean 方法声明:
@Configuration
public class AppConfig {

  @Bean
  public TransferServiceImpl transferService() {
    return new TransferServiceImpl();
  }
}
  • 前面的配置完全等同于下面的 Spring XML:
<beans>
  <bean id="transferService" class="com.acme.TransferServiceImpl"/>
</beans>
4.4.2 @Bean 初始化和销毁方法指定
  • @Bean 注解支持指定任意初始化和销毁回调方法,非常类似于 Spring XML 在 bean 元素上的 init-method 和 destroy-method 属性,如以下示例所示:
public class BeanOne {

  public void init() {
    // initialization logic
  }
}

public class BeanTwo {

  public void cleanup() {
    // destruction logic
  }
}

@Configuration
public class AppConfig {

  @Bean(initMethod = "init")
  public BeanOne beanOne() {
    return new BeanOne();
  }

  @Bean(destroyMethod = "cleanup")
  public BeanTwo beanTwo() {
    return new BeanTwo();
  }
}
4.4.3 @Bean Scope 作用域
  • 可以指定使用 @Bean 注释定义的 bean 应具有特定范围。您可以使用在 Bean 作用域部分中指定的任何标准作用域。

  • 默认作用域为 singleton ,但可以使用 @Scope 注释覆盖此范围,如以下示例所示:

@Configuration
public class MyConfiguration {

  @Bean
  @Scope("prototype")
  public Encryptor encryptor() {
    // ...
  }
}
4.4.4 @Bean 方法之间依赖
4.4.4.1 准备组件
public class HappyMachine {

    private String machineName;

    public String getMachineName() {
        return machineName;
    }

    public void setMachineName(String machineName) {
        this.machineName = machineName;
    }
}
public class HappyComponent {
    //引用新组件
    private HappyMachine happyMachine;

    public HappyMachine getHappyMachine() {
        return happyMachine;
    }

    public void setHappyMachine(HappyMachine happyMachine) {
        this.happyMachine = happyMachine;
    }

    public void doWork() {
        System.out.println("HappyComponent.doWork");
    }

}
4.4.4.2 Java 配置类实现:
  • 方案 1:直接调用方法返回 Bean 实例:在一个 @Bean 方法中直接调用其他 @Bean 方法来获取 Bean 实例,虽然是方法调用,也是通过 IoC 容器获取对应的 Bean,例如:
@Configuration
public class JavaConfig {

    @Bean
    public HappyMachine happyMachine(){
        return new HappyMachine();
    }

    @Bean
    public HappyComponent happyComponent(){
        HappyComponent happyComponent = new HappyComponent();
        //直接调用方法即可!
        happyComponent.setHappyMachine(happyMachine());
        return happyComponent;
    }

}
  • 方案 2:参数引用法:通过方法参数传递 Bean 实例的引用来解决 Bean 实例之间的依赖关系,例如:
package com.alex.config;

import com.alex.ioc.HappyComponent;
import com.alex.ioc.HappyMachine;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * projectName: com.alex.config
 * description: 配置HappyComponent和HappyMachine关系
 */

@Configuration
public class JavaConfig {

    @Bean
    public HappyMachine happyMachine(){
        return new HappyMachine();
    }

    /**
     * 可以直接在形参列表接收IoC容器中的Bean!
     *    情况1: 直接指定类型即可
     *    情况2: 如果有多个bean,(HappyMachine 名称 ) 形参名称等于要指定的bean名称!
     *           例如:
     *               @Bean
     *               public Foo foo1(){
     *                   return new Foo();
     *               }
     *               @Bean
     *               public Foo foo2(){
     *                   return new Foo()
     *               }
     *               @Bean
     *               public Component component(Foo foo1 / foo2 通过此处指定引入的bean)
     */
    @Bean
    public HappyComponent happyComponent(HappyMachine happyMachine){
        HappyComponent happyComponent = new HappyComponent();
        //赋值
        happyComponent.setHappyMachine(happyMachine);
        return happyComponent;
    }

}

4.5 实验四:高级特性:@Import 扩展

  • @Import 注释允许从另一个配置类加载 @Bean 定义,如以下示例所示:
@Configuration
public class ConfigA {

  @Bean
  public A a() {
    return new A();
  }
}

@Configuration
@Import(ConfigA.class)
public class ConfigB {

  @Bean
  public B b() {
    return new B();
  }
}
  • 现在,在实例化上下文时不需要同时指定 ConfigA.class 和 ConfigB.class ,只需显式提供 ConfigB ,如以下示例所示:
public static void main(String[] args) {
  ApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigB.class);

  // now both beans A and B will be available...
  A a = ctx.getBean(A.class);
  B b = ctx.getBean(B.class);
}
  • 此方法简化了容器实例化,因为只需要处理一个类,而不是要求在构造期间记住可能大量的 @Configuration 类。

4.6 实验五:基于注解 + 配置类方式整合三层架构组件

4.6.1 需求分析
  • 搭建一个三层架构案例,模拟查询全部学生(学生表)信息,持久层使用 JdbcTemplate 和 Druid 技术,使用注解+配置类方式进行组件管理!

在这里插入图片描述

4.6.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.6.3 项目准备
4.6.3.1 项目创建
  • spring-java-practice-06
4.6.3.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>
4.6.3.3 实体类准备
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.6.4 三层架构搭建和实现
4.6.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;
    }
}
4.6.4.2 业务层
//接口
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;
    }
}
4.6.4.3 表述层
@Controller
public class StudentController {

    @Autowired
    private StudentService studentService;

    public void findAll(){
       List<Student> studentList =  studentService.findAll();
        System.out.println("studentList = " + studentList);
    }
}
4.6.5 三层架构 IoC 配置类
@Configuration
@ComponentScan(basePackages = "com.alex")
@PropertySource("classpath:jdbc.properties")
public class JavaConfig {

    @Value("${alex.url}")
    private String url;
    @Value("${alex.driver}")
    private String driver;
    @Value("${alex.username}")
    private String username;
    @Value("${alex.password}")
    private String password;

    @Bean(destroyMethod = "close")
    public DruidDataSource dataSource(){
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUrl(url);
        dataSource.setDriverClassName(driver);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        return dataSource;
    }

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

}
4.6.6 运行测试
public class ControllerTest {

    @Test
    public void testRun(){

        AnnotationConfigApplicationContext applicationContext =
                new AnnotationConfigApplicationContext(JavaConfig.class);

        StudentController studentController = applicationContext.getBean(StudentController.class);

        studentController.findAll();

    }
}
4.6.7 注解+配置类 IoC 方式总结
  • 完全摒弃了 XML 配置文件
  • 自定义类使用 IoC 和 DI 注解标记
  • 第三方类使用配置类声明方法+@Bean 方式处理
  • 完全注解方式(配置类+注解)是现在主流配置方式

5. 三种配置方式总结

5.1 XML 方式配置总结

  • 所有内容写到 xml 格式配置文件中
  • 声明 bean 通过<bean 标签
  • <bean 标签包含基本信息(id,class)和属性信息 <property name value / ref
  • 引入外部的 properties 文件可以通过<context:property-placeholder
  • IoC 具体容器实现选择 ClassPathXmlApplicationContext 对象

5.2 XML+注解方式配置总结

  • 注解负责标记 IoC 的类和进行属性装配
  • xml 文件依然需要,需要通过<context:component-scan 标签指定注解范围
  • 标记 IoC 注解:@Component,@Service,@Controller,@Repository
  • 标记 DI 注解:@Autowired @Qualifier @Resource @Value
  • IoC 具体容器实现选择 ClassPathXmlApplicationContext 对象

5.3 完全注解方式配置总结

  • 完全注解方式指的是去掉 xml 文件,使用配置类 + 注解实现
  • xml 文件替换成使用@Configuration 注解标记的类
  • 标记 IoC 注解:@Component,@Service,@Controller,@Repository
  • 标记 DI 注解:@Autowired @Qualifier @Resource @Value
  • <context:component-scan 标签指定注解范围使用@ComponentScan(basePackages = {“com.alex.components”})替代
  • <context:property-placeholder 引入外部配置文件使用@PropertySource({“classpath:application.properties”,“classpath:jdbc.properties”})替代
  • <bean 标签使用@Bean 注解和方法实现
  • IoC 具体容器实现选择 AnnotationConfigApplicationContext 对象

6. 整合 Spring5-Test5 搭建测试环境

6.1 整合测试环境作用

  • 好处 1:不需要自己创建 IOC 容器对象了
  • 好处 2:任何需要的 bean 都可以在测试类中直接享受自动装配

6.2 导入相关依赖

<!--junit5测试-->
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-api</artifactId>
    <version>5.3.1</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>6.0.6</version>
    <scope>test</scope>
</dependency>

6.3 整合测试注解使用

//@SpringJUnitConfig(locations = {"classpath:spring-context.xml"})  //指定配置文件xml
@SpringJUnitConfig(value = {BeanConfig.class})  //指定配置类
public class Junit5IntegrationTest {

    @Autowired
    private User user;

    @Test
    public void testJunit5() {
        System.out.println(user);
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SSM - Springboot - MyBatis-Plus 全栈体系(八) 的相关文章

随机推荐

  • ES6中Fetch的封装及使用,炒鸡简单~

    1 封装 http js class Ajax get url return new Promise resolve reject gt fetch url then res gt res json then data gt resolve
  • StyleCop 代码审查(VS插件)

    代码审查 StyleCop 介绍 下载 使用 自定义规则 源码 StyleCop简介 StyleCop是代码规范检查工具 Code Review 工具 它不仅仅检查代码格式 而是编码规范 包括命名和注释等 StyleCop可以帮助你更容易地
  • 【Matlab学习笔记】【数学形态学】数字图像处理(MATLAB版)冈萨雷斯第九章学习笔记

    1 形态学源于生物学 最初用于处理动植物的形状和结构 用于提取区域的形状 边界 骨骼或凸壳 形态学图像处理主要用于图像预处理和后处理 包括形态学滤波 细化和裁剪等 2 图像的形态学处理 由二值图像开始 逐步扩展到灰度图像 彩色图像 由简单到
  • 深入浅出SQL(3)-在Mac OS X上安装MySQL

    如何在Mac OS X上安装MySQL 下载安装包 打开官方下载地址 https dev mysql com downloads 选择合适版本的安装包 新建Oracle MySQL账户 email H10 登陆后下载安装包 安装 安装过程中
  • openGL GLSL GLSL.Refract & Reflect & Diffraction 反射、折射、衍射Fresnel Effect

    一 Refract Reflect Snell定律描述了光线从一个介质传播到另外一个介质时 入射角 折射角以及介质折射率的关系 通过snell定律 可以根据入射光的方向向量求取折射光的方向向量 Fresnel定律完善了光的衍射理论 当光线到
  • C++中GB2312字符串和UTF-8之间的转换

    在编程过程中需要对字符串进行不同的转换 特别是Gb2312和Utf 8直接的转换 在几个开源的魔兽私服中 很多都是老外开发的 而暴雪为了能 够兼容世界上的各个字符集也使用了UTF 8 在中国使用VS VS2005以上版本 开发基本都是使用G
  • MyBatis 配置多数据源

  • 解决FTP client 上传文件失败

    遇到的问题 在测试环境可以正常上传pdf 到了预发布环境虽然登陆成功了 但是上传的文件都是0KB 后来发现原来是运维添加了安全策略 需要在代码里添加以下方法 FTPClient enterLocalPassiveMode 调用FTPClie
  • 更换数据集

    以yolov5 deepsort的行人检测项目说一下怎么更换数据集 最终目标是要生成四个文件夹 一开始只有两个文件夹 1 标注文件 在终端输入lableme即可打开 尝试一下多分类 又是人 又是女人 如果win的lable导出的文件是xml
  • 安装SAPTrex

    1 下载安装包2 安装过程3 启动Admin工具C usr sap T02 TRX02TREXAdmin bat4 保存后 SM59会有一个新的T连接生成5 进去tcode SRMO 转载于 https blog 51cto com jen
  • android adb install apk的安装流程

    目录 一 PackageManagerService启动流程 二 apk adb安装流程 一 简介 1 Android上应用安装可以分为以下几种方式 通过adb命令安装 adb 命令包括adb push install 用户下载的Apk 通
  • 后端代码审计——PHP函数及PHP危险函数

    文章目录 PHP函数 1 自定义函数 1 1 函数语言结构 1 2 函数传参 1 3 函数调用 1 3 1 函数调用过程 1 4 变量范围 1 4 1 局部变量 1 4 2 全局变量 1 5 参数传递 1 5 1 按值传参 1 5 2 默认
  • 【程序员的财富自由之路】停更说明...

    停更原因 一个月前我发表了 程序员的财富自由之路 开篇序这篇文章 承蒙CSDN博客编辑的厚爱 将该专栏推荐到了专栏首页显示 因此带来了很多网友的关注 写那篇文章的时候 我信心满满 但惭愧的是 一个多月过去了 我仍然没有更新过专栏文章 让很多
  • 央行数字货币开始崛起:DC/EP正在领跑全球

    2020年8月24日 国际清算银行 以下简称BIS 发表题为 央行数字货币崛起 驱动因素 方法和技术 的工作报告 报告认为 央行数字货币 以下简称CBDC 将极大改变人类未来的支付以及生活方式 在全球诸多经济体中 中国人民银行的数字货币DC
  • golang exec 标准错误输出有 error 但是 err 是 nil

    golang 的 exec 模块 有可能标准错误输出会有类似 ERROR Incorrect date and time argument 2021 11 16 13 52 10 0000 UTC 但是 err 确是 nil package
  • \r \n 和strcat 笔记

    r 回车 ASCII码13 r gt return n 换行 ASCII码10 n gt newline 在Windows中 r 回车 回到当前行的行首 而不会换到下一行 n 换行 换到当前位置的下一行 而不会回到行首 描述 C 库函数 c
  • 详解如何使用AWS完善架构框架改造云上架构

    对于大部分项目来说 上云后的重构才刚开始 因为很多企业在上云之初 只是简单的把从前在物理服务器上的业务放到云上 并没有针对云环境做优化 没有充分到利用云服务的优势 上云之后 你需要重构业务架构 以提升企业的IT能力 比如通过架构优化让你的业
  • python爬虫学习(十二)xpath解析爬取58二手房

    xpath解析 最常用且便捷高效的解析方式 通用性 1 实例化一个etree的对象 且需要将被解析的页面源码数据加载到该对象中 2 调用etree对象中的xpath方法结合这xpath表示式实现标签的定位和内容的捕获 环境的安装 1 pip
  • 计算机网络常见题目

    题目地址 https www nowcoder com exam interview TCP和UDP的区别 回答要有条理 记起来好记 是什么 TCP是传输控制协议 UDP是用户数据报协议 它们都是属于传输层的协议 为应用层提供服务 而且他们
  • SSM - Springboot - MyBatis-Plus 全栈体系(八)

    第二章 SpringFramework 四 SpringIoC 实践和应用 4 基于 配置类 方式管理 Bean 4 4 实验三 高级特性 Bean 注解细节 4 4 1 Bean 生成 BeanName 问题 Bean 注解源码 publ