【Spring篇】IOC/DI注解开发

痛定思痛。 2024-04-20 07:53 187阅读 0赞

?系列专栏:Spring系列专栏

?个人主页:个人主页

目录

一、IOC/DI注解开发

1.注解开发定义bean

2.纯注解开发模式

1.思路分析

2.实现步骤

3.注解开发bean作用范围与生命周期管理

1.环境准备

2.Bean的作用范围

3.Bean的生命周期

4.注解开发依赖注入

1.环境准备

2.注解实现按照类型注入

3.注解实现按照名称注入

4.简单数据类型注入

5.注解读取properties配置文件

二、IOC/DI注解开发管理第三方bean

1.环境准备

2.注解开发管理第三方bean

3.引入外部配置类

1.使用包扫描引入

2.使用@Import引入

4.注解开发实现为第三方bean注入资源

1.简单数据类型

2.引用数据类型

三、注解开发总结


一、IOC/DI注解开发

Spring 的 IOC/DI 对应的配置开发就已经讲解完成,但是使用起来相对来说还是比较复杂的,复杂的

地方在 配置文件

前面咱们聊 Spring 的时候说过, Spring 可以简化代码的开发,到现在并没有体会到。

所以 Spring 到底是如何简化代码开发的呢 ?

要想真正简化开发,就需要用到 Spring 的注解开发, Spring 对注解支持的版本历程 :

  • 2.0版开始支持注解
  • 2.5版注解功能趋于完善3.0版支持纯注解开发

关于注解开发,我们会讲解两块内容 注解开发定义 bean 和 纯注解开发 。

注解开发定义 bean 用的是 2.5 版提供的注解,纯注解开发用的是 3.0 版提供的注解。

环境准备

在学习注解开发之前,先来准备下案例环境:

  • 创建一个Maven项目
  • pom.xml添加Spring的依赖



    org.springframework
    spring-context
    5.2.10.RELEASE

  • resources下添加applicationContext.xml

    <?xml version=”1.0” encoding=”UTF-8”?>



  • 添加 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 …”);
    }
    }

  • 创建运行类App

    public class App {
    public static void main(String[] args) {
    ApplicationContext ctx = new
    ClassPathXmlApplicationContext(“applicationContext.xml”);
    BookDao bookDao = (BookDao) ctx.getBean(“bookDao”);
    bookDao.save();
    }
    }

最终创建好的项目结构如下 :

aa4c0cc4b0fd45d3b721e08451509650.png

1.注解开发定义**bean**

步骤 1: 删除原 XML 配置

将配置文件中的 标签删除掉

  1. <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>

步骤 2:Dao 上添加注解

在 BookDaoImpl 类上添加 @Component 注解

  1. @Component("bookDao")
  2. public class BookDaoImpl implements BookDao {
  3. public void save() {
  4. System.out.println("book dao save ..." );
  5. }
  6. }

注意 :@Component 注解不可以添加在接口上,因为接口是无法创建对象的。

XML 与注解配置的对应关系 :

adc69e053f02475a8209ffb5d5c1a730.png

步骤**3:配置Spring**的注解包扫描

为了让Spring框架能够扫描到写在类上的注解,需要在配置文件上进行包扫描

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="
  5. http://www.springframework.org/schema/beans
  6. http://www.springframework.org/schema/beans/spring-beans.xsd">
  7. <context:component-scan base-package="com.itheima"/>
  8. </beans>

说明 :

component-scan

  • component:组件,Spring将管理的bean视作自己的一个组件
  • scan:扫描

base-package 指定 Spring 框架扫描的包路径,它会扫描指定包及其子包中的所有类上的注解。

  • 包路径越多[如:com.itheima.dao.impl],扫描的范围越小速度越快
  • 包路径越少[如:com.itheima],扫描的范围越大速度越慢
  • 一般扫描到项目的组织名称即Maven的groupId下[如:com.itheima]即可。

步骤 4 :运行程序

运行 App 类查看打印结果

34fca1633d8840e4b38ece382417d309.png

步骤 5:Service 上添加注解

在 BookServiceImpl 类上也添加 @Component 交给 Spring 框架管理

  1. @Component
  2. public class BookServiceImpl implements BookService {
  3. private BookDao bookDao;
  4. public void setBookDao(BookDao bookDao) {
  5. this.bookDao = bookDao;
  6. }
  7. public void save() {
  8. System.out.println("book service save ...");
  9. bookDao.save();
  10. }
  11. }

