5、Spring_DI注解开发

DI 注解开发

1.目前面临问题

  • 建立 mapper

    public interface EmployeeMapper {
        void save();
    }
    
  • 建立 mapper 实现类

    @Repository
    public class EmployeeMapperImpl implements EmployeeMapper {
        public void save(){
            System.out.println("保存员工信息");
        }
    }
    
  • 建立 service

    public interface IEmployeeService {
        void save();
    }
    
  • 建立 service 实现类

    @Service
    public class EmployeeServiceImpl implements IEmployeeService {
    
        private EmployeeMapper employeeMapper;
    
        public void setEmployeeMapper(EmployeeMapper employeeMapper){
            this.employeeMapper = employeeMapper;
        }
        public void save() {
            employeeMapper.save();
        }
    }
    
  • 设置配置类

    @Configuration
    @ComponentScan("cn.sycoder.di.di01")
    public class DiConfig {
    }
    
  • 出现空指针异常

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oSHnV3L7-1692700773739)(picture/image-20221028160214170.png)]

2.使用类型注入

  • @Autowired按照类型注入

  • 通过构造器注入

    @Autowired
    public EmployeeServiceImpl(EmployeeMapper employeeMapper) {
        this.employeeMapper = employeeMapper;
    }
    
  • 通过setter 方法注入

    @Autowired
    public void setEmployeeMapper(EmployeeMapper employeeMapper) {
        this.employeeMapper = employeeMapper;
    }
    
  • 直接在属性上使用(是以后用得最多的)

    @Service
    public class EmployeeServiceImpl implements IEmployeeService {
    
        @Autowired
        private EmployeeMapper employeeMapper;
    
        public void save() {
            employeeMapper.save();
        }
    }
    
    • 注意:不提供setter 方法以及构造器是使用反射创建对象的

      @Test
          public void autowired() throws Exception {
              final Class<?> aClass = Class.forName("cn.sycoder.di.di01.service.impl.EmployeeServiceImpl");
              final Object o = aClass.newInstance();
              final Field[] fields = aClass.getDeclaredFields();
              AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(DiConfig.class);
              final EmployeeMapper bean = context.getBean(EmployeeMapper.class);
              for (Field field : fields) {
                  field.setAccessible(true);
                  field.set(o,bean);
              }
              final EmployeeServiceImpl service = (EmployeeServiceImpl) o;
              service.save();
          }
      
    • 根据类型注入必须只有一个实现类,否则会报错,添加名称也不行

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZJHcdvtU-1692700773741)(picture/image-20221028161616168.png)]

  • 属性required=false,如果找不到不会报错

3.使用名称注入

  • @Autowired & @Qualifier

  • @Autowired & @Qualifier必须同时使用,缺一不可

  • 解决刚才出现两个实现类没法注入的问题

  • 配置mapper 并且指定实现类的名称

    public interface EmployeeMapper {
        void save();
    }
    
    @Repository("empMapper2")
    public class EmployeeMapperImpl implements EmployeeMapper {
        public void save(){
            System.out.println("保存员工信息");
        }
    }
    
    @Repository("empMapper1")
    public class EmployeeMapperImpl1 implements EmployeeMapper{
        public void save() {
            System.out.println("save");
        }
    }
    
  • 注入的时候使用名称注入

    @Service
    public class EmployeeServiceImpl implements IEmployeeService {
    
        @Autowired(required = false)
        @Qualifier("empMapper1")
        private EmployeeMapper employeeMapper;
    
        public void save() {
            employeeMapper.save();
        }
    
    }
    

4.简单数据类型注入

  • @Value

    @Component
    public class DbProperties {
        
        @Value("sy")
        private String username;
        @Value("123456")
        private String password;
        
    }
    
  • 硬编码,太垃圾了,需要改成动态

5.注解读取配置文件参数

  • @Value

  • 修改配置类

    @Configuration
    @ComponentScan("cn.sycoder.di.di01")
    @PropertySource("db.properties")
    public class DiConfig {
    }
    
  • 修改获取方式使用 ${} 的方式

    @Component
    public class DbProperties {
    
        @Value("${username}")
        private String username;
        @Value("${password}")
        private String password;
    
        public void test(){
            System.out.println(username + ":" + password);
        }
    }
    

