【SpringFramework】Spring IoC-基于注解的实现

简介: 本文主要记录基于Spring注解实现IoC容器和DI相关知识。

注解的基础知识,请查阅 (四)【乙】Java注解

一、启用组件自动扫描

(1)使用注解管理Bean,第一步需要开启组件自动扫描

<?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  http://www.springframework.org/schema/context/spring-context.xsd">
    <!--开启组件扫描功能-->
    <!--1. 基本方式:全包扫描-->
    <context:component-scan base-package="com.sheeprunner.spring.c.ioc_annotation" />
</beans>

(2)关于context:component-scan的几种扫描方式

  1. 基本方式:全包扫描
<context:component-scan base-package="com.sheeprunner.spring.c.ioc_annotation" />
  1. 排除指定组件:context:exclude=filter type="annotation"/"assignable" expression="需排除包路径"
<context:component-scan base-package="com.sheeprunner.spring.c.ioc_annotation">
    <!-- context:exclude-filter标签:指定排除规则 -->
    <!-- 
         type:设置排除或包含的依据
        type="annotation",根据注解排除,expression中设置要排除的注解的全类名
        type="assignable",根据类型排除,expression中设置要排除的类型的全类名
    -->
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    <!--<context:exclude-filter type="assignable" expression="com.atguigu.spring6.controller.UserController"/>-->
</context:component-scan>
  1. 仅扫描指定组件:context:include=filter type="annotation"/"assignable" expression="需扫描包路径"
<context:component-scan base-package="com.atguigu" use-default-filters="false">
    <!-- context:include-filter标签:指定在原有扫描规则的基础上追加的规则 -->
    <!-- use-default-filters属性:取值false表示关闭默认扫描规则 -->
    <!-- 此时必须设置use-default-filters="false",因为默认规则即扫描指定包下所有类 -->
    <!-- 
         type:设置排除或包含的依据
        type="annotation",根据注解排除,expression中设置要排除的注解的全类名
        type="assignable",根据类型排除,expression中设置要排除的类型的全类名
    -->
    <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    <!--<context:include-filter type="assignable" expression="com.atguigu.spring6.controller.UserController"/>-->
</context:component-scan>

(3)使用注解定义Bean

Spring提供了四个注解,直接标注在Java类上,用于将这些类定义为Spring Bean。

  • @Component:用于Spring中的Bean,是一个泛华的概念,进表示容器中的一个组件(Bean),可用于任何层次的类上,例如Service/Dao/Controller
  • @Repository:用于数据访问层(Dao层)的类,功能与@Component相同
  • @Service:用于业务层(Service层)的类,功能与@Component相同
  • @Controller:用于控制层(Controller层)的类,功能与@Component相同

(4)使用注解装配Bean

  1. @AutoWired
package org.springframework.beans.factory.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
    boolean required() default true;
}
  • 默认根据类型装配(byType)
  • 该注解可以用在构造方法、方法、参数、字段、注解类型上,甚至如果只有一个构造函数,则该注解可以省略
  • required属性:默认为true,表示被注入的Bean必须存在,否则报错;如果required属性设置为false,表示注入Bean存在或不存在都没关系,存在就注入,不存在也不报错
  1. @Qualifier
  • 如果存在多个同类型的Bean,则使用@Qualifier指定Bean的名称,例如@Qualifier("userDao")
  • @Qualifier("")使用名称进行装配(byName)
  • 该注解搭配@Autowired注解一起使用,也可以在Bean上使用@Primary指定优先级

