【Spring框架】一文带你吃透基于注解的DI技术详细教程

news2025/7/25 6:44:27

本文目录

文章目录

      • 本文目录
  • 💖基于注解的DI
    • ✨概念
    • ✨@[Component](https://so.csdn.net/so/search?q=Component&spm=1001.2101.3001.7020)注解创建对象
    • ✨声明组件扫描器
    • ✨创建对象的四个注解
    • ✨扫描多个包的三种方式
    • ✨@Value简单类型属性赋值
    • ✨@Value使用外部属性配置文件
    • ✨@Autowired引用类型属性赋值
      • 💫byType自动注入
      • 💫byName自动注入
      • 💫required属性
    • ✨@Resource引用类型属性赋值

💖基于注解的DI

✨概念

基于注解的DI:使用spring提供的注解,完成java对象创建,属性赋值。

注解使用的核心步骤:
1.在源代码加入注解,例如@Component。
2.在spring的配置文件,加入组件扫描器的标签。

✨@Component注解创建对象

@Component: 表示创建对象,对象放到容器中。 作用是

  •   属性:value ,表示对象名称,也就是bean的id属性值
    
    
  •   位置:在类的上面,表示创建此类的对象。
    
    
 @Component(value = "myStudent") 等同于
< bean id="myStudent" class="com.ba01.Student" />
12
//使用value 指定对象的名称
//@Component(value = "myStudent")
//省略value
@Component("myStudent")

//没有提供自定义对象名称, 使用框架的默认对象名称:类名首字母小写
//@Component
public class Student {

    private String name;
    private int age;

    public Student() {
        System.out.println("Student无参数构造方法");
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}


✨声明组件扫描器

声明组件扫描器:使用注解必须加入这个语句。

<context:component-scan base-package="注解所在的包名"/>

    component-scan:翻译过来是组件扫描器,组件是java对象。
        属性: base-package 注解在你的项目中的包名。
              框架会扫描这个包和子包中的所有类,找类中的所有注解。
              遇到注解后,按照注解表示的功能,去创建对象, 给属性赋值。

认识了组件扫描器,然后我们来到Spring配置文件来使用它

<?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">

    <!--声明组件扫描器:使用注解必须加入这个语句
        component-scan:翻译过来是组件扫描器,组件是java对象。
            属性: base-package 注解在你的项目中的包名。
                  框架会扫描这个包和子包中的所有类,找类中的所有注解。
                  遇到注解后,按照注解表示的功能,去创建对象, 给属性赋值。
    -->
    <context:component-scan base-package="com.b01"/>

</beans>

注意:最上面的都是一些需要的约束文件,当你把组件扫描器写上去后,也会自动的添加对应的约束文件。

那么接下来我们创建一个测试类,进行测试。

public class MyTest {

    @Test
    public void test01(){
        String config="applicationContext.xml";
        ApplicationContext ctx = new ClassPathXmlApplicationContext(config);

		//后面的myStudent是上面@Component注解创建对象时设置的对象名
        Student student = (Student) ctx.getBean("myStudent");

        System.out.println("student=="+student);
    }
}


✨创建对象的四个注解

经过刚刚的学习,我们已经了解了@Component注解创建对象的使用方法,那么还有其它的相关注解吗?当然有,下面我们将介绍的是和@Component功能相同的创建对象的注解。

\1. @Repository : 放在dao接口的实现类上面,表示创建dao对象,持久层对象,能访问数据库。

2).@Service : 放在业务层接口的实现类上面, 表示创建业务层对象, 业务层对象有事务的功能。

3.@Controller:放在控制器类的上面,表示创建控制器对象。 属于表示层对象。控制器对象能接受请求,把请求的处理结果显示给用户。

以上四个注解都能创建对象,但是@Repository @Service @Controller有角色说明, 表示对象是分层的。

✨扫描多个包的三种方式

<?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">

    <!--声明组件扫描器:使用注解必须加入这个语句
        component-scan:翻译过来是组件扫描器,组件是java对象。
            属性: base-package 注解在你的项目中的包名。
                  框架会扫描这个包和子包中的所有类,找类中的所有注解。
                  遇到注解后,按照注解表示的功能,去创建对象, 给属性赋值。
    -->
    <context:component-scan base-package="com.b01"/>

    <!--扫描多个包的三种方式-->
    <!--第一种,使用多次组件扫描器-->
    <context:component-scan base-package="com.b01"/>
    <context:component-scan base-package="com.b02"/>

    <!--第二种,使用分隔符( ;或,),指定多个包-->
    <context:component-scan base-package="com.b01;com.b02"/>

    <!--第三种:指定父包-->
    <context:component-scan base-package="com"/>
</beans>

✨@Value简单类型属性赋值

@Value: 简单类型属性赋值
属性:value 简单类型属性值
位置:1.在属性定义的上面 ,无需set方法,推荐使用。2.在set方法的上面。

在属性定义的上面定义

package com.bjpowernode.ba02;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;


@Component("myStudent")
public class Student {
    @Value(value = "李四")
    private String name ;
    //括号里面的value也可以省略
    @Value("20")
    private int age;

    public Student() {
        System.out.println("Student无参数构造方法");
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}


第二种方式:在set方法的上面

package com.bjpowernode.ba02;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;


@Component("myStudent")
public class Student {
    private String name ;
    private int age;
    public Student() {
        System.out.println("Student无参数构造方法");
    }

    @Value("22")
    public void setAge(int age) {
        System.out.println("setAge===="+age);
        this.age = age;
    }
    
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}


✨@Value使用外部属性配置文件

这里我创建了一个名为myconf.properties的配置文件

在这里插入图片描述

然后在配置文件输入相应的内容。
在这里插入图片描述
然后我们打开spring配置文件,在spring文件中读取使用它

<?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">

    <!--声明组件扫描器:使用注解必须加入这个语句
        component-scan:翻译过来是组件扫描器,组件是java对象。
            属性: base-package 注解在你的项目中的包名。
                  框架会扫描这个包和子包中的所有类,找类中的所有注解。
                  遇到注解后,按照注解表示的功能,去创建对象, 给属性赋值。
    -->
    <context:component-scan base-package="com.b01"/>


    <!--读取外部的属性配置文件
        property-placeholder:读取properties这样的文件
    -->
    <context:property-placeholder location="classpath:/myconf.properties" />
</beans>

注意:location=“classpath:/类路径”

下一步我们开始还有外部文配置件。

语法 :@Value(${"key"})

@Component("myStudent")
public class Student {
    //使用外部属性文件中的数据,语法 @Value(${"key"})
    @Value("${myname}")
    private String name ;

    private int age;

    public Student() {
        System.out.println("Student无参数构造方法");
    }


    public void setName(String name) {
        this.name = name;
    }
    //使用外部属性文件中的数据
    @Value("${myage}")
    public void setAge(int age) {
        System.out.println("setAge===="+age);
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}


✨@Autowired引用类型属性赋值

 * @Autowired: spring框架提供的,给引用类型赋值的,使用自动注入原理。
 *             支持byName,byType。默认是byType.

💫byType自动注入

  •   位置:1)在属性定义的上面,无需set方法,推荐使用
    
    
  •       2)在set方法的上面
    
    

创建一个School类

@Component("mySchool")
public class School {
    @Value("安徽大学")
    private String name;

    @Value("安徽的合肥市")
    private String address;

    public void setName(String name) {
        this.name = name;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "School{" +
                "name='" + name + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}


在Student类中使用School

@Component("myStudent")
public class Student {

    //默认使用byType
    @Autowired
    private School school;

    public Student() {
        System.out.println("Student无参数构造方法");
    }


    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", school=" + school +
                '}';
    }
}


Spring配置文件

<?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">

    <context:component-scan base-package="com.bjpowernode.ba07"/>

    <!--读取外部的属性配置文件
        property-placeholder:读取properties这样的文件
    -->
    <context:property-placeholder location="classpath:/myconf.properties" />
</beans>

测试

public class MyTest3 {
    @Test
    public void test01(){
        String config="applicationContext.xml";
        ApplicationContext ctx = new ClassPathXmlApplicationContext(config);

        Student student = (Student) ctx.getBean("myStudent");

        System.out.println("student=="+student);
    }
}

💫byName自动注入

byName自动注入
1.@Autowired:给引用类型赋值。
2.@Qualifer(value=“bean的id”):从容器中找到指定名称的对象,把这个对象赋值给引用类型。

@Component("myStudent")
public class Student {

    //byName
    @Autowired
    @Qualifier("mySchool")
    private School school;

    public Student() {
        System.out.println("Student无参数构造方法");
    }


    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", school=" + school +
                '}';
    }
}