步骤**6:**运行程序

在 App 类中,从 IOC 容器中获取 BookServiceImpl 对应的 bean 对象,打印

  1. public class App {
  2. public static void main(String[] args) {
  3. ApplicationContext ctx = new
  4. ClassPathXmlApplicationContext("applicationContext.xml");
  5. BookDao bookDao = (BookDao) ctx.getBean("bookDao");
  6. System.out.println(bookDao);
  7. //按类型获取bean
  8. BookService bookService = ctx.getBean(BookService.class);
  9. System.out.println(bookService);
  10. }
  11. }

打印观察结果,两个 bean 对象都已经打印到控制台

6286ae26b5474128bb8334586899df33.png

说明 :

  • BookServiceImpl类没有起名称,所以在App中是按照类型来获取bean对象
  • @Component注解如果不起名称,会有一个默认值就是当前类名首字母小写,所以也可以按照名称获取,如

    BookService bookService = (BookService)ctx.getBean(“bookServiceImpl”);
    System.out.println(bookService);

对于@Component注解,还衍生出了其他三个注解@Controller、@Service、@Repository

通过查看源码会发现 :

e3343827544e4d9395f0c45264692460.png

这三个注解和@Component注解的作用是一样的,为什么要衍生出这三个呢?

方便我们后期在编写类的时候能很好的区分出这个类是属于表现层、业务层还是数据层的类。

知识点 1:@Component
























名称 @Component/@Controller/@Service/@Repository
类型 类注解
位置 类定义上方
作用 设置该类为spring管理的bean
属性 value(默认):定义beanid

2.纯注解开发模式

上面已经可以使用注解来配置bean, 但是依然有用到配置文件,在配置文件中对包进行了扫描,

Spring 在 3.0 版已经支持纯注解开发

  • Spring3.0开启了纯注解开发模式,使用Java类替代配置文件,开启了Spring快速开发赛道具体如何实现?

1.思路分析

实现思路为 :

将配置文件 applicationContext.xml 删除掉,使用类来替换。

2.实现步骤

步骤 1: 创建配置类

创建一个配置类 SpringConfig

  1. public class SpringConfig {
  2. }

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

在配置类上添加 @Configuration 注解,将其标识为一个配置类 , 替换 applicationContext.xml

  1. @Configuration
  2. public class SpringConfig {
  3. }

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

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

  1. @Configuration
  2. @ComponentScan("com.itheima")
  3. public class SpringConfig {
  4. }

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

创建一个新的运行类 AppForAnnotation

  1. public class AppForAnnotation {
  2. public static void main(String[] args) {
  3. //AnnotationConfigApplicationContext加载Spring配置类初始化Spring容器
  4. ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
  5. BookDao bookDao = (BookDao) ctx.getBean("bookDao");
  6. System.out.println(bookDao);
  7. //按类型获取bean
  8. BookService bookService = ctx.getBean(BookService.class);
  9. System.out.println(bookService);
  10. }
  11. }

运行 AppForAnnotation, 可以看到两个对象依然被获取成功

173ab30e198146608e62052cb506eb09.png

至此,纯注解开发的方式就已经完成了,主要内容包括 :

  • Java类替换Spring核心配置文件

9e00cff5d6f841fcbb02ccee08ba6ada.png

  • @Configuration注解用于设定当前类为配置类
  • @ComponentScan注解用于设定扫描路径,此注解只能添加一次,多个数据请用数组格式

    @ComponentScan({com.itheima.service”,”com.itheima.dao”})

  • 读取Spring核心配置文件初始化容器对象切换为读取Java配置类初始化容器对象

    //加载配置文件初始化容器
    ApplicationContext ctx = new
    ClassPathXmlApplicationContext(“applicationContext.xml”);
    //加载配置类初始化容器
    ApplicationContext ctx = new
    AnnotationConfigApplicationContext(SpringConfig.class);

知识点 1 @Configuration
























名称 @Configuration
类型 类注解
位置 类定义上方
作用 设置该类为spring配置类
属性 value(默认):定义beanid

知识点 2 @ComponentScan
