当存在两个Bean,而没有用@Qualifier注解指定时,编译时抛出如下异常:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'bookController' defined in file [D:\SheepRunner\GitProjects\springexecute\Cspring_ioc_annotation\target\classes\com\sheeprunner\spring\c\ioc_annotation\controller\BookController.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'bookServiceImpl': Unsatisfied dependency expressed through method 'setBookDao' parameter 0; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.sheeprunner.spring.c.ioc_annotation.dao.BookDao' available: expected single matching bean but found 2: bookDaoImpl,bookDaoRedisImpl
  1. @Resource

@Resource注解也可以完成属性注入。那它和@Autowired注解有什么区别?

  • @Resource注解是JDK扩展包中的,也就是说属于JDK的一部分。所以该注解是标准注解,更加具有通用性。(JSR-250标准中制定的注解类型。JSR是Java规范提案。)
  • @Autowired注解是Spring框架自己的。
  • @Resource注解默认根据名称装配byName,未指定name时,使用属性名作为name。通过name找不到的话会自动启动通过类型byType装配。
  • @Autowired注解默认根据类型装配byType,如果想根据名称装配,需要配合@Qualifier注解一起用。
  • @Resource注解用在属性上、setter方法上。
  • @Autowired注解用在属性上、setter方法上、构造方法上、构造方法参数上。

@Resource注解属于JDK扩展包,所以不在JDK当中,需要额外引入以下依赖:【如果是JDK8的话不需要额外引入依赖。高于JDK11或低于JDK8需要引入以下依赖。

①场景一:根据name注入

修改UserDaoImpl类

package com.atguigu.spring6.dao.impl;
import com.atguigu.spring6.dao.UserDao;
import org.springframework.stereotype.Repository;
@Repository("myUserDao")
public class UserDaoImpl implements UserDao {
    @Override
    public void print() {
        System.out.println("Dao层执行结束");
    }
}
②场景二:name未知注入

修改UserDaoImpl类

package com.atguigu.spring6.dao.impl;
import com.atguigu.spring6.dao.UserDao;
import org.springframework.stereotype.Repository;
@Repository("myUserDao")
public class UserDaoImpl implements UserDao {
    @Override
    public void print() {
        System.out.println("Dao层执行结束");
    }
}

@Resource注解:默认byName注入,没有指定name时把属性名当做name,根据name找不到时,才会byType注入。byType注入时,某种类型的Bean只能有一个

(5)全注解

全注解开发就是不再需要Spring配置文件,而是通过一个配置类来替代。
使用@Configuration注解来标识配置类,@ComponentScan("com.sheeprunner.spring.c")表示需要扫描的包路径。

二、原理

  1. 反射
    详见  (四)【甲】Java反射
  2. 注解

详见   (四)【乙】Java注解

  1. 手写实现Spring IoC
    基于注解和反射实现IoC容器,注册组件及装配Bean
目录
相关文章
|
12天前
|
XML Java 数据格式
【SpringFramework】Spring初体验
Spring是一款由Rod Johnson创立的主流Java EE轻量级开源框架,它旨在简化Java企业级项目开发,提供一站式轻量级解决方案,取代复杂的EJB。Spring的核心功能包括IoC(控制反转)和AOP(面向切面编程),并支持非侵入式开发、组件化和容器管理。这篇文章简要描述相关知识点和初始springframework。
104 60
【SpringFramework】Spring初体验
|
7天前
|
Java Spring
【Spring】方法注解@Bean,配置类扫描路径
@Bean方法注解,如何在同一个类下面定义多个Bean对象,配置扫描路径
131 73
|
4天前
|
XML Java 数据格式
【SpringFramework】Spring IoC-基于XML的实现
本文主要讲解SpringFramework中IoC和DI相关概念,及基于XML的实现方式。
94 69
|
9天前
|
设计模式 XML Java
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
本文详细介绍了Spring框架的核心功能,并通过手写自定义Spring框架的方式,深入理解了Spring的IOC(控制反转)和DI(依赖注入)功能,并且学会实际运用设计模式到真实开发中。
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
|
7天前
|
存储 Java Spring
【Spring】获取Bean对象需要哪些注解
@Conntroller,@Service,@Repository,@Component,@Configuration,关于Bean对象的五个常用注解
|
7天前
|
存储 Java 应用服务中间件
【Spring】IoC和DI,控制反转,Bean对象的获取方式
IoC,DI,控制反转容器,Bean的基本常识,类注解@Controller,获取Bean对象的常用三种方式
|
7天前
|
Java Spring
【Spring配置】idea编码格式导致注解汉字无法保存
问题一:对于同一个项目,我们在使用idea的过程中,使用汉字注解完后,再打开该项目,汉字变成乱码问题二:本来a项目中,汉字注解调试好了,没有乱码了,但是创建出来的新的项目,写的注解又成乱码了。
|
29天前
|
存储 缓存 Java
Spring面试必问:手写Spring IoC 循环依赖底层源码剖析
在Spring框架中,IoC(Inversion of Control,控制反转)是一个核心概念,它允许容器管理对象的生命周期和依赖关系。然而,在实际应用中,我们可能会遇到对象间的循环依赖问题。本文将深入探讨Spring如何解决IoC中的循环依赖问题,并通过手写源码的方式,让你对其底层原理有一个全新的认识。
50 2
|
2月前
|
前端开发 Java 开发者
Spring MVC中的请求映射:@RequestMapping注解深度解析
在Spring MVC框架中,`@RequestMapping`注解是实现请求映射的关键,它将HTTP请求映射到相应的处理器方法上。本文将深入探讨`@RequestMapping`注解的工作原理、使用方法以及最佳实践,为开发者提供一份详尽的技术干货。
131 2
|
2月前
|
前端开发 Java Spring
探索Spring MVC:@Controller注解的全面解析
在Spring MVC框架中,`@Controller`注解是构建Web应用程序的基石之一。它不仅简化了控制器的定义,还提供了一种优雅的方式来处理HTTP请求。本文将全面解析`@Controller`注解,包括其定义、用法、以及在Spring MVC中的作用。
57 2