5.1@PropertySource

  • @PropertySource 加载配置文件

  • 位置:配置类上

  • 作用导入配置文件

  • 对于多个配置文件

    @Configuration
    @ComponentScan("cn.sycoder.di.di01")
    @PropertySource({"db.properties","xx.properties"})
    public class DiConfig {
    }
    

6.注解配置第三方bean

6.1配置 druid

  • 添加依赖

    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.2.8</version>
    </dependency>
    
  • 先添加配置类 SpringConfig

    @Configuration
    public class SpringConfig {
    
    
        public DataSource dataSource(){
            final DruidDataSource source = new DruidDataSource();
            source.setUsername("root");
            source.setPassword("123456");
            source.setDriverClassName("com.mysql.cj.jdbc.Driver");
            source.setUrl("jdbc:mysql://localhost:3306/mybatis");
            return source;
        }
    
    }
    
  • 传统做法存在硬编码,DataSource 并且没有交给 spring 管理,每次都需要重新新建 DataSource ,并不存在单例一说

    @Test
        public void testDruid(){
            AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
            final SpringConfig bean = context.getBean(SpringConfig.class);
            System.out.println(bean.dataSource());
        }
    

6.2@Bean 配置 druid

  • 使用@Bean 交给 spring 管理

    @Configuration
    public class SpringConfig {
    
        @Bean
        public DataSource dataSource(){
            final DruidDataSource source = new DruidDataSource();
            source.setUsername("root");
            source.setPassword("123456");
            source.setDriverClassName("com.mysql.cj.jdbc.Driver");
            source.setUrl("jdbc:mysql://localhost:3306/mybatis");
            return source;
        }
    
    }
    
  • 修改配置的硬编码改成软编码

    @Configuration
    @PropertySource("druidDb.properties")
    public class SpringConfig {
        @Value("${jdbc.username}")
        private String username;
        @Value("${jdbc.password}")
        private String password;
        @Value("${jdbc.url}")
        private String url;
        @Value("${jdbc.driverClassName}")
        private String driver;
    
        @Bean
        public DataSource dataSource(){
            final DruidDataSource source = new DruidDataSource();
            source.setUsername(username);
            source.setPassword(password);
            source.setDriverClassName(driver);
            source.setUrl(url);
            return source;
        }
    
    }
    
    jdbc.username=root
    jdbc.password=123456
    jdbc.driverClassName=com.mysql.cj.jdbc.Driver
    jdbc.url=jdbc:mysql://localhost:3306/mybatis
    
  • @Bean 与 xml 对应

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Xn4DyXfT-1692697345778)(picture/image-20221029105022768.png)]

7.使用@Import 实现配置导入

  • 目前存在:任何类都配置到配置类里面,不方便管理,也不方便维护

7.1配置 Component 解决

  • @Component

    @Component
    public class DruidConfig {
        @Value("{jdbc.username}")
        private String username;
        @Value("{jdbc.password}")
        private String password;
        @Value("{jdbc.url}")
        private String url;
        @Value("{jdbc.driverClassName}")
        private String driver;
    
    
        @Bean
        public DataSource dataSource(){
            final DruidDataSource source = new DruidDataSource();
            source.setUsername(username);
            source.setPassword(password);
            source.setDriverClassName(driver);
            source.setUrl(url);
            return source;
        }
    }
    

7.2使用@import

  • 修改druidConfig

    @Configuration
    public class DruidConfig {
        @Value("{jdbc.username}")
        private String username;
        @Value("{jdbc.password}")
        private String password;
        @Value("{jdbc.url}")
        private String url;
        @Value("{jdbc.driverClassName}")
        private String driver;
    
    
        @Bean
        public DataSource dataSource(){
            final DruidDataSource source = new DruidDataSource();
            source.setUsername(username);
            source.setPassword(password);
            source.setDriverClassName(driver);
            source.setUrl(url);
            return source;
        }
    }
    
  • 修改spring配置类

    @Configuration
    @PropertySource("druidDb.properties")
    @Import({DruidConfig.class})
    public class SpringConfig {
    }
    
  • 如果需要传参,只需要将参数交给spring管理就行了

    @Configuration
    public class RepositoryConfig {
         @Bean
         public AccountRepository accountRepository(DataSource dataSource) {
            return new JdbcAccountRepository(dataSource);
         }
    }
    

8.注解开发总结