名称 @ComponentScan
类型 类注解
位置 类定义上方
作用 设置spring配置类扫描路径,用于加载使用注解格式定义的bean
属性 value(默认):扫描路径,此路径可以逐层向下扫描

小结 :

这一节重点掌握的是使用注解完成 Spring 的 bean 管理,需要掌握的内容为 :

  • 记住@Component、@Controller、@Service、@Repository这四个注解
  • applicationContext.xml中的作用是指定扫描包路径,注解为 @ComponentScan
  • @Configuration标识该类为配置类,使用类替换applicationContext.xml文件
  • ClassPathXmlApplicationContext是加载XML配置文件
  • AnnotationConfigApplicationContext是加载配置类

3.注解开发**bean**作用范围与生命周期管理

使用注解已经完成了 bean 的管理,接下来按照前面所学习的内容,将通过配置实现的内容都换成对应的注解实现,包含两部分内容: bean 作用范围 和 bean 生命周期 。

1.环境准备

老规矩,学习之前先来准备环境 :

  • 创建一个Maven项目
  • pom.xml添加Spring的依赖【之前的】
  • 添加一个配置类SpringConfig【之前的】
  • 添加BookDao、BookDaoImpl类

    public interface BookDao {
    public void save();
    }
    @Repository
    public class BookDaoImpl implements BookDao {
    public void save() {
    System.out.println(“book dao save …” );
    }
    }

  • 创建运行类App

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

最终创建好的项目结构如下 :

2fd4e1e2d2284a0a96420c4a6d48871e.png

2.Bean**的作用范围**

(1)先运行App类,在控制台打印两个一摸一样的地址,说明默认情况下bean是单例

7c4e8dca6b654a05b776a9bc7a1a1674.png

(2)要想将BookDaoImpl变成非单例,只需要在其类上添加@scope注解

  1. @Repository
  2. //@Scope设置bean的作用范围
  3. @Scope("prototype")
  4. public class BookDaoImpl implements BookDao {
  5. public void save() {
  6. System.out.println("book dao save ...");
  7. }
  8. }

e34682d5ead647148113d5afa9be0b03.png

知识点****@Scope
























名称

@Scope
类型 类注解
位置 类定义上方
作用

设置该类创建对象的作用范围


可用于设置创建出的
bean
是否为单例对象
属性

value
(默认):定义
bean
作用范围,


默认值
singleton
(单例),可选值
prototype
(非单例)

3.Bean**的生命周期**

(1) 在 BookDaoImpl 中添加两个方法, init 和 destroy , 方法名可以任意.

在对应的方法上添加 @PostConstruct 和 @PreDestroy 注解

  1. @Repository
  2. //@Scope设置bean的作用范围
  3. public class BookDaoImpl implements BookDao {
  4. public void save() {
  5. System.out.println("book dao save ...");
  6. }
  7. // @PostConstruct设置bean的初始化方法
  8. @PostConstruct
  9. public void init() {
  10. System.out.println("init ...");
  11. }
  12. //@PreDestroy设置bean的销毁方法
  13. @PreDestroy
  14. public void destroy() {
  15. System.out.println("destroy ...");
  16. }
  17. }

(2) 要想看到两个方法执行,需要注意的是 destroy 只有在容器关闭的时候,才会执行,所以需要修

改 App 的类

  1. public class App {
  2. public static void main(String[] args) {
  3. AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
  4. BookDao bookDao1 = ctx.getBean(BookDao.class);
  5. BookDao bookDao2 = ctx.getBean(BookDao.class);
  6. System.out.println(bookDao1);
  7. System.out.println(bookDao2);
  8. ctx.close();
  9. }
  10. }

运行App,类查看打印结果,证明init和destroy方法都被执行了。

3d3dec24fa594688a0d348f3932590b0.png

注意**:@PostConstruct@PreDestroy注解如果找不到,需要导入下面的jar**包

  1. <dependency>
  2. <groupId>javax.annotation</groupId>
  3. <artifactId>javax.annotation-api</artifactId>
  4. <version>1.3.2</version>
  5. </dependency>

找不到的原因是,从 JDK9 以后 jdk 中的 javax.annotation 包被移除了,这两个注解刚好就在这个包

中。

9f17fd84835b4540b4bc77e1d3f1d068.png

小结

4e8b1293a178460986d4df46e00f6f22.png

