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开发学习(十二)----基于注解开发依赖注入的更多相关文章

  1. 07 Spring框架 依赖注入(四)基于注解的依赖注入

    前面几节我们都在使用xml进行依赖的注入,但是在实际的开发中我们往往偏爱于使用注解进行依赖注入,因为这样更符合我们人的思维,并且更加快捷,本节就来讲述Spring基于注解的依赖注入: 信息注入注解 @ ...

  2. 吴裕雄--天生自然JAVA SPRING框架开发学习笔记:Spring DI(依赖注入)的实现方式属性注入和构造注入

    依赖注入(Dependency Injection,DI)和控制反转含义相同,它们是从两个角度描述的同一个概念. 当某个 Java 实例需要另一个 Java 实例时,传统的方法是由调用者创建被调用者的 ...

  3. spring4——IOC之基于注解的依赖注入(DI )

    spring容器对于Bean的创建和对象属性的依赖注入提供了注解的支持,让我们在开发中能够更加便捷的实现对象的创建和对象属性的依赖注入.一,对于Bean的创建spring容器提供了以下四个注解的支持: ...

  4. Spring:基于注解的依赖注入的使用

    1.什么是pojo?什么是bean? 首先,在之前几篇Spring的介绍文章当中,自己都提到了一个名词叫做POJO类,但是在回顾Spring的注解的使用的时候,去形容java当中的对象还有一个名词是叫 ...

  5. java web 学习十二(session)

    一.Session简单介绍 在WEB开发中,服务器可以为每个用户浏览器创建一个会话对象(session对象),注意:一个浏览器独占一个session对象(默认情况下).因此,在需要保存用户数据时,服务 ...

  6. JAVA多线程学习十二 - Semaphere同步工具

    java 中Semaphere可类比操作系统信号量,硬件资源如IO.内存.磁盘等都是有固定量的,多个程序需要竞争这些资源,没有资源就需要被挂起. 一.类和方法摘要 构造函数: public Semap ...

  7. java入门学习(十二)运算语句 if switch

    这两天在网上做兼职,耽误了些博客见谅哈 欢迎来我的博客:www.taomaipin.com java中的运算语句而且频繁用到的无法就是条件语句和循环语句,包括if,for,while,switch,b ...

  8. Java开发学习(十)----基于注解开发定义bean 已完成

    一.环境准备 先来准备下环境: 创建一个Maven项目 pom.xml添加Spring的依赖 <dependencies>    <dependency>        < ...

  9. Java开发学习(十三)----基于注解开发定义第三方bean及注解开发总结

    在前面的博客中定义bean的时候都是在自己开发的类上面写个注解就完成了,但如果是第三方的类,这些类都是在jar包中,我们没有办法在类上面添加注解,这个时候该怎么办? 遇到上述问题,我们就需要有一种更加 ...

随机推荐

  1. MySQL left join 引发的惨案

    当我用这个进行更改值时,type未控制order表 其他数据被更改 还好备份数据表了(这里就体现了备份的重要性) UPDATE expense_order as a left join ( SELEC ...

  2. Vue过渡和动画效果展示(案例、GIF动图演示、附源码)

    前言 本篇随笔主要写了Vue过渡和动画基础.多个元素过渡和多个组件过渡,以及列表过渡的动画效果展示.详细案例分析.GIF动图演示.附源码地址获取. 作为自己对Vue过渡和动画效果知识的总结与笔记. 因 ...

  3. XCTF练习题---WEB---view_source

    XCTF练习题---WEB---view_source flag:cyberpeace{662b1cf989a0a7999a5589290ce5a88e} 解题步骤: 1.观察题目,打开场景 2.根据 ...

  4. 浅尝Spring注解开发_Bean生命周期及执行过程

    Spring注解开发 浅尝Spring注解开发,基于Spring 4.3.12 包含Bean生命周期.自定义初始化方法.Debug BeanPostProcessor执行过程及在Spring底层中的应 ...

  5. Linux命令篇 - sed 命令

    sed sed - stream editor for filtering and transforming text: sed:利用脚本来处理.编辑文本文件: 格式:sed [OPTION]... ...

  6. NMS技术总结(NMS原理、多类别NMS、NMS的缺陷、NMS的改进思路、各种NMS方法)

    ​  前言  本文介绍了NMS的应用场合.基本原理.多类别NMS方法和实践代码.NMS的缺陷和改进思路.介绍了改进NMS的几种常用方法.提供了其它不常用的方法的链接. 本文很早以前发过,有个读者评论说 ...

  7. 购物车+ATM项目(图形化)

    项目下载 项目目录结构 运行效果 seetings.py import logging import logging.config # 定义日志输出格式 开始 import os standard_f ...

  8. 【mq】从零开始实现 mq-10-消费者拉取消息回执 pull message ack

    前景回顾 [mq]从零开始实现 mq-01-生产者.消费者启动 [mq]从零开始实现 mq-02-如何实现生产者调用消费者? [mq]从零开始实现 mq-03-引入 broker 中间人 [mq]从零 ...

  9. Linux下使用ssh测试端口是否开启

    当服务器上不允许使用telnet时,可以使用ssh测试远程服务器端口是否开启 具体命令如下 -v 显示连接debug信息 -p port 指定端口 ssh -v -p 80 root@192.168. ...

  10. 《Mybatis 手撸专栏》第8章:把反射用到出神入化

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 为什么,读不懂框架源码? 我们都知道作为一个程序员,如果想学习到更深层次的技术,就需 ...