注解配置xml 配置功能说明
@Component
@Controller
@Service
@Repository
bean 标签(id,class)定义bean
@ComponentScan<context:component-scan base-package=“cn.sycoder.ioc.xmlAnnotationBean”/>扫描包加载bean
@Autowired
@Qualifier
@Value
setter 注入
构造器注入
自动装配
依赖注入
@Beanbean 标签,静态工厂模式,实例工厂模式,FactoryBean配置第三方bean
@Scopebean 标签中的 scope 属性设置作用域
@PostConstructor
@PreDestroy
bean 标签中的 init-method / destroy-method生命周期相关
@Import导入其它的配置类
@PropertySource({“db.properties”,“xx.properties”})<context:property-placeholder system-properties-mode=“NEVER” location=“*.properties”/>导入配置文件

9.lombok 地址

  • lombok学习地址

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C++(Qt)软件调试---gdb调试入门用法(12)

gdb调试—入门用法&#xff08;1&#xff09; 文章目录 gdb调试---入门用法&#xff08;1&#xff09;1、前言1.1 什么是GDB1.2 为什么要学习GDB1.3 主要内容1.4 GDB资料 2、C/C开发调试环境准备3、gdb启动调试1.1 启动调试并传入参数1.2 附加到进程1.3 过程执行1.4 退出调试 4…

【《深入浅出计算机网络》学习笔记】第2章 物理层

内容来自b站湖科大教书匠《深入浅出计算机网络》视频和《深入浅出计算机网络》书籍 目录 2.1 物理层概述 2.1.1 物理层要实现的功能 2.1.2 物理层接口特性 2.1.2.1 机械特性 2.1.2.2 电气特性 2.1.2.3 功能特性 2.1.2.4 过程特性 2.2 物理层下面的传输媒体 2.2.1 导向…

网络安全设备篇——加密机

加密机是一种专门用于数据加密和解密的网络安全设备。它通过使用密码学算法对数据进行加密&#xff0c;从而保护数据的机密性和完整性。加密机通常被用于保护敏感数据&#xff0c;如金融信息、个人身份信息等。 加密机的主要功能包括&#xff1a; 数据加密&#xff1a;加密机使…

python知识:什么是字符编码?

前言 嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 我们的MySQL使用latin1的默认字符集&#xff0c; 也就是说&#xff0c;对汉字字段直接使用GBK内码的编码进行存储&#xff0c; 当需要对一些有汉字的字段进行拼音排序时&#xff08;特别涉及到类似于名字这样的字段时…

excel统计函数篇2之count系列

1、COUNT(value1,[value2],…):计算参数列表中数字的个数 2、COUNTA(value1,[value2],…)&#xff1a;计算参数列表中值的个数 联想在excel之数学函数、excel中的通配符一文中提到求和函数&#xff1a; SUMIF(range,ceriteria,[sum_range])&#xff1a;对范围内符合指定条件的…

Nginx高可用集群

目录 一.简介二.案例1.实现思路2.配置文件修改3.实现效果故障转移机制 一.简介 以提高应用系统的可靠性&#xff0c;尽可能地减少中断时间为目标&#xff0c;确保服务的连续性&#xff0c;达到高可用的容错效果。例如“故障切换”、“双机热备”、“多机热备”等都属于高可用集…

nginx防盗链

防盗链介绍 通过二次访问&#xff0c;请求头中带有referer&#xff0c;的方式不允许访问静态资源。 我们只希望用户通过反向代理服务器才可以拿到我们的静态资源&#xff0c;不希望别的服务器通过二次请求拿到我们的静态资源。 盗链是指在自己的页面上展示一些并不在自己服务…

C#和Java的大端位和小端位的问题

C#代码里就是小端序,Java代码里就是大端序&#xff0c; 大端位:big endian,是指数据的高字节保存在内存的低地址中&#xff0c;而数据的低字节保存在内存的高地址中&#xff0c;也叫高尾端 小端位:little endian,是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存…

RunnerGo性能测试时如何从数据库获取数据

我们在做性能测试或者场景测试时往往需要从数据库中获取一些真实的系统数据让我们配置的场景更加贴合实际。而RunnerGo也是在最近的大版本更新中推出连接数据库功能&#xff0c;本篇文章也给大家讲解一下具体的操作方法和实际应用场景。 配置数据库 首先进入RunnerGo页面&…

ShowMeBug CEO李亚飞受邀参加深圳青年创新创业系列沙龙电子信息专场