4.注解开发依赖注入

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

1.环境准备

在学习之前,把案例环境介绍下 :

  • 创建一个Maven项目
  • pom.xml添加Spring的依赖
  • 添加一个配置类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 {

    1. public static void main(String[] args) {
    2. AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
    3. BookService bookService = ctx.getBean(BookService.class);
    4. bookService.save();
    5. }

    }

最终创建好的项目结构如下 :

84ca5ab473df4fcc94d39e2a15f11861.png

环境准备好后,运行后会发现有问题22c13ff728e54645a531a9ab26829c40.png

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

2.注解实现按照类型注入

对于这个问题使用注解该如何解决 ?

(1) 在 BookServiceImpl 类的 bookDao 属性上添加 @Autowired 注解

  1. @Service
  2. public class BookServiceImpl implements BookService {
  3. @Autowired
  4. private BookDao bookDao;
  5. // public void setBookDao(BookDao bookDao) {
  6. // this.bookDao = bookDao;
  7. // }
  8. public void save() {
  9. System.out.println("book service save ...");
  10. bookDao.save();
  11. }
  12. }

注意 :

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

setter 方法删除掉

为什么 setter 方法可以删除呢 ?

  • 自动装配基于反射设计创建对象并通过暴力反射为私有属性进行设值
  • 普通反射只能获取public修饰的内容
  • 暴力反射除了获取public修饰的内容还可以获取private修改的内容
  • 所以此处无需提供setter方法

(2)@Autowired 是按照类型注入,那么对应 BookDao 接口如果有多个实现类,比如添加

BookDaoImpl2

  1. @Repository
  2. public class BookDaoImpl2 implements BookDao {
  3. public void save() {
  4. System.out.println("book dao save ...2");
  5. }
  6. }

这个时候再次运行 App ,就会报错

300644d7ab374d1da41eef0629a307ee.png

此时,按照类型注入就无法区分到底注入哪个对象,解决方案:按照名称注入

先给两个 Dao 类分别起个名称

  1. @Repository("bookDao")
  2. public class BookDaoImpl implements BookDao {
  3. public void save() {
  4. System.out.println("book dao save ..." + name);
  5. }
  6. }
  7. @Repository("bookDao2")
  8. public class BookDaoImpl2 implements BookDao {
  9. public void save() {
  10. System.out.println("book dao save ...2");
  11. }
  12. }

此时就可以注入成功,但是得思考个问题 :

  • @Autowired是按照类型注入的,给BookDao的两个实现起了名称,它还是有两个bean对象, 为什么不报错?
  • @Autowired默认按照类型自动装配,如果IOC容器中同类的Bean找到多个,就按照变量名和 Bean的名称匹配。因为变量名叫bookDao而容器中也有一个bookDao,所以可以成功注入。
  • 分析下面这种情况是否能完成注入呢?

985838259eda4e12aba85fd09c4c15a7.png

不行,因为按照类型会找到多个bean对象,此时会按照bookDao名称去找,因为IOC容器只有名称叫bookDao1和bookDao2 ,所以找不到,会报NoUniqueBeanDefinitionException

3.注解实现按照名称注入

当根据类型在容器中找到多个 bean, 注入参数的属性名又和容器中 bean 的名称不一致,这个时候该如何解决,就需要使用到@Qualifier 来指定注入哪个名称的 bean 对象。

  1. @Service
  2. public class BookServiceImpl implements BookService {
  3. @Autowired
  4. @Qualifier("bookDao1")
  5. private BookDao bookDao;
  6. public void save() {
  7. System.out.println("book service save ...");
  8. bookDao.save();
  9. }
  10. }

@Qualifier 注解后的值就是需要注入的 bean 的名称。

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

4.简单数据类型注入

引用类型看完,简单类型注入就比较容易懂了。简单类型注入的是基本数据类型或者字符串类型,下面在BookDaoImpl 类中添加一个 name 属性,用其进行简单类型注入

  1. @Repository("bookDao")
  2. public class BookDaoImpl implements BookDao {
  3. private String name;
  4. public void save() {
  5. System.out.println("book dao save ..." + name);
  6. }
  7. }

