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

第二章 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 {@Beanpublic 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 {@Beanpublic HappyMachine happyMachine(){return new HappyMachine();}@Beanpublic 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 {@Beanpublic 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)*/@Beanpublic HappyComponent happyComponent(HappyMachine happyMachine){HappyComponent happyComponent = new HappyComponent();//赋值happyComponent.setHappyMachine(happyMachine);return happyComponent;}}

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

  • @Import 注释允许从另一个配置类加载 @Bean 定义,如以下示例所示:
@Configuration
public class ConfigA {@Beanpublic A a() {return new A();}
}@Configuration
@Import(ConfigA.class)
public class ConfigB {@Beanpublic 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;}@Overridepublic 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 {@Autowiredprivate JdbcTemplate jdbcTemplate;/*** 查询全部学生数据* @return*/@Overridepublic 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 {@Autowiredprivate StudentDao studentDao;/*** 查询全部学员业务* @return*/@Overridepublic List<Student> findAll() {List<Student> studentList =  studentDao.queryAll();return studentList;}
}
4.6.4.3 表述层
@Controller
public class StudentController {@Autowiredprivate 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)@Beanpublic JdbcTemplate jdbcTemplate(DataSource dataSource){JdbcTemplate jdbcTemplate = new JdbcTemplate();jdbcTemplate.setDataSource(dataSource);return jdbcTemplate;}}
4.6.6 运行测试
public class ControllerTest {@Testpublic 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 {@Autowiredprivate User user;@Testpublic void testJunit5() {System.out.println(user);}
}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Mendeley在linux中无法打开APPimage

原因:FUSE 库为用户空间程序提供了一个接口&#xff0c;可以将虚拟文件系统导出到 Linux 内核。由于缺少这个关键库&#xff0c;AppImage 无法按预期工作。 1 安装fuse,打开终端,输入命令 sudo apt install libfuse2 输入用户密码结,果如下 2 确保APPimage作为程序运行 右击…

docker 获取Nvidia 镜像 | cuda |cudnn

本文分享如何使用docker获取Nvidia 镜像&#xff0c;包括cuda10、cuda11等不同版本&#xff0c;cudnn7、cudnn8等&#xff0c;快速搭建深度学习环境。 1、来到docker hub官网&#xff0c;查看有那些Nvidia 镜像 https://hub.docker.com/r/nvidia/cuda/tags?page2&name11.…

【计算机视觉 | 图像模型】常见的计算机视觉 image model(CNNs Transformers) 的介绍合集(五)

文章目录 一、MoCo v3二、AmoebaNet三、Residual Multi-Layer Perceptrons四、FractalNet五、LV-ViT六、RepVGG七、Transformer in Transformer八、SimpleNet九、SpineNet十、Bottleneck Transformer十一、ZFNet十二、DetNet十三、Invertible Rescaling Network十四、SNet十五、…

SVN 索引版本与打包版本号不匹配

今天突然遇到了一个问题&#xff0c;SVN上传不了&#xff0c;错误提示如下&#xff1a; 解决方法&#xff1a; 1.其实&#xff0c;这是SVN库不小心搞坏了&#xff0c;只能重新再创建一个SVN仓库了。

Redis:分布式锁误删原因分析

一、线程阻塞 例如&#xff0c;线程一获取分布式锁&#xff0c;但是线程一阻塞时间过长&#xff0c;导致锁超时释放。此时线程二获取分布式锁。当线程一阻塞结束后&#xff0c;释放分布式锁&#xff0c;但是释放的却是线程二的锁。此时线程二就不安全了&#xff0c;线程三也可…

Linux下修改jar包中的配置文件application.conf

文件位置 jar包文件工程目录 打包后解压jar包目录 提取和上传 jar tf XXX.jar # 获取包内文件 application.conf是jar包的配置文件&#xff0c;如果修改需要 提取文件 jar xf my-app.jar application.conf 修改后上传文件 jar uf my-app.jar application.conf

解决开了burp suite ,火狐访问不了其他网站的问题

问题描述&#xff1a; 有软件正在阻止 Firefox 安全地连接至此网站 www.baidu.com 很像是一个安全&#xff08;连接加密&#xff09;的网站&#xff0c;但我们未能与它建立安全连接。这个问题是由 PortSwigger CA 所造成&#xff0c;它是您的计算机或您所在网络中的软件。 您…

为什么Proteus串口无法正常显示

我以前就可以正常显示&#xff0c;但是最近一段时间&#xff0c;发现串口无法正常显示&#xff0c;试了很多办法都不行&#xff0c; 然后今天干好有点时间就刷了个机&#xff0c;然后居然就好了&#xff0c; 这就说明&#xff1a;Proteus不正常可能是病毒破坏了某个文件导致异…

HSRP(热备份路由选择协议)的概念,原理与配置实验

作者&#xff1a;Insist-- 个人主页&#xff1a;insist--个人主页 梦想从未散场&#xff0c;传奇永不落幕&#xff0c;持续更新优质网络知识、Python知识、Linux知识以及各种小技巧&#xff0c;愿你我共同在CSDN进步 目录 一、了解HSRP协议 1. 什么是HSRP协议 2、HSRP协议的…

java和fastjson

1.java是如何跨平台通信的 java--->class字节码--->jvm虚拟机运行 2.使因为jvm只会读文件名 如果不一致 则无法找到文件 3.main 函数说明java代码的接口 被使用 4.java和class后缀的区别 java是当前编写的代码文件 class是编译后的文件 5.void 没有返回值 这…

Django系列:Django简介与MTV架构体系概述

Django系列 Django简介与MTV架构体系概述 作者&#xff1a;李俊才 &#xff08;jcLee95&#xff09;&#xff1a;https://blog.csdn.net/qq_28550263 邮箱 &#xff1a;291148484163.com 本文地址&#xff1a;https://blog.csdn.net/qq_28550263/article/details/132890054 【介…

Canny图像算法仿真

目录 一、简要说明 1.1 算法流程 第一步&#xff0c;图像降噪。 第二步&#xff0c;计算图像梯度&#xff0c;得到可能边缘。 第三步&#xff0c;非极大值抑制。 第四步&#xff0c;双阈值筛选。 1.2 验证流程&#xff1a; 二、操作步骤 第一步&#xff1a;获取图像 …

代码随想录算法训练营第48天|198. 打家劫舍,213. 打家劫舍 II,337. 打家劫舍 III

198. 打家劫舍 你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋。每间房内都藏有一定的现金&#xff0c;影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统&#xff0c;如果两间相邻的房屋在同一晚上被小偷闯入&#xff0c;系统会自动报警。 给定一个代表每个…

国产洗碗机打响超越战

“征服世界的将是这样一些人&#xff1a;开始的时候&#xff0c;他们试图找到梦想中的乐园。最终&#xff0c;当他们无法找到时&#xff0c;就亲自创造了它。”诺贝尔文学奖获得者萧伯纳的这句话&#xff0c;适用于许多中国行业和企业&#xff0c;洗碗机就是其中之一。 对热爱…

Zabbix监控平台部署流程

Zabbix WEB、Zabbix Server、Zabbix Database放在一台服务器&#xff1b;&#xff08;192.168.10.12&#xff09;Zabbix Agent部署在被监控服务器上 &#xff08;192.168.10.11&#xff09;Zabbix Porxy 单独部署在一台服务器上&#xff08;被监控服务器少于500台可以不部署&am…

C#: 未能加载文件或程序集“xxx“

导入数据时&#xff0c;发生了异常&#xff0c;错误日志如下&#xff1a; 2023-09-11 09:20:49,304 [125] FATAL [(null)] - NPOI.POIXMLException ---> System.Reflection.TargetInvocationException: 调用的目标发生了异常。 ---> System.IO.FileLoadException: 未能加…

矿山边坡安全监测及预警系统解决方案

1.建设背景 近年来&#xff0c;矿山安全问题一直受到国家和社会的高度关注。为了全面提升矿山安全生产水平&#xff0c;国家矿山安全监察局和各省级非煤矿山安全监管部门开展了一项重大举措&#xff1a;推广并实施露天矿山边坡监测系统。 矿山边坡和排土场安全是露天矿山安全生…

第2章_瑞萨MCU零基础入门系列教程之面向过程与面向对象

本教程基于韦东山百问网出的 DShanMCU-RA6M5开发板 进行编写&#xff0c;需要的同学可以在这里获取&#xff1a; https://item.taobao.com/item.htm?id728461040949 配套资料获取&#xff1a;https://renesas-docs.100ask.net 瑞萨MCU零基础入门系列教程汇总&#xff1a; ht…

使用C#开发163邮件发送功能

创建SMTP服务器&#xff08;发送邮件需要SMTP服务器代发&#xff09; 这里介绍创建网易SMTP&#xff08;SMTP是邮件通讯格式&#xff09;服务器&#xff1a; 1.先注册一个163网易邮箱 2.注册成功后登陆该邮箱 3.在该邮箱中找到设置>POP3/SMTP/IMAP点击进入&#xff0c;如下…

【C语言】每日一题(半月斩)——day2

目录 一.选择题 1、以下程序段的输出结果是( ) 2、若有以下程序&#xff0c;则运行后的输出结果是&#xff08; &#xff09; 3、如下函数的 f(1) 的值为&#xff08; &#xff09; 4、下面3段程序代码的效果一样吗( ) 5、对于下面的说法&#xff0c;正确的是&#xf…