黑马Spring学习笔记(二)——注解开发

news2024/11/15 18:04:41

目录

一、纯注解开发

1.1  实现步骤

1.2  小结

二、注解开发依赖注入

2.1 自动装配

2.1.1  @Autowired——按照类型注入

2.1.2  @Qualifier——按照名称注入

2.1.3  @Value——简单类型注入

2.2  注解读取properties配置文件——@PropertySource

三、注解开发管理第三方Bean——@Bean

四、注解开发总结


一、纯注解开发

        Spring3.0开启了纯注解开发模式,使用Java类替代配置文件,开启了Spring快速开发赛道。即将配置文件applicationContext.xml删除掉,使用类来替换。

1.1  实现步骤

BookDao BookDaoImpl BookService BookServiceImpl 如下:
public interface BookDao {
    public void save();
}
public class BookDaoImpl implements BookDao {
    public void save() {
        System.out.println("book dao save ..." );
    }
}
public interface BookService {
    public void save();
}
public class BookServiceImpl implements BookService {
    public void save() {
        System.out.println("book service save ...");

步骤1:在实现类上添加注解

在Dao上添加注解

@Component("bookDao")
public class BookDaoImpl implements BookDao {
...

在Service上添加注解

@Component
public class BookServiceImpl implements BookService {
...

步骤2:创建配置类

创建一个配置类SpringConfig

步骤3:标识该类为配置类

在配置类上添加@Configuration注解

@Configuration
public class SpringConfig {
}

步骤4:用注解替换包扫描配置

在配置类上添加包扫描注解@ComponentScan

@Configuration
@ComponentScan("com.itheima")
public class SpringConfig {
}

步骤5:创建运行类并执行

创建一个新的运行类 AppForAnnotation
public class AppForAnnotation {
    public static void main(String[] args) {
        ApplicationContext ctx = new
                AnnotationConfigApplicationContext(SpringConfig.class);
        BookDao bookDao = (BookDao) ctx.getBean("bookDao");
        System.out.println(bookDao);
        BookService bookService = ctx.getBean(BookService.class);
        System.out.println(bookService);
    }
}

运行

1.2  小结

1. Spring对于Bean的管理有四种注解,分别为:

  • @Component
    • @Controller
    • @Service
    • @Repository

2. ClassPathXmlApplicationContext是加载XML配置文件,AnnotationConfigApplicationContext是加载配置类

3. 想要把实现类变为非单例,只需要添加注解scope即可,例如:

@Repository
@Scope("prototype")
public class BookDaoImpl implements BookDao {
...

4. 配置文件与配置类的对比

二、注解开发依赖注入

        Spring为了使用注解简化开发,并没有提供构造函数注入setter注入对应的注解,只提供了自动装配的注解实现。

2.1 自动装配

2.1.1  @Autowired——按照类型注入

(1)准备工作:

  • 创建Maven项目,添加Spring依赖
  • 添加一个配置类SpringConfig
  • BookDaoBookDaoImplBookService、BookServiceImpl类,其中BookDaoImpl添加@Repository注解,BookServiceImpl添加@Service注解
    BookServiceImpl如下:

  • 创建运行类App,运行

出现问题:NullPointerException:Cannot invoke "com.itheima.dao.BookDao.save()" because "this.bookDao" is null

(2)原因

        虽然在BookServiceImpl类中添加了BookDao的属性,并提供了setter方法,但是目前是没有提供配置注入BookDao的,所以bookDao对象为Null,调用其save方法就会报控指针异常。

(3)解决

        在BookServiceImpl 类的 bookDao 属性上添加 @Autowired 注解,实现自动装配
@Service
public class BookServiceImpl implements BookService {
    @Autowired
    private BookDao bookDao;
    ...

        这样,运行就可以成功了!

(4)小结

  • @Autowired 可以写在属性上,也可也写在 setter 方法上,最简单的处理方式是 写在属性上并将

    setter方法删除

    @Service
    public class BookServiceImpl implements BookService {
        @Autowired
        private BookDao bookDao;
    
        public void save() {
            System.out.println("book service save ...");
            bookDao.save();
        }
    }
  • 为什么 setter 方法可以删除呢 ?
    自动装配基于反射设计创建对象并通过暴力反射为私有属性进行设值, 普通反射只能获取 public 修饰的内容, 暴力反射除了获取 public 修饰的内容,还可以获取 private 修改的内容, 所以此处无需提供 setter 方法。
  • @Autowired 是按照类型注入,那么对应 BookDao 接口如果有多个实现类,比如添加
    BookDaoImpl2,情况就会不同。例如:
    • ① BookDaoImpl和BookDaoImpl2都只添加了注解@Repository,运行就会报错,因为按照类型注入无法区分按照哪个注入
    • ② BookDaoImpl和BookDaoImpl2分别添加了注解@Repository("bookDao"),@Repository("bookDao2"),虽然还是有两个Bean对象,但因为变量名叫bookDao,而容器中也只有一个bookDao,所以可以注入成功。
    • ③ BookDaoImpl和BookDaoImpl2分别添加了注解@Repository("bookDao1"),@Repository("bookDao2"),因为按照类型有多个Bean对象,此时按照名称bookDao去找,找不到,会报错。
    • 有多个Bean对象,一般选择“按照名称注入”

2.1.2  @Qualifier——按照名称注入

        如果根据类型找到了多个Bean对象,就可以使用@Qualifier指定注入哪个名称的Bean对象

@Service
public class BookServiceImpl implements BookService {
    @Autowired
    @Qualifier("bookDao1")
    private BookDao bookDao;

    public void save() {
        System.out.println("book service save ...");
        bookDao.save();
    }
}

        注意:@Qualifier不能独立使用,必须和@Autowired一起使用

2.1.3  @Value——简单类型注入

@Repository("bookDao1")
public class BookDaoImpl implements BookDao {
    @Value("itheima")
    private String name;
    ...

此处的@Value并不是无用功,@Value一般会被用在从properties配置文件中读取内容进行使用。

2.2  注解读取properties配置文件——@PropertySource

步骤1:resource下准备properties文件【jdbc.properties】

 步骤2:使用注解加载properties配置文件

@Configuration
@ComponentScan("com.itheima")
@PropertySource("jdbc.properties")
public class SpringConfig {
}

步骤3:使用@Value读取配置文件中的内容

@Repository("bookDao")
public class BookDaoImpl implements BookDao {
    @Value("${name}")
    private String name;

    public void save() {
        System.out.println("book dao save ..." + name);
    }
}

运行

 注意:

  • 如果读取的properties配置文件有多个,可以使用@PropertySource的属性来指定多个,@PropertySource({"jdbc.properties","xxx.properties"})
  • @PropertySource 注解属性中不支持使用通配符 * , 运行会报错

三、注解开发管理第三方Bean——@Bean

        例如,在一个环境中完成对 Druid 数据源的管理,具体步骤为:

步骤1:导入对应的jar包

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.16</version>
</dependency>

步骤2:在配置类中添加方法——@Import

第一种:直接在配置类SpringConfig中书写

@Configuration
public class SpringConfig {
    public DataSource dataSource(){
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName("com.mysql.jdbc.Driver");
        ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
        ds.setUsername("root");
        ds.setPassword("root");
        return ds;
    }
}

(不推荐)

第二种:引入外部配置类——@Import

        如果把所有的第三方bean都配置到Spring的配置类SpringConfig中,会不利于代码阅读和分类管理,我们可以新建一个JdbcConfig配置类,并把数据源配置到该类下

public class JdbcConfig {
    public DataSource dataSource(){
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName("com.mysql.jdbc.Driver");
        ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
        ds.setUsername("root");
        ds.setPassword("root");
        return ds;
    }
}

        然后在SpringConfig中通过@Import注解手动导入需要加载的配置类即可

@Configuration
@Import({JdbcConfig.class})
public class SpringConfig {
}

注意:

  • @Import参数需要的是一个数组,可以引入多个配置类。
  • @Import注解在配置类中只能写一次

        当然,我们不建议将数据库的四要素写死在代码里,可以通过加载配置文件,并使用@Value的形式实现,例如:

SpringConfig配置类:

@Configuration
@PropertySource("jdbc.properties")
@Import({JdbcConfig.class})
public class SpringConfig {
}

JdbcConfig配置类

public class JdbcConfig {
    @Value("${driver}")
    private String driver;
    @Value("${url}")
    private String url;
    @Value("${username}")
    private String userName;
    @Value("${password}")
    private String password;

    @Bean
    public DataSource dataSource() {
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName(driver);
        ds.setUrl(url);
        ds.setUsername(userName);
        ds.setPassword(password);
        return ds;
    }
}

步骤3:在方法上添加@Bean注解

public class JdbcConfig {
    @Bean
    public DataSource dataSource(){
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName("com.mysql.jdbc.Driver");
        ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
        ds.setUsername("root");
        ds.setPassword("root");
        return ds;
    }
}

@Bean的作用是:

  • @Bean只用在方法上,并告诉这个方法产生一个Bean对象
  • 这个Bean对象会交给Spring管理
  • Spring只会调用一次这个方法,随后将这个Bean对象放入容器中管理

步骤4:从IOC容器中获取Bean对象并打印

public class App {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext ctx = new
            AnnotationConfigApplicationContext(SpringConfig.class);
        DataSource dataSource = ctx.getBean(DataSource.class);
        System.out.println(dataSource);
    }
}

四、注解开发总结

XML 配置和注解的开发实现之间的差异如图:



笔记跟课:

https://www.bilibili.com/video/BV1Fi4y1S7ix/?spm_id_from=333.1007.top_right_bar_window_custom_collection.content.click&vd_source=0e0517ebadf244dd640ab0b61dd700c5https://www.bilibili.com/video/BV1Fi4y1S7ix/?spm_id_from=333.1007.top_right_bar_window_custom_collection.content.click&vd_source=0e0517ebadf244dd640ab0b61dd700c5



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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【基础算法】差分

&#x1f339;作者:云小逸 &#x1f4dd;个人主页:云小逸的主页 &#x1f4dd;Github:云小逸的Github &#x1f91f;motto:要敢于一个人默默的面对自己&#xff0c;强大自己才是核心。不要等到什么都没有了&#xff0c;才下定决心去做。种一颗树&#xff0c;最好的时间是十年前…

Kotlin 33. CompileSdkVersion 和 targetSdkVersion 有什么区别?

CompileSdkVersion 和 targetSdkVersion 有什么区别&#xff1f; 在 build.gradle (Module) 文件中&#xff0c;我们通常会看到 CompileSdkVersion 和 targetSdkVersion 的使用&#xff0c;比如下面是一个完整的 build.gradle (Module) 文件&#xff1a; plugins {id com.and…

JavaScript随手笔记---比较两个数组差异

&#x1f48c; 所属专栏&#xff1a;【JavaScript随手笔记】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎咨询&#xff01; &#…

0基础学习diffusion_model扩散模型【易理解的公式推导】

0基础学习diffusion_model扩散模型【易理解的公式推导】一、概述二、扩散过程(已知X0求Xt)三、逆扩散过程(已知Xt求Xt-1)1。算法流程图四、结论五、损失函数六、心得体会&#xff08;优缺点分析&#xff09;一、概述 DDPM论文链接&#xff1a; Jonathan Ho_Denoising Diffusion…

Android入门第64天-MVVM下瀑布流界面的完美实现-使用RecyclerView

前言 网上充满着不完善的基于RecyclerView的瀑布流实现&#xff0c;要么根本是错的、要么就是只知其一不知其二、要么就是一充诉了一堆无用代码、要么用的是古老的MVC设计模式。 一个真正的、用户体验类似于淘宝、抖音的瀑布流怎么实现目前基本为无解。因为本人正好自己空闲时也…

32岁,薪水被应届生倒挂,裸辞了

今年 32 岁&#xff0c;我从公司离职了&#xff0c;是裸辞。 前段时间&#xff0c;我有一件事情一直憋在心里很难受&#xff0c;想了很久也没找到合适的人倾诉&#xff0c;就借着今天写出来。 我一个十几年开发经验&#xff0c;八年 软件测试 经验的职场老人&#xff0c;我慢…

markdown常用语法--花括号(超详细)

&#x1f48c; 所属专栏&#xff1a;【Markdown常用语法】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎咨询&#xff01; &#x1…

2023年,自动化测试岗位有这么吃香吗

测试人员需要具备自动化测试或者测试开发能力&#xff0c;已经成为测试行业内容的一种显在趋势&#xff0c;而且这种趋势呈放大态势&#xff0c;其发展前景是十分明朗的。 2022疫情期间&#xff0c;就业大环境不是很理想&#xff0c;目前呢&#xff0c;企业倾向于招自动化测试…

易基因项目文章| 组蛋白ChIP-seq揭示烟粉虱含菌细胞共生菌调控宿主生殖的新机制

喜报&#xff1a;易基因组蛋白ChIP-seq研究成果见刊《Cell Reports》2023年02月10日&#xff0c;沈阳农业大学植物保护学院博士研究生姚亚林为第一作者、栾军波教授为论文通讯作者在《Cell Reports》杂志以“A bacteriocyte symbiont determines whitefly sex ratio by regulat…

④ 链表

24. 两两交换链表中的节点 题目链接&#xff1a;https://leetcode.cn/problems/swap-nodes-in-pairs/ 注意点&#xff1a; 遍历链表的时候什么时候截止&#xff08;避免空指针异常或无限死循环的问题&#xff09;&#xff1f; 节点数量为偶数或链表为空时&#xff0c;cur.ne…

关于欧拉角你需要知道几个点

基础理解&#xff0c;参照&#xff1a;https://www.cnblogs.com/Estranged-Tech/p/16903025.html 欧拉角、万向节死锁&#xff08;锁死&#xff09;理解 一、欧拉角理解 举例讲解 欧拉角用三次独立的绕确定的轴旋转角度来表示姿态。如下图所示 经过三次旋转&#xff0c;旋…

原创不易,坚持更难

早上CSDN发消息&#xff0c;今天是创作满三年的纪念日&#xff0c;邀请写一篇博文&#xff0c;谈谈感受 开博原因 2020年是一个特殊的年份&#xff0c;疫情刚爆发第一年&#xff0c;也是第一次居家办公&#xff0c;从过完年就一直居家办公&#xff0c;一直居家了38天。2020年…

宗教生活污水处理项目的设计原则

我国的历史源远流长&#xff0c;许多传统文化都延续了上千年以上。同时&#xff0c;我国也是宗教信仰自由的国家&#xff0c;儒释道文化相互影响&#xff0c;交相辉映。游人穿过山间小道&#xff0c;走到寺院庄严礼拜&#xff0c;游客和信众的增多&#xff0c;使教堂、寺庙等宗…

机器学习笔记之谱聚类(一)k-Means聚类算法介绍

机器学习笔记之谱聚类——K-Means聚类算法介绍引言回顾&#xff1a;高斯混合模型聚类任务基本介绍距离计算k-Means\text{k-Means}k-Means算法介绍k-Means\text{k-Means}k-Means算法示例k-Means\text{k-Means}k-Means算法与高斯混合模型的关系k-Means\text{k-Means}k-Means算法的…

CTFer成长之路之CTF中的SQL注入

CTF中的SQL注入CTF SQL注入 SQL注入-1 题目描述: 暂无 docker-compose.yml version: 3.2services:web:image: registry.cn-hangzhou.aliyuncs.com/n1book/web-sql-1:latestports:- 80:80启动方式 docker-compose up -d 题目Flag n1book{union_select_is_so_cool} Wri…

PyQt5数据库开发1 4.3 QSqlTableModel 之 相关槽函数的实现(多图长文详解)

目录 一、打开数据库表 1. 写打开数据库的槽函数 2. 运行后发现数据库可以打开了 3. ODBC配通了&#xff0c;数据库还是打不开 4. 写在tableView上显示数据库表的函数 5. 运行后发现表可以显示了 6. 代码分析 7. 添加列名称 8. 根据内容调整列宽 9. 备注&#xff1a;…

Kaggle系列之CIFAR-10图像识别分类(残差网络模型ResNet-18)

CIFAR-10数据集在计算机视觉领域是一个很重要的数据集&#xff0c;很有必要去熟悉它&#xff0c;我们来到Kaggle站点&#xff0c;进入到比赛页面&#xff1a;https://www.kaggle.com/competitions/cifar-10CIFAR-10是8000万小图像数据集的一个子集&#xff0c;由60000张32x32彩…

spring cloud gateway集成sentinel并扩展支持restful api进行url粒度的流量治理

sentinel集成网关支持restful接口进行url粒度的流量治理前言使用网关进行总体流量治理&#xff08;sentinel版本&#xff1a;1.8.6&#xff09;1、cloud gateway添加依赖:2、sentinel配置3、网关类型项目配置4、通过zk事件监听刷新上报api分组信息1、非网关项目上报api分组信息…

I.MX6ULL_Linux_系统篇(16) uboot分析-启动流程

原文链接&#xff1a;I.MX6ULL_系统篇(16) uboot分析-启动流程 – WSY Personal Blog (cpolar.cn) 前面我们详细的分析了 uboot 的顶层 Makefile&#xff0c;了解了 uboot 的编译流程。本章我们来详细的分析一下 uboot 的启动流程&#xff0c;理清 uboot 是如何启动的。通过对 …

虹科资讯| 虹科AR荣获汽车后市场“20佳”维修工具评委会提名奖!

2022 虹科荣获20佳维修工具 评委会提名奖 特大喜讯&#xff0c;在2月16日《汽车维修与保养》杂志主办的第十八届汽车后市场“20佳”评选活动中&#xff0c;虹科的产品“M400智能AR眼镜”凭借在AR领域的专业实力&#xff0c;通过层层筛选&#xff0c;在102款入围产品中脱颖而出…