数据类型换了,对应的注解也要跟着换,这次使用 @Value 注解,将值写入注解的参数中就行了

  1. @Repository("bookDao")
  2. public class BookDaoImpl implements BookDao {
  3. @Value("itheima")
  4. private String name;
  5. public void save() {
  6. System.out.println("book dao save ..." + name);
  7. }
  8. }

注意数据格式要匹配,如将 “abc” 注入给 int 值,这样程序就会报错。

介绍完后,会有一种感觉就是这个注解好像没什么用,跟直接赋值是一个效果,还没有直接赋值简

单,所以这个注解存在的意义是什么 ?

5.注解读取**properties**配置文件

@Value一般会被用在从properties配置文件中读取内容进行使用,具体如何实现?

步骤 1 resource 下准备 properties 文件

jdbc.properties

  1. name=itheima888

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

在配置类上添加 @PropertySource 注解

  1. @Configuration
  2. @ComponentScan("com.itheima")
  3. //@PropertySource加载properties配置文件
  4. @PropertySource({"jdbc.properties"})
  5. public class SpringConfig {
  6. }

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

  1. @Repository("bookDao")
  2. public class BookDaoImpl implements BookDao {
  3. //@Value:注入简单类型(无需提供set方法)
  4. @Value("${name}")
  5. private String name;
  6. public void save() {
  7. System.out.println("book dao save ..." + name);
  8. }
  9. }

步骤4:运行程序

运行 App 类,查看运行结果,说明配置文件中的内容已经被加载到

7bbc9a90c6d0428ab0fd8e8b0ebc4b19.png

注意 :

  • 如果读取的properties配置文件有多个,可以使用@PropertySource的属性来指定多个

    @PropertySource({“jdbc.properties”,”xxx.properties”})

  • @PropertySource注解属性中不支持使用通配符* ,运行会报错

    @PropertySource({“*.properties”})

  • @PropertySource注解属性中可以把classpath:加上,代表从当前项目的根路径找文件

    @PropertySource({“classpath:jdbc.properties”})

38911cb6da034af09096a0c93fabedb5.png

知识点 4 @PropertySource

e7a690f008174d0d946862861ac89c76.png

二、IOC/DI注解开发管理第三方bean

前面定义 bean 的时候都是在自己开发的类上面写个注解就完成了,但如果是第三方的类,这些类都是在jar 包中,我们没有办法在类上面添加注解,这个时候该怎么办 ?

遇到上述问题,我们就需要有一种更加灵活的方式来定义 bean, 这种方式不能在原始代码上面书写注解,一样能定义bean, 这就用到了一个全新的注解 @Bean

这个注解该如何使用呢 ?

咱们把之前使用配置方式管理的数据源使用注解再来一遍,通过这个案例来学习下 @Bean 的使用。

1.环境准备

添加BookDao、BookDaoImpl类

  1. public interface BookDao {
  2. public void save();
  3. }
  4. @Repository
  5. public class BookDaoImpl implements BookDao {
  6. public void save() {
  7. System.out.println("book dao save ..." );
  8. }
  9. }

创建运行类 App

  1. public class App {
  2. public static void main(String[] args) {
  3. AnnotationConfigApplicationContext ctx = new
  4. AnnotationConfigApplicationContext(SpringConfig.class);
  5. }
  6. }

最终创建好的项目结构如下 :

f57b1f1712e24e479b877bafea87909f.png

2.注解开发管理第三方**bean**

在上述环境中完成对Druid数据源的管理,具体的实现步骤为:

步骤**1:导入对应的jar**包

  1. <dependency>
  2. <groupId>com.alibaba</groupId>
  3. <artifactId>druid</artifactId>
  4. <version>1.1.16</version>
  5. </dependency>

步骤 2: 在配置类中添加一个方法

注意该方法的返回值就是要创建的 Bean 对象类型

  1. @Configuration
  2. public class SpringConfig {
  3. public DataSource dataSource(){
  4. DruidDataSource ds = new DruidDataSource();
  5. ds.setDriverClassName("com.mysql.jdbc.Driver");
  6. ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
  7. ds.setUsername("root");
  8. ds.setPassword("root");
  9. return ds;
  10. }
  11. }

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

@Bean 注解的作用是将方法的返回值制作为 Spring 管理的一个 bean 对象

  1. @Configuration
  2. public class SpringConfig {
  3. @Bean
  4. public DataSource dataSource(){
  5. DruidDataSource ds = new DruidDataSource();
  6. ds.setDriverClassName("com.mysql.jdbc.Driver");
  7. ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
  8. ds.setUsername("root");
  9. ds.setPassword("root");
  10. return ds;
  11. }
  12. }