测试

public class MyTest3 {
    @Test
    public void test01(){
        String config="applicationContext.xml";
        ApplicationContext ctx = new ClassPathXmlApplicationContext(config);
        Student student = (Student) ctx.getBean("myStudent");
        System.out.println("student=="+student);
    }
}

💫required属性

 *        属性:required :boolean类型的属性, 默认true
 *             true:spring在启动的时候,创建容器对象时候,会检查引用类型是否赋值成功。
 *                   如果赋值失败, 终止程序执行,并报错。
 *             false:引用类型赋值失败,程序正常执行,不报错。引用类型的值是null

示例:
在这里插入图片描述

✨@Resource引用类型属性赋值

 * 引用类型
 * @Resource: 来自jdk中,给引用类型赋值的,支持byName,byType.默认是byName
 *             spring支持这个注解的使用。
 *      位置:1)在属性定义的上面,无需set方法, 推荐使用
 *            2)在set方法的上面
 *
 *  说明,使用jdk1.8带有@Resource注解, 高于jdk1.8没有这个@Resource,
 *  需要加入一个依赖。
 *    <dependency>
 *       <groupId>javax.annotation</groupId>
 *       <artifactId>javax.annotation-api</artifactId>
 *       <version>1.3.2</version>
 *     </dependency>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/35437.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

