ioc 注解

159 阅读5分钟

pom.xml的配置

<dependencies>
    <!--spring context依赖-->
    <!--当你引入Spring Context依赖之后,表示将Spring的基础依赖引入了-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>6.0.6</version>
    </dependency>

    <!--junit5测试-->
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-api</artifactId>
        <version>5.3.1</version>
    </dependency>
</dependencies>
  1. 组件添加标记注解

  2. 组件标记注解和区别

    Spring 提供了以下多个注解,这些注解可以直接标注在 Java 类上,将它们定义成 Spring Bean。

    @respository,@service,@controller底层都有@component注解

注解说明
@Component该注解用于描述 Spring 中的 Bean,它是一个泛化的概念,仅仅表示容器中的一个组件(Bean),并且可以作用在应用的任何层次,例如 Service 层、Dao 层等。 使用时只需将该注解标注在相应类上即可。
@Repository该注解用于将数据访问层(Dao 层)的类标识为 Spring 中的 Bean,其功能与 @Component 相同。d
@Service该注解通常作用在业务层(Service 层),用于将业务层的类标识为 Spring 中的 Bean,其功能与 @Component 相同。
@Controller该注解通常作用在控制层(如SpringMVC 的 Controller),用于将控制层的类标识为 Spring 中的 Bean,其功能与 @Component 相同。
    ![](http://heavy_code_industry.gitee.io/code_heavy_industry/assets/img/img017.93fb56c5.png)

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

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

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

    普通组件
/**
 * projectName: com.atguigu.components
 *
 * description: 普通的组件
 */
@Component
public class CommonComponent {
}
    Controller组件
/**
 * projectName: com.atguigu.components
 *
 * description: controller类型组件
 */
@Controller
public class XxxController {
}
    Service组件
/**
 * projectName: com.atguigu.components
 *
 * description: service类型组件
 */
@Service
public class XxxService {
}
    Dao组件
/**
 * projectName: com.atguigu.components
 *
 * description: dao类型组件
 */
@Repository
public class XxxDao {
}

确定配置文件扫描

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="<http://www.springframework.org/schema/beans>"
       xmlns:xsi="<http://www.w3.org/2001/XMLSchema-instance>"
       xmlns:context="<http://www.springframework.org/schema/context>"
       xsi:schemaLocation="<http://www.springframework.org/schema/beans> <http://www.springframework.org/schema/beans/spring-beans.xsd> <http://www.springframework.org/schema/context> <https://www.springframework.org/schema/context/spring-context.xsd>">
    <!-- 配置自动扫描的包 -->
    <!-- 1.包要精准,提高性能!
         2.会扫描指定的包和子包内容
         3.多个包可以使用,分割 例如: com.atguigu.controller,com.atguigu.service等
    -->
    <context:component-scan base-package="com.atguigu.components"/>
  
</beans>

在我们使用 XML 方式管理 bean 的时候,每个 bean 都有一个唯一标识——id 属性的值,便于在其他地方引用。现在使用注解后,每个组件仍然应该有一个唯一标识。

bean 作用域和周期

周期和servlet一样 采用init/destory

  1. 组件作用域配置

    1. Bean作用域概念

      <bean 标签声明Bean,只是将Bean的信息配置给SpringIoC容器!

      在IoC容器中,这些<bean标签对应的信息转成Spring内部 BeanDefinition 对象,BeanDefinition 对象内,包含定义的信息(id,class,属性等等)!

      这意味着,BeanDefinition概念一样,SpringIoC容器可以可以根据BeanDefinition对象反射创建多个Bean对象实例。

      具体创建多少个Bean的实例对象,由Bean的作用域Scope属性指定!

    2. 作用域可选值

取值含义创建对象的时机默认值
singleton在 IOC 容器中,这个 bean 的对象始终为单实例IOC 容器初始化时
prototype这个 bean 在 IOC 容器中有多个实例获取 bean 时
    如果是在WebApplicationContext环境下还会有另外两个作用域(但不常用):
取值含义创建对象的时机默认值
request请求范围内有效的实例每次请求
session会话范围内有效的实例每次会话
3. 作用域配置
@Scope(scopeName = ConfigurableBeanFactory.SCOPE_SINGLETON) //单例,默认值
@Scope(scopeName = ConfigurableBeanFactory.SCOPE_PROTOTYPE) //多例  二选一
public class BeanOne {

  //周期方法要求: 方法命名随意,但是要求方法必须是 public void 无形参列表
  @PostConstruct  //注解制指定初始化方法
  public void init() {
    // 初始化逻辑
  }
}

自动装配

  1. 自动装配实现

    1. 前提

      参与自动装配的组件(需要装配、被装配)全部都必须在IoC容器中。

      注意:不区分IoC的方式!XML和注解都可以!

    2. @Autowired注解

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

    3. 给Controller装配Service

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

    @Autowired
    private SoldierService soldierService;

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

}
  1. 工作流程

    !heavy_code_industry.gitee.io/code_heavy_…

    • 首先根据所需要的组件类型到 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;
  • @Resource使用
@Controller
public class XxxController {
    /**
     * 1. 如果没有指定name,先根据属性名查找IoC中组件xxxService
     * 2. 如果没有指定name,并且属性名没有对应的组件,会根据属性类型查找
     * 3. **可以指定name名称查找!  @Resource(name='test') == @Autowired + @Qualifier(value='test')
     */**
    @Resource
    private XxxService xxxService;

    //@Resource(name = "指定beanName")
    //private XxxService xxxService;

    public void show(){
        System.out.println("XxxController.show");
        xxxService.show();
    }
}

@resource的功能 是@autowwired和@qualifer的结合