注意 : 不能使用 DataSource ds = new DruidDataSource()

因为 DataSource 接口中没有对应的 setter 方法来设置属性。

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

  1. public class App {
  2. public static void main(String[] args) {
  3. AnnotationConfigApplicationContext ctx = new
  4. AnnotationConfigApplicationContext(SpringConfig.class);
  5. DataSource dataSource = ctx.getBean(DataSource.class);
  6. System.out.println(dataSource);
  7. }
  8. }

至此使用 @Bean 来管理第三方 bean 的案例就已经完成。

如果有多个 bean 要被 Spring 管理,直接在配置类中多些几个方法,方法上添加 @Bean 注解即可。

ff1c8cb9beeb458f8c18fa8f74c3fe24.png

3.引入外部配置类

如果把所有的第三方bean都配置到Spring的配置类SpringConfig中,虽然可以,但是不利于代码阅 读和分类管理,所有我们就想能不能按照类别将这些bean配置到不同的配置类中?

对于数据源的 bean, 我们新建一个 JdbcConfig 配置类,并把数据源配置到该类下。

  1. public class JdbcConfig {
  2. @Bean
  3. public DataSource dataSource(){
  4. DruidDataSource ds = new DruidDataSource();
  5. ds.setDriverClassName("com.mysql.jdbc.Driver");
  6. ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
  7. ds.setUsername("root");
  8. ds.setPassword("root");
  9. return ds;
  10. }
  11. }

现在的问题是,这个配置类如何能被 Spring 配置类加载到,并创建 DataSource 对象在 IOC 容器中 ?

针对这个问题,有两个解决方案 :

1.使用包扫描引入

步骤**1:Spring**的配置类上添加包扫描

  1. @Configuration
  2. @ComponentScan("com.itheima.config")
  3. public class SpringConfig {
  4. }

步骤 2: JdbcConfig 上添加配置注解

JdbcConfig 类要放入到 com.itheima.config 包下,需要被 Spring 的配置类扫描到即可

  1. @Configuration
  2. public class JdbcConfig {
  3. @Bean
  4. public DataSource dataSource(){
  5. DruidDataSource ds = new DruidDataSource();
  6. ds.setDriverClassName("com.mysql.jdbc.Driver");
  7. ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
  8. ds.setUsername("root");
  9. ds.setPassword("root");
  10. return ds;
  11. }
  12. }

步骤 3: 运行程序

依然能获取到 bean 对象并打印控制台。

这种方式虽然能够扫描到,但是不能很快的知晓都引入了哪些配置类,所有这种方式不推荐使用。

#

2.使用@Import引入

方案一实现起来有点小复杂, Spring 早就想到了这一点,于是又给我们提供了第二种方案。

这种方案可以不用加 @Configuration 注解,但是必须在 Spring 配置类上使用 @Import 注解手动引入

需要加载的配置类

步骤 1: 去除 JdbcConfig 类上的注解

  1. public class JdbcConfig {
  2. @Bean
  3. public DataSource dataSource(){
  4. DruidDataSource ds = new DruidDataSource();
  5. ds.setDriverClassName("com.mysql.jdbc.Driver");
  6. ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
  7. ds.setUsername("root");
  8. ds.setPassword("root");
  9. return ds;
  10. }
  11. }

步骤 2: Spring 配置类中引入

  1. @Configuration
  2. //@ComponentScan("com.itheima.config")
  3. @Import({JdbcConfig.class})
  4. public class SpringConfig {
  5. }

注意**:**

扫描注解可以移除

@Import 参数需要的是一个数组,可以引入多个配置类。

@Import 注解在配置类中只能写一次,下面的方式是 不允许的

  1. @Configuration
  2. //@ComponentScan("com.itheima.config")
  3. @Import(JdbcConfig.class)
  4. @Import(Xxx.class)
  5. public class SpringConfig {
  6. }

03a7609b74214f27959aed3f81517569.png

4.注解开发实现为第三方**bean**注入资源

在使用 @Bean 创建 bean 对象的时候,如果方法在创建的过程中需要其他资源该怎么办 ?

