Spring IOC容器的理解(六)

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
简介: Spring IOC容器的理解(六)

第四节 基于注解管理bean
第一个实验 [重要]标记与扫描

第二个实验 [重要]自动装配

第三个实验 完全注解开发

第四个实验 整合junit4

第一个实验 [重要]标记与扫描

1、注解的作用①注解②扫描

2、新建Module

3、创建Spring配置文件

4、创建一组组件类

①使用@Component注解标记的普通组件

②使用@Controller注解标记的控制器组件

③使用@Service注解标记的业务逻辑组件

④使用@Repository注解标记的持久化层组件

5、四个典型注解没有本质区别

6、扫描

①情况一:最基本的扫描方式[常用]

②情况二:指定匹配模式

③情况三:指定要排除的组件

④情况四:仅扫描指定组件

7、组件的beanName

①默认情况

②使用value属性指定

第一个实验 [重要]标记与扫描
1、注解的作用
①注解
和 XML 配置文件一样,注解本身并不能执行,注解本身仅仅只是做一个标记,具体的功能是框架检测到注解标记的位置,然后针对这个位置按照注解标记的功能来执行具体操作。

本质上:所有一切的操作都是Java代码来完成的,XML和注解只是告诉框架中的Java代码如何执行。

举例:元旦联欢会要布置教室,蓝色的地方贴上元旦快乐四个字,红色的地方贴上拉花,黄色的地方贴上气球。

班长做了所有标记,同学们来完成具体工作。墙上的标记相当于我们在代码中使用的注解,后面同学们做的工作,相当于框架的具体操作。

②扫描
Spring 为了知道程序员在哪些地方标记了什么注解,就需要通过扫描的方式,来进行检测。然后根据注解进行后续操作。

2、新建Module

<!-- 基于Maven依赖传递性,导入spring-context依赖即可导入当前所需所有jar包 -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.3.1</version>
</dependency>

<!-- junit测试 -->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>


3、创建Spring配置文件

4、创建一组组件类
①使用@Component注解标记的普通组件
package com.atguigu.ioc.component;

import org.springframework.stereotype.Component;

@Component
public class CommonComponent {
}
②使用@Controller注解标记的控制器组件
这个组件就是我们在三层架构中表述层里面,使用的控制器。以前是Servlet,以后我们将会使用Controller来代替Servlet。

package com.atguigu.ioc.component;

import org.springframework.stereotype.Controller;

@Controller
public class SoldierController {
}
③使用@Service注解标记的业务逻辑组件
这个组件就是我们在三层架构中使用的业务逻辑组件。

package com.atguigu.ioc.component;

import org.springframework.stereotype.Service;

@Service
public class SoldierService {

}
④使用@Repository注解标记的持久化层组件
这个组件就是我们以前用的Dao类,但是以后我们整合了Mybatis,这里就变成了Mapper接口,而Mapper接口是由Mybatis和Spring的整合包负责扫描的。

由于Mybatis整合包想要把Mapper接口背后的代理类加入Spring的IOC容器需要结合Mybatis对Mapper配置文件的解析,所以这个事情是Mybatis和Spring的整合包来完成,将来由Mybatis负责扫描,也不使用@Repository注解。

package com.atguigu.ioc.component;

import org.springframework.stereotype.Repository;

@Repository
public class SoldierDao {
}
5、四个典型注解没有本质区别

通过查看源码我们得知,@Controller、@Service、@Repository这三个注解只是在@Component注解的基础上起了三个新的名字。

对于Spring使用IOC容器管理这些组件来说没有区别。所以@Controller、@Service、@Repository这三个注解只是给开发人员看的,让我们能够便于分辨组件的作用。

注意:虽然它们本质上一样,但是为了代码的可读性,为了程序结构严谨我们肯定不能随便胡乱标记。

6、扫描
①情况一:最基本的扫描方式[常用]

<context:component-scan base-package="com.atguigu.ioc.component"/>
从IOC容器中获取bean