外卖项目07---git

git&#xff1a;企业、公司等 目录 一、Git概述 105 1.1Git简介 105 1.2Git下载与安装 105 二、Git代码托管服务 106 2.1常用的Git代码托管服务 106 三、Git常用命令 107 3.1Git全局配置 3.2获取Git仓库 ​编辑 ​编辑 3.3工作区、暂存区、版本库概念 3.4Git工作…

ASPICE系列:顺利通过ASPICE流程软件单元验证(SWE.4)

上次的ASPICE评估是否出了问题而您不知道原因? 或者您马上要进行第一次评估&#xff1f; 本系列文章是关于如何准备ASPICE流程软件单元验证(SWE.4)评估的。我们探究这个过程&#xff0c;预期交付以及评估人员的观点。永远记住一个想法:怎样做才能成功地通过评估? 想要成功通…

【PdgCntEditor】利用PDF目录书签编辑软件PdgCntEditor为PDF型图书快速添加书签的方法

一、给PDF加书签的两种情况 1.1 文字版PDF添加书签的理想情形 假设我们弄到了一本PDF&#xff0c;这个PDF如果是由Word或WPS转化而来&#xff0c;其中的标题也就代表了目录&#xff0c;我们可以用acrobat PDF中的AutuBookmark插件实现自动识别标题为目录的方法来添加书签。 …

『Java安全』利用反射调用MimeLauncher.run()触发RCE

文章目录前言MimeLauncherrun()MimeLauncher()反射调用MimeLauncher.run()触发RCE条件PoC完前言 rt.jar内的sun.net.www.MimeLauncher类的run方法调用了exec 据说可以有效绕过某些免杀&#xff0c;下面分析一下调用过程 MimeLauncher run() 首先&#xff1a;调用了this.m.ge…

古人的名与字、号、讳、谥有什么区别

古人复杂的名字 这个世界上想来是不存在没有名字的人&#xff0c;即便真的有人没名字&#xff0c;也会被外人赠予姓名&#xff0c;比如说一些古人典籍里的“无名氏”&#xff0c;就是专门用来形容那些没有名字也不清楚根脚的人&#xff0c;即便是现如今一些作品不知道作者是谁…

信号与线性时不变系统的傅里叶描述

1、复正弦信号和线性时不变系统的频率相应 卷积积分和卷积和傅里叶变换冲激表示信号正弦表示信号输入信号表示为延迟冲激的加权叠加输入信号为复正弦信号的加权叠加输出可以用卷积的形式来表示输出可以用傅里叶的形式来表示 (1)频率响应Frequency response 线性时不变系统对正…

Java中mybatis的Mpper代理开发的详细使用步骤

目录 前言&#xff1a; 一、全图预览 二、使用步骤 1.pom.xml里面添加依赖包 2.新建统一配置文件&#xff08;俗称数据库连接文件&#xff09; 3.新建项目 4.新建映射文件&#xff08;俗称数据库对应表xml&#xff09; 5.测试 三、文中的全部代码&#xff08;去复制可…

MySQL如何保证主备一致?

1. MySQL主备的基本原理 如下图展示的是基本的主备切换流程&#xff1a; 在状态1中&#xff0c;主库是A&#xff0c;备库是B&#xff0c;所以客户端的读写都直接方法节点A。由于节点B是节点A的备库&#xff0c;所以备库B只是将A的更新都同步过来&#xff0c;本地执行&#x…

皕杰报表使用字体和部署后添加字体