这些资源会有两大类,分别是 简单数据类型 和 引用数据类型 。

1.简单数据类型

对于下面代码关于数据库的四要素不应该写死在代码中,应该是从 properties 配置文件中读取。如

何来优化下面的代码 ?

  1. public class JdbcConfig {
  2. @Bean
  3. public DataSource dataSource(){
  4. DruidDataSource ds = new DruidDataSource();
  5. ds.setDriverClassName("com.mysql.jdbc.Driver");
  6. ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
  7. ds.setUsername("root");
  8. ds.setPassword("root");
  9. return ds;
  10. }
  11. }

注入简单数据类型步骤

步骤 1: 类中提供四个属性

  1. public class JdbcConfig {
  2. private String driver;
  3. private String url;
  4. private String userName;
  5. private String password;
  6. @Bean
  7. public DataSource dataSource(){
  8. DruidDataSource ds = new DruidDataSource();
  9. ds.setDriverClassName("com.mysql.jdbc.Driver");
  10. ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
  11. ds.setUsername("root");
  12. ds.setPassword("root");
  13. return ds;
  14. }
  15. }

步骤 2: 使用 @Value 注解引入值

  1. public class JdbcConfig {
  2. //1.定义一个方法获得要管理的对象
  3. @Value("com.mysql.jdbc.Driver")
  4. private String driver;
  5. @Value("jdbc:mysql://localhost:3306/spring_db")
  6. private String url;
  7. @Value("root")
  8. private String userName;
  9. @Value("root")
  10. private String password;
  11. //2.添加@Bean,表示当前方法的返回值是一个bean
  12. @Bean
  13. public DataSource dataSource(){
  14. DruidDataSource ds = new DruidDataSource();
  15. ds.setDriverClassName(driver);
  16. ds.setUrl(url);
  17. ds.setUsername(userName);
  18. ds.setPassword(password);
  19. return ds;
  20. }
  21. }

扩展

现在的数据库连接四要素还是写在代码中,需要做的是将这些内容提

取到 jdbc.properties 配置文件,大家思考下该如何实现 ?

1.resources 目录下添加 jdbc.properties

  1. 配置文件中提供四个键值对分别是数据库的四要素

  2. 使用 @PropertySource 加载 jdbc.properties 配置文件

  3. 修改 @Value 注解属性的值,将其修改为 ${key} , key 就是键值对中的键的值

2.引用数据类型

假设在构建 DataSource 对象的时候,需要用到 BookDao 对象,该如何把 BookDao 对象注入进方法内让其使用呢?

  1. public class JdbcConfig {
  2. @Bean
  3. public DataSource dataSource(){
  4. DruidDataSource ds = new DruidDataSource();
  5. ds.setDriverClassName("com.mysql.jdbc.Driver");
  6. ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
  7. ds.setUsername("root");
  8. ds.setPassword("root");
  9. return ds;
  10. }
  11. }

注入引用数据类型步骤

步骤 1: SpringConfig 中扫描 BookDao

扫描的目的是让 Spring 能管理到 BookDao, 也就是说要让 IOC 容器中有一个 bookDao 对象

  1. @Configuration
  2. @ComponentScan("com.itheima.dao")
  3. @Import({JdbcConfig.class})
  4. public class SpringConfig {
  5. }

步骤 2: JdbcConfig 类的方法上添加参数

  1. @Bean
  2. public DataSource dataSource(BookDao bookDao){
  3. System.out.println(bookDao);
  4. DruidDataSource ds = new DruidDataSource();
  5. ds.setDriverClassName(driver);
  6. ds.setUrl(url);
  7. ds.setUsername(userName);
  8. ds.setPassword(password);
  9. return ds;
  10. }

引用类型注入只需要为 bean 定义方法设置形参即可,容器会根据类型自动装配对象。

步骤 3: 运行程序

cf56b95181074f1c9b5eac398f58a5f8.png

三、注解开发总结

39cf178923964e5fb52015c6dc7e039d.png

发表评论

表情:
评论列表 (有 0 条评论,187人围观)

还没有评论,来说两句吧...

相关阅读

    相关 spring 注解开发

    spring 注解开发 注解:为了代替配置文件,让配置信息和java代码看起来更直观 (注,JDK1.8和spring4.0以上才兼容) 也起解释说明和检查的作用,