@Test
public void testAnnotationcScanBean() {

CommonComponent commonComponent = iocContainer.getBean(CommonComponent.class);

SoldierController soldierController = iocContainer.getBean(SoldierController.class);

SoldierService soldierService = iocContainer.getBean(SoldierService.class);

SoldierDao soldierDao = iocContainer.getBean(SoldierDao.class);

System.out.println("commonComponent = " + commonComponent);
System.out.println("soldierController = " + soldierController);
System.out.println("soldierService = " + soldierService);
System.out.println("soldierDao = " + soldierDao);

}

②情况二:指定匹配模式

<context:component-scan
        base-package="com.atguigu.ioc.component"
        resource-pattern="Soldier*.class"/>

③情况三:指定要排除的组件
或者也可以说指定不扫描的组件

<context:component-scan base-package="com.atguigu.ioc.component">


<!-- context:exclude-filter标签:指定排除规则 -->
<!-- type属性:指定根据什么来进行排除,annotation取值表示根据注解来排除 -->
<!-- expression属性:指定排除规则的表达式,对于注解来说指定全类名即可 -->
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>

</context:component-scan>
④情况四:仅扫描指定组件

<context:component-scan base-package="com.atguigu.ioc.component" use-default-filters="false">


<!-- context:include-filter标签:指定在原有扫描规则的基础上追加的规则 -->
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>

</context:component-scan>
7、组件的beanName
在我们使用XML方式管理bean的时候,每个bean都有一个唯一标识,便于在其他地方引用。现在使用注解后,每个组件仍然应该有一个唯一标识。

①默认情况
类名首字母小写就是bean的id。例如:SoldierController类对应的bean的id就是soldierController。

②使用value属性指定
@Controller(value = "tianDog")
public class SoldierController {
}
当注解中只设置一个属性时,value属性的属性名可以省略:

@Service("smallDog")
public class SoldierService {

}
第二个实验 [重要]自动装配

1、设定情景

①在SoldierController中声明方法

②在SoldierService中声明方法

③在SoldierDao中声明方法

2、自动装配的实现

①前提

②@Autowired注解

[1]给Controller装配Service

[2]给Service装配Dao

3、@Autowired注解其他细节

①标记在其他位置

[1]构造器

[2]setXxx()方法

②@Autowired工作流程

③佛系装配

第二个实验 [重要]自动装配
1、设定情景
SoldierController需要SoldierService
SoldierService需要SoldierDao
同时在各个组件中声明要调用的方法。

①在SoldierController中声明方法
package com.atguigu.ioc.component;

import org.springframework.stereotype.Controller;

@Controller(value = "tianDog")
public class SoldierController {

private SoldierService soldierService;

public void getMessage() {
    soldierService.getMessage();
}


}
②在SoldierService中声明方法
@Service("smallDog")
public class SoldierService {

private SoldierDao soldierDao;

public void getMessage() {
    soldierDao.getMessage();
}

}
③在SoldierDao中声明方法
@Repository
public class SoldierDao {

public void getMessage() {
    System.out.println("I am a soldier");
}


}
2、自动装配的实现
①前提
参与自动装配的组件(需要装配别人、被别人装配)全部都必须在IOC容器中。

②@Autowired注解
在成员变量上直接标记@Autowired注解即可,不需要提供setXxx()方法。以后我们在项目中的正式用法就是这样。

[1]给Controller装配Service

@Controller(value = "tianDog")
public class SoldierController {


@Autowired
private SoldierService soldierService;

public void getMessage() {
    soldierService.getMessage();
}

}
[2]给Service装配Dao

@Service("smallDog")
public class SoldierService {


@Autowired
private SoldierDao soldierDao;

public void getMessage() {
    soldierDao.getMessage();
}

}
3、@Autowired注解其他细节
①标记在其他位置
[1]构造器

