Java开发学习(十二)----基于注解开发依赖注入
Spring为了使用注解简化开发,并没有提供构造函数注入、setter注入对应的注解,只提供了自动装配的注解实现。
1、环境准备
首先准备环境:
创建一个Maven项目
pom.xml添加Spring的依赖
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
</dependencies>添加一个配置类
SpringConfig@Configuration
@ComponentScan("com.itheima")
public class SpringConfig {
}添加BookDao、BookDaoImpl、BookService、BookServiceImpl类
public interface BookDao {
public void save();
}
@Repository
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ..." );
}
}
public interface BookService {
public void save();
}
@Service
public class BookServiceImpl implements BookService {
private BookDao bookDao;
public void setBookDao(BookDao bookDao) {
this.bookDao = bookDao;
}
public void save() {
System.out.println("book service save ...");
bookDao.save();
}
}创建运行类App
public class App {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
BookService bookService = ctx.getBean(BookService.class);
bookService.save();
}
}
最终创建好的项目结构如下:

环境准备好后,运行后会发现有问题

出现问题的原因是,在BookServiceImpl类中添加了BookDao的属性,并提供了setter方法,但是目前是没有提供配置注入BookDao的,所以bookDao对象为Null,调用其save方法就会报空指针异常。
2、注解实现按照类型注入
对于这个问题使用注解该如何解决?
(1) 在BookServiceImpl类的bookDao属性上添加@Autowired注解
@Service
public class BookServiceImpl implements BookService {
@Autowired
private BookDao bookDao;
// @Autowired
// public void setBookDao(BookDao bookDao) {
// this.bookDao = bookDao;
// }
public void save() {
System.out.println("book service save ...");
bookDao.save();
}
}
注意:
@Autowired可以写在属性上,也可也写在setter方法上,最简单的处理方式是
写在属性上并将setter方法删除掉为什么setter方法可以删除呢?
自动装配基于反射设计创建对象并通过暴力反射为私有属性进行设值
普通反射只能获取public修饰的内容
暴力反射除了获取public修饰的内容还可以获取private修改的内容
所以此处无需提供setter方法
(2)@Autowired是按照类型注入,那么对应BookDao接口如果有多个实现类,比如添加BookDaoImpl2
@Repository
public class BookDaoImpl2 implements BookDao {
public void save() {
System.out.println("book dao save ...2");
}
}
这个时候再次运行App,就会报错

此时,按照类型注入就无法区分到底注入哪个对象,解决方案:按照名称注入
先给两个Dao类分别起个名称
@Repository("bookDao")
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ..." );
}
}
@Repository("bookDao2")
public class BookDaoImpl2 implements BookDao {
public void save() {
System.out.println("book dao save ...2" );
}
}此时就可以注入成功,但是得思考个问题:
@Autowired是按照类型注入的,给BookDao的两个实现起了名称,它还是有两个bean对象,为什么不报错?
@Autowired默认按照类型自动装配,如果IOC容器中同类的Bean找到多个,就按照变量名和Bean的名称匹配。因为变量名叫
bookDao而容器中也有一个booDao,所以可以成功注入。分析下面这种情况是否能完成注入呢?

不行,因为按照类型会找到多个bean对象,此时会按照
bookDao名称去找,因为IOC容器只有名称叫bookDao1和bookDao2,所以找不到,会报NoUniqueBeanDefinitionException
3、注解实现按照名称注入
当根据类型在容器中找到多个bean,注入参数的属性名又和容器中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注解后的值就是需要注入的bean的名称。
注意:@Qualifier不能独立使用,必须和@Autowired一起使用
4、简单数据类型注入
引用类型看完,简单类型注入就比较容易懂了。简单类型注入的是基本数据类型或者字符串类型,下面在BookDaoImpl类中添加一个name属性,用其进行简单类型注入
@Repository("bookDao")
public class BookDaoImpl implements BookDao {
private String name;
public void save() {
System.out.println("book dao save ..." + name);
}
}
数据类型换了,对应的注解也要跟着换,这次使用@Value注解,将值写入注解的参数中就行了
@Repository("bookDao")
public class BookDaoImpl implements BookDao {
@Value("itheima")
private String name;
public void save() {
System.out.println("book dao save ..." + name);
}
}
注意数据格式要匹配,如将"abc"注入给int值,这样程序就会报错。
介绍完后,会有一种感觉就是这个注解好像没什么用,跟直接赋值是一个效果,还没有直接赋值简单,所以这个注解存在的意义是什么?
5、注解读取properties配置文件
@Value一般会被用在从properties配置文件中读取内容进行使用,具体如何实现?
步骤1:resource下准备properties文件
jdbc.properties
name=itheima888
步骤2: 使用注解加载properties配置文件
在配置类上添加@PropertySource注解
@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);
}
}
步骤4:运行程序
运行App类,查看运行结果,说明配置文件中的内容已经被加载到