Windows系统 1、打开Win10系统的字体安装文件夹&#xff0c;可以双击打开此电脑-->打开C盘-->打开Windows-->打开Fonts&#xff1b;也可先打开计算机&#xff0c;在计算机地址栏上直接拷贝“C:WindowsFonts”路径。回车打开Win10字体文件夹。 2.下载自己需要的字体。…

数组、链表、栈、队列、树

1. 数组&#xff08;Array&#xff09; 定义&#xff1a;数组是一种 线性表 数据结构&#xff0c;它用一组 连续的内存空间 存储一组具有 相同类型 的数据。 Java中 基本数据类型数组 的存储格式&#xff1a; int arr[] new int[3]; arr[0] 0; arr[1] 1; arr[2] 2;Java中…

拿去吧你,华为出品《看漫画学Python》零基础自学首选~

目前Python在人工智能、机器学习、大数据、数据分析、网络爬虫等领域广泛应用&#xff0c;是非常适合初学者入门和培养编程兴趣的一门语言。相比较其他主流编程语言而言&#xff0c;有更好的可读性&#xff0c;和满足感&#xff0c;上手相对容易。 但是很多零基础的同学不知道…

【C语言】 函数

函数 在计算机科学中&#xff0c;子程序 &#xff0c;一个大型程序中的某部分代码&#xff0c; 由一个或多个语句块组 成。它负责完成某项特定任务&#xff0c;而且相较于其他代 码&#xff0c;具备相对的独立性。 一般会有输入参数并有返回值&#xff0c;提供对过程的封装和细…

元组啊,不就是不可变的列表吗?

B站|公众号&#xff1a;啥都会一点的研究生 相关阅读 整理了几个100%会踩的Python细节坑&#xff0c;提前防止脑血栓 整理了十个100%提高效率的Python编程技巧&#xff0c;更上一层楼 Python-列表&#xff0c;从基础到进阶用法大总结&#xff0c;进来查漏补缺 Python-元组&…

【ABAP】EXIT_SAPLMBMB_001无法Debug调试问题处理

【ABAP】EXIT_SAPLMBMB_001无法Debug调试问题处理 不久前看到SAP Community里面有这样一个问题&#xff0c;可能比较老了&#xff0c;但个人觉得比较新奇&#xff0c;就去做了下面一个测试。 首先通过事务代码“CMOD”对增强“MB_CF001”&#xff08;更新物料凭证时的客户功能出…

《从零开始:机器学习的数学原理和算法实践》chap6

《从零开始&#xff1a;机器学习的数学原理和算法实践》chap6 学习笔记 文章目录6.1 凸函数6.2 梯度下降引入梯度是什么为啥梯度是上升最快的方向捏梯度下降与参数求解梯度下降过程演示6.3 代码实践 梯度下降一元函数的梯度下降多元函数的梯度下降6.1 凸函数 凸集 何为凸集 凸集…

c# 多线程

案例1 单线程与多线程对比 单线程会卡主线程,此时会将ui界面给卡住。而多线程开启以后就好了 不会卡住主线程,且运行速度快,相当于多个同时运动。 单线程按钮 private void singlethread_Click(object sender, EventArgs e){for

Kafka多生产者消费者自动配置

背景 项目中不同的业务可能会使用多个kafka&#xff0c;按默认的Kafka配置&#xff0c;最多是支持消费者和生产者使用不同的Kafka&#xff0c;如果两个生产者使用不同的Kafka则需要自定义配置&#xff0c;生成对应的bean。 解决方案 多生产者&#xff0c;多消费者&#xff0…

PowerDesigner 设置

PowerDesigner 设置前言推荐PowerDesigner 设置简单设置sql反向生成物理模型物理模型创建索引最后前言 以下内容源自自己 仅供学习交流使用 推荐 第11章 数据库的设计规范【2.索引及调优篇】【MySQL高级】 powerdesign 通过sql反向生成ER模型 PowerDesiner 15 在物理模型中…

Python测试框架之unittest和pytest 的区别

一、Unittest Unittest是Python标准库中自带的单元测试框架&#xff0c;Unittest有时候也被称为PyUnit&#xff0c;就像JUnit是Java语言的标准单元测试框架一样&#xff0c;Unittest则是Python语言的标准单元测试框架。 Unittest支持自动化测试&#xff0c;测试用例的初始化、…

FFN -> GLU -> GAU

1 GLU GLU的起源是2016年由Yann N. Dauphin在 论文:Language Modeling with Gated Convolutional Networks 在语言模型的建模方法上相比于循环神经网络更具有竞争力&#xff0c;提出了一种简单的线性门控单元来堆叠卷积层从而使得文本中的token可以并行化处理来获得上下文的语义…