@Controller(value = "tianDog")
public class SoldierController {


private SoldierService soldierService;

@Autowired
public SoldierController(SoldierService soldierService) {
    this.soldierService = soldierService;
}
……

[2]setXxx()方法

@Controller(value = "tianDog")
public class SoldierController {

private SoldierService soldierService;

@Autowired
public void setSoldierService(SoldierService soldierService) {
    this.soldierService = soldierService;
}
……

②@Autowired工作流程

首先根据所需要的组件类型到IOC容器中查找

能够找到唯一的bean:直接执行装配

如果完全找不到匹配这个类型的bean:装配失败

和所需类型匹配的bean不止一个

没有@Qualifier注解:根据@Autowired标记位置成员变量的变量名作为bean的id进行匹配

能够找到:执行装配
找不到:装配失败
使用@Qualifier注解:根据@Qualifier注解中指定的名称作为bean的id进行匹配

能够找到:执行装配
找不到:装配失败
@Controller(value = "tianDog")
public class SoldierController {


@Autowired
@Qualifier(value = "maomiService222")
// 根据面向接口编程思想,使用接口类型引入Service组件
private ISoldierService soldierService;

③佛系装配
给@Autowired注解设置required = false属性表示:能装就装,装不上就不装。但是实际开发时,基本上所有需要装配组件的地方都是必须装配的,用不上这个属性。

@Controller(value = "tianDog")
public class SoldierController {

// 给@Autowired注解设置required = false属性表示:能装就装,装不上就不装
@Autowired(required = false)
private ISoldierService soldierService;
相关文章
|
6天前
|
XML Java 数据格式
【SpringFramework】Spring IoC-基于XML的实现
本文主要讲解SpringFramework中IoC和DI相关概念,及基于XML的实现方式。
96 69
|
4天前
|
Java Spring 容器
【SpringFramework】Spring IoC-基于注解的实现
本文主要记录基于Spring注解实现IoC容器和DI相关知识。
37 21
|
11天前
|
设计模式 XML Java
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
本文详细介绍了Spring框架的核心功能,并通过手写自定义Spring框架的方式,深入理解了Spring的IOC(控制反转)和DI(依赖注入)功能,并且学会实际运用设计模式到真实开发中。
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
|
9天前
|
存储 Java 应用服务中间件
【Spring】IoC和DI,控制反转,Bean对象的获取方式
IoC,DI,控制反转容器,Bean的基本常识,类注解@Controller,获取Bean对象的常用三种方式
|
15天前
|
XML Java 数据格式
Spring容器Bean之XML配置方式
通过对以上内容的掌握,开发人员可以灵活地使用Spring的XML配置方式来管理应用程序的Bean,提高代码的模块化和可维护性。
52 6
|
30天前
|
存储 缓存 Java
Spring面试必问:手写Spring IoC 循环依赖底层源码剖析
在Spring框架中,IoC(Inversion of Control,控制反转)是一个核心概念,它允许容器管理对象的生命周期和依赖关系。然而,在实际应用中,我们可能会遇到对象间的循环依赖问题。本文将深入探讨Spring如何解决IoC中的循环依赖问题,并通过手写源码的方式,让你对其底层原理有一个全新的认识。
53 2
|
30天前
|
安全 Java 开发者
Spring容器中的bean是线程安全的吗?
Spring容器中的bean默认为单例模式,多线程环境下若操作共享成员变量,易引发线程安全问题。Spring未对单例bean做线程安全处理,需开发者自行解决。通常,Spring bean(如Controller、Service、Dao)无状态变化,故多为线程安全。若涉及线程安全问题,可通过编码或设置bean作用域为prototype解决。
34 1
|
2月前
|
XML 缓存 Java
搞透 IOC、Spring IOC ,看这篇就够了!
本文详细解析了Spring框架的核心内容——IOC(控制反转)及其依赖注入(DI)的实现原理,帮助读者理解如何通过IOC实现组件解耦,提高程序的灵活性和可维护性。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
|
2月前
|
前端开发 Java Docker
使用Docker容器化部署Spring Boot应用程序
使用Docker容器化部署Spring Boot应用程序
|
2月前
|
Java Docker 微服务
利用Docker容器化部署Spring Boot应用
利用Docker容器化部署Spring Boot应用
54 0