注意:
如果读取的properties配置文件有多个,可以使用
@PropertySource的属性来指定多个@PropertySource({"jdbc.properties","xxx.properties"})@PropertySource注解属性中不支持使用通配符*,运行会报错@PropertySource({"*.properties"})@PropertySource注解属性中可以把classpath:加上,代表从当前项目的根路径找文件@PropertySource({"classpath:jdbc.properties"})
知识点1:@Autowired
| 名称 | @Autowired |
|---|---|
| 类型 | 属性注解 或 方法注解(了解) 或 方法形参注解(了解) |
| 位置 | 属性定义上方 或 标准set方法上方 或 类set方法上方 或 方法形参前面 |
| 作用 | 为引用类型属性设置值 |
| 属性 | required:true/false,定义该属性是否允许为null |
知识点2:@Qualifier
| 名称 | @Qualifier |
|---|---|
| 类型 | 属性注解 或 方法注解(了解) |
| 位置 | 属性定义上方 或 标准set方法上方 或 类set方法上方 |
| 作用 | 为引用类型属性指定注入的beanId |
| 属性 | value(默认):设置注入的beanId |
知识点3:@Value
| 名称 | @Value |
|---|---|
| 类型 | 属性注解 或 方法注解(了解) |
| 位置 | 属性定义上方 或 标准set方法上方 或 类set方法上方 |
| 作用 | 为 基本数据类型 或 字符串类型 属性设置值 |
| 属性 | value(默认):要注入的属性值 |
知识点4:@PropertySource
| 名称 | @PropertySource |
|---|---|
| 类型 | 类注解 |
| 位置 | 类定义上方 |
| 作用 | 加载properties文件中的属性值 |
| 属性 | value(默认):设置加载的properties文件对应的文件名或文件名组成的数组 |
Java开发学习(十二)----基于注解开发依赖注入的更多相关文章
- 07 Spring框架 依赖注入(四)基于注解的依赖注入
前面几节我们都在使用xml进行依赖的注入,但是在实际的开发中我们往往偏爱于使用注解进行依赖注入,因为这样更符合我们人的思维,并且更加快捷,本节就来讲述Spring基于注解的依赖注入: 信息注入注解 @ ...
- 吴裕雄--天生自然JAVA SPRING框架开发学习笔记:Spring DI(依赖注入)的实现方式属性注入和构造注入
依赖注入(Dependency Injection,DI)和控制反转含义相同,它们是从两个角度描述的同一个概念. 当某个 Java 实例需要另一个 Java 实例时,传统的方法是由调用者创建被调用者的 ...
- spring4——IOC之基于注解的依赖注入(DI )
spring容器对于Bean的创建和对象属性的依赖注入提供了注解的支持,让我们在开发中能够更加便捷的实现对象的创建和对象属性的依赖注入.一,对于Bean的创建spring容器提供了以下四个注解的支持: ...
- Spring:基于注解的依赖注入的使用
1.什么是pojo?什么是bean? 首先,在之前几篇Spring的介绍文章当中,自己都提到了一个名词叫做POJO类,但是在回顾Spring的注解的使用的时候,去形容java当中的对象还有一个名词是叫 ...
- java web 学习十二(session)
一.Session简单介绍 在WEB开发中,服务器可以为每个用户浏览器创建一个会话对象(session对象),注意:一个浏览器独占一个session对象(默认情况下).因此,在需要保存用户数据时,服务 ...
- JAVA多线程学习十二 - Semaphere同步工具
java 中Semaphere可类比操作系统信号量,硬件资源如IO.内存.磁盘等都是有固定量的,多个程序需要竞争这些资源,没有资源就需要被挂起. 一.类和方法摘要 构造函数: public Semap ...
- java入门学习(十二)运算语句 if switch
这两天在网上做兼职,耽误了些博客见谅哈 欢迎来我的博客:www.taomaipin.com java中的运算语句而且频繁用到的无法就是条件语句和循环语句,包括if,for,while,switch,b ...
- Java开发学习(十)----基于注解开发定义bean 已完成
一.环境准备 先来准备下环境: 创建一个Maven项目 pom.xml添加Spring的依赖 <dependencies> <dependency> < ...
- Java开发学习(十三)----基于注解开发定义第三方bean及注解开发总结
在前面的博客中定义bean的时候都是在自己开发的类上面写个注解就完成了,但如果是第三方的类,这些类都是在jar包中,我们没有办法在类上面添加注解,这个时候该怎么办? 遇到上述问题,我们就需要有一种更加 ...
随机推荐
- python学习-Day35
目录 今日内容详细 代码创建进程 创建进程的方式 第一种创建进程的方式 创建进程的第二种方式 进程实现并发 join方法 进程间数据默认隔离 进程对象属性和方法 进程号如何查看 查看进程号的方法 杀死 ...
- Windows下使用 Docker 部署 RabbitMQ
安装 Docker 首先进入 https://docs.docker.com/desktop/windows/install/ 下载最新版 Docker,下载好后,双击进行安装,此处不对安装进行说明. ...
- 看完复旦博士用Python统计核酸结果后,我照着也写了一个
前几天,人民日报公众号报道了复旦博士生自己写代码,通过OCR和正则表达式统计核酸截图结果.具体文章见:https://mp.weixin.qq.com/s/l8u9JifKDlRDoz32-jZWQg ...
- 从旧金山到上海, HTTP/3 非常快!
HTTP/3 是超文本传输协议 (HTTP) 的第三个版本,它对 Web 性能来说意义重大, 让我们看看HTTP/3 如何让网站的速度变得更快! 等等,HTTP/2 发生了什么? 不是几年前才开始推广 ...
- ansible模块的介绍与使用
ansible-doc的使用 1.ansible-doc -h可以看见ansible-doc的所有参数 2.ansible-doc 命令格式:ansible-doc [-l|-F|-s] [optio ...
- 如何利用 React Hooks 管理全局状态
如何利用 React Hooks 管理全局状态 本文写于 2020 年 1 月 6 日 React 社区最火的全局状态管理库必定是 Redux,但是 Redux 本身就是为了大型管理数据而妥协设计的- ...
- Fail2ban 运维管理 服务控制
启动监禁 启动所有或者单个监禁项目. # 语法:fail2ban-client start [监禁名称] root@ubuntu:~# fail2ban-client start sshd 停止监禁 ...
- 用python解决打标签时将xml文件的标签名打错
用python解决打标签时将xml文件的标签名打错 问题描述:再进行达标签时将magnetic_tile的标签名错误的打成了magnetic_title,又不想一张一张的修改 出现问题的xml文件 & ...
- 秋招如何抱佛脚?2022最新大厂Java面试真题合集(附答案
2022秋招眼看着就要来了,但是离谱的是,很多同学最近才想起来还有秋招这回事,所以纷纷临时抱佛脚,问我有没有什么快速磨枪的方法, 我的回答是:有! 说起来,临阵磨枪没有比背八股文更靠谱的了,很多人对这 ...
- 关于『进击的Markdown』:第三弹
关于『进击的Markdown』:第三弹 建议缩放90%食用 我与神明画押,赌这弹markdown又双叒叕拖稿了 %%%Markdown!我的CSDN编辑器崩了呜呜呜 各路英雄豪杰,大家好! 我们要开 ...