7月13日下午&#xff0c;由深圳市科技交流服务中心&#xff08;深圳市科技专家委员会办公室&#xff09;主办&#xff0c;深圳新一代产业园承办的“2023深圳青年创新创业系列沙龙——电子信息专场”活动举行。ShowMeBug CEO李亚飞受邀参加此次活动。 深圳市科学技术协会党组成员…

[.NET/WPF] CommunityToolkit.Mvvm 异步指令

我们在开发中, 经常会有这样的需求: 点击按钮后, 进行一些耗时的工作工作进行时, 按钮不可再次被点击工作进行时, 会显示进度条, 或者 “加载中” 的动画 RelayCommand CommunityToolkit.Mvvm 中的 RelayCommand 除了支持最简单的同步方法, 还支持以 Task 作为返回值的异步方…

k8s集群监控方案--node-exporter+prometheus+grafana

目录 前置条件 一、下载yaml文件 二、部署yaml各个组件 2.1 node-exporter.yaml 2.2 Prometheus 2.3 grafana 2.4访问测试 三、grafana初始化 3.1加载数据源 3.2导入模板 四、helm方式部署 前置条件 安装好k8s集群&#xff08;几个节点都可以&#xff0c;本人为了方便实验k8s集…

记一次项目内存优化--内存泄漏

需求–内存泄漏优化&#xff0c;PSS有所下降&#xff0c; OOM率减少 主要是与某个版本作基准进行对比&#xff08;一般是最新版本的前一个版本作原数据&#xff09;&#xff0c;优化后&#xff0c;PSS有所下降&#xff0c;线上OOM率减少&#xff08;Bugly版本对比&#xff09;…

Unsafe upfileupload

文章目录 client checkMIME Typegetimagesize 文件上传功能在web应用系统很常见&#xff0c;比如很多网站注册的时候需要上传头像、上传附件等等。当用户点击上传按钮后&#xff0c;后台会对上传的文件进行判断 比如是否是指定的类型、后缀名、大小等等&#xff0c;然后将其按…

Php“牵手”淘宝商品SKU信息数据采集方法,淘宝API接口申请指南

淘宝天猫商品属性sku信息接口 API 是开放平台提供的一种 API 接口&#xff0c;它可以帮助开发者获取商品的详细信息&#xff0c;包括商品的标题、描述、图片&#xff0c;销量&#xff0c;sku信息等信息。在电商平台的开发中&#xff0c;商品属性接口API是非常常用的 API&#x…

JS中对象数组深拷贝方法

structuredClone() JavaScript 中提供了一个原生 API 来执行对象的深拷贝&#xff1a;structuredClone。它可以通过结构化克隆算法创建一个给定值的深拷贝&#xff0c;并且还可以传输原始值的可转移对象。 当对象中存在循环引用时&#xff0c;仍然可以通过 structuredClone()…

基本定时器

1.简介 1. 基本定时器 TIM6 和 TIM7 包含一个 16 位自动重载计数器 2. 可以专门用于驱动数模转换器 (DAC), 用于触发 DAC 的同步电路 3. 16 位自动重载递增计数器 4. 16 位可编程预分频器 5. 计数器溢出时, 会触发中断/DMA请求 从上往下看 1.开始RCC供给定时器的时钟 RCC_APB1…

通过Matlab编程分析微分方程、SS模型、TF模型、ZPK模型的关系

微分方程、SS模型、TF模型、ZPK模型的关系 一、Matlab编程 微分方程、SS模型、TF模型、ZPK模型的关系二、对系统输出进行微分计算三、对系统输出进行积分计算四、总结五、系统的零点与极点的物理意义参考 &#xff1a;[https://www.zhihu.com/question/22031360/answer/3073452…

【AGC】Publishing api怎么上传绿色认证审核材料

【问题描述】 华为应用市场会对绿色应用标上特有的绿色标识&#xff0c;代表其通过华为终端开放实验室DevEco云测平台的兼容性、稳定性、安全、功耗和性能的检测和认证&#xff0c;是应用高品质的象征。想要自己的应用认证为绿色应用就需要在发布应用时提供绿色认证审核材料&a…

数据结构之——(手撕)顺序表

本章会介绍的知识点如下图&#xff1a; 1&#xff1a; 顺序表的概念&#xff1a;顺序表是用一段物理地址连续的存储单元依次存储数据的线性结构&#xff0c;通常我们使用数组来表示&#xff0c;对数组进行增删查改。 顺序表的结构&#xff1a;逻辑结构与物理结构都是内存中一块…