SpringFrameWork之注解类管理Bean

news2024/11/17 17:53:18

1 Bean 注解方式的扫描

1.1 .1注解理解

和 XML 配置文件一样,注解本身并不能执行,注解本身仅仅只是做一个标记,具体的功能是框架检测到注解标记的位置,然后针对这个位置按照注解标记的功能来执行具体操作。

1.1.2 扫描理解

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

使用注解方式:

(1):我们需要在ioc容器里添加的组件上添加上注解,该注解并不能执行,只是后来为了方便让ioc容器知道需要在ioc容器中添加上什么类。

(2):编写配置扫描信息,ioc容器并不是挨着扫描所有包的所有类,来看需要将哪个类添加在容器中,这样效率很慢,我们需要指定哪些包有需要添加的组件。

(3):创建容器....获取bean对象.

1.1.3 应用:

a.准备项目pom文件。

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

b.准备组件类

普通组件

package com.cky;

import org.springframework.stereotype.Component;

@Component
public class Common {
}

Controller组件

package com.cky;

import org.springframework.stereotype.Controller;

@Controller
public class UserCon {
}

Service组件

package com.cky;

import org.springframework.stereotype.Service;

@Service
public class UserSerive {
}

Dao组件 

package com.cky;

import org.springframework.stereotype.Repository;

@Repository
public class UserDao {
}

c.编写配置文件

<?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:直接导入具体的包 1.包要精准,提高性能!
         2.会扫描指定的包和子包内容
         3.多个包可以使用 用逗号分割-->
<!--    <context:component-scan base-package="com.cky"></context:component-scan>-->
    <!--导入固定的注解,但是要注意,我们要设置use-default-filters为false,即让基础包下的不生效,接着在追加规则-->
    <context:component-scan base-package="com.cky" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
    </context:component-scan>
    <!--排除不扫描的组件
        context:exclude-filter标签:指定排除规则 -->
    <!-- type属性:指定根据什么来进行排除,annotation取值表示根据注解来排除 -->
    <!-- expression属性:指定排除规则的表达式,对于注解来说指定全类名即可 -->

<!--    <context:component-scan base-package="com.cky">-->
<!--        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>-->
<!--    </context:component-scan>-->
</beans>

d.测试

public class testdemo {
    @Test
    public void test_01(){
        //实例化容器
        ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("demo01.xml");
        //得到Bean对象
        UserDao userDao=context.getBean("userDao",UserDao.class);
        System.out.println(userDao);
        UserSerive userSerive=context.getBean(UserSerive.class);
        System.out.println(userSerive);
    }
}

1.1.4 组件注解区别:

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

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

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

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

1.1.5 组件beanname 问题

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

默认情况:

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

但是,我们也可以使用value进行配置id

@Repository(value = "userdao")
public class UserDao {
}

1.1.6 总结:

1. 注解方式IoC只是标记哪些类要被Spring管理
2. 最终,我们还需要XML方式或者后面讲解Java配置类方式指定注解生效的包
3. **现阶段配置方式为 注解 (标记)+ XML(扫描)**

2、扩展周期方法和作用域

至于周期方法和作用域具体是什么,可见文章1,在这里不重复介绍。

使用注解的方式来编写周期方法:

A.周期方法声明

public class BeanOne {

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

public class BeanTwo {
  
  @PreDestroy //注解指定销毁方法
  public void cleanup() {
    // 释放资源逻辑
  }
}

B.组件作用域配置

@Scope(scopeName = ConfigurableBeanFactory.SCOPE_SINGLETON) //单例,默认值
@Scope(scopeName = ConfigurableBeanFactory.SCOPE_PROTOTYPE) //多例  二选一

public class BeanOne {

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

注意:单例的话会在容器关闭的时候进行销毁工作,但是多例不会。 

3、Bean属性赋值:引用类型自动配置(DI)

3.1 场景及实例:

UserController 需要 UserService

UserService需要UserDao

a. 准备组件 并在组件中配置 IOC 和DI

package demo03;

import org.springframework.stereotype.Repository;

@Repository
public class UserDao {
    public void show2(){
        System.out.println("Userdao");
    }
}
package demo03;

import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

@Service
public class UserService {
//    @Autowired
//    @Qualifier(value ="userdao")
    @Resource(name = "userdao")
    private UserDao userDao;
    public void show1(){
        userDao.show2();
        System.out.println("UserService");
    }
}
package demo03;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

@Controller
public class UserController {
    @Autowired
    private UserService userService;
    public void show(){
        userService.show1();
        System.out.println("usercontroller");
    }
}

b.编写配置文件 确定扫描哪写包

<?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="demo03"></context:component-scan>
</beans>

c.编写测试代码:

    @Test
    public void test_03(){
        //实例化容器
        ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("demo03.xml");
        //得到Bean对象
        UserController userController=context.getBean(UserController.class);
        userController.show();

}

d.结果:

3.2 对实例讲解

3.2.1 @Autowired 注解

在使用注解方式时,我们没必要像 XML方式那样,在组件中写上setter,使用<bean>之后使用配置的方式进行DI配置。只需要在成员变量上加上@Autowired注解即可,不需要提供setXxx()方法。以后我们在项目中的正式用法就是这样。

A.该注解可添加在成员变量上(最常用)

@Service("smallDog")
public class SoldierService {
    
    @Autowired
    private SoldierDao soldierDao;
    
    public void getMessage() {
        soldierDao.getMessage();
    }
}

B. 构造方法上

@Controller(value = "tianDog")
public class SoldierController {
    
    private SoldierService soldierService;
    
    @Autowired
    public SoldierController(SoldierService soldierService) {
        this.soldierService = soldierService;
    }
    ……

C. Set方法上

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

    private SoldierService soldierService;

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

3.2.2 工作流程

- 首先根据所需要的组件类型到 IOC 容器中查找
    - 能够找到唯一的 bean:直接执行装配
    - 如果完全找不到匹配这个类型的 bean:装配失败
    - 和所需类型匹配的 bean 不止一个
        - 没有 @Qualifier 注解:根据 @Autowired 标记位置成员变量的变量名作为 bean 的 id 进行匹配
            - 能够找到:执行装配
            - 找不到:装配失败
        - 使用 @Qualifier 注解:根据 @Qualifier 注解中指定的名称作为 bean 的id进行匹配
            - 能够找到:执行装配
            - 找不到:装配失败 

只有一个bean的我们不讨论,这里仅需要根据类型需查找ioc中是否有该组件类型即可。

下边讨论一下不止一个bean。

比如一个接口,我们的两个类都实现了该接口。那么这两个类与该接口 的instanceof 都为true。

在我们在其它组件中注入该接口时,ioc容器会发现有两个类 都是该接口的实例化组件,此时就会报错,解决方法①:我们可以使用bean id的方式来找到其中一个实例化组件,就是在编写该接口变量时,接口变量的名字写成其中一个组件的id,那么就会根据该id确定其中的一个实例化组件。

方法②:我们可以 在该接口变量的上方,通过@Autowried@Qualifier注解,在后者里边添加上value属性,即我们要选用实例化组件的id。

方法③:我们可以使用@Resource 注解,不过该注解是java的一种规范化技术,

我们在使用该注解时,需要导入依赖

<dependency>
    <groupId>jakarta.annotation</groupId>
    <artifactId>jakarta.annotation-api</artifactId>
    <version>2.1.1</version>
</dependency>

3.2.3 @Resource与@Autowried 区别

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

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

总结:

(1)@Autowired注解默认根据类型装配,如果类型没有,则报错。如果想根据名称装配,需要配合@Qualifier注解一起用。一旦使用名称来装配,即使类型有,但是名称不匹配也会报错。

(2)@Resource注解默认根据Bean名称装配,如果Bean名称找不到,则会启动根据类型来装配。如果指定了名称,类型有但是名称不匹配就会报错。如果没有启动名称匹配,则后续会在进行类型匹配。

4、使用@Value注解

对于基本数据类型的DI

对于基本数据类型

我们可以直接赋值的方式

比如

private int age=8;

同时我们也可以使用@Value注解 这个注解主要是为了配置外部属性

a.配置组件

package demo04;
 @Service 
public class JavaBean 
{ private int age=8; 
 @Value("${url}") 
private String url; 
 @Value("${a:cui}") 冒号后边是默认值,即配置中如果没有a属性的话,就自动赋值为冒号后边的值。 
private String name;
 @Override public String toString() 
{ return "JavaBean{" + "age=" + age + ", url='" + url + '\'' + ", name='" + name + '\'' + '}'; } }


b. 配置信息 demo04.xml

<?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="demo04">
</context:component-scan>
//把配置的包导入进来,之后在该容器中的组件都可以通过{$xxx}来访问xxx属性名的值
<context:property-placeholder location="aoo.properties"></context:property-placeholder>
</beans>

c.一些外部配置文件 aoo,properties

 5、总结:

基于注解的方式,我们还是需要xml配置文件

xml配置:①扫描包的配置 ②外部配置包的部署 ③第三方组件 如jdbctemplate等

之后我们将学习配置类的方式,使用上配置类我们就可以不用在使用xml的方式来完成上边三种配置了。

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

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

相关文章

怎么使用LightPicture开源搭建图片管理系统并远程访问?【搭建私人图床】

文章目录 1.前言2. Lightpicture网站搭建2.1. Lightpicture下载和安装2.2. Lightpicture网页测试2.3.cpolar的安装和注册 3.本地网页发布3.1.Cpolar云端设置3.2.Cpolar本地设置 4.公网访问测试5.结语 1.前言 现在的手机越来越先进&#xff0c;功能也越来越多&#xff0c;而手机…

【单片机毕业设计】【hj-006-1】烟雾、甲烷气体检测 | 空气质量检测 | 有害气体检测

一、基本介绍 项目名&#xff1a; 基于单片机的烟雾、甲烷气体检测系统设计 基于单片机的空气质量检测 系统设计 基于单片机的有害气体检测系统设计 项目编号&#xff1a;mcuclub-hj-006-1 单片机类型&#xff1a;STM32F103C8T6 具体功能&#xff1a; 1、通过MQ-2检测烟雾值&…

人防行业通信系统

深圳市华脉智联科技有限公司是一家拥有核心自主知识产权的高科技企业&#xff0c;公司致力于公网对讲、融合通信、应急通信、执法调度等领域的系统和技术的开发和探讨&#xff0c;为行业用户提供一整套以通信为基础&#xff0c;软硬件结合的实战解决方案。华脉智联始终坚持将解…

2023年淘宝天猫双十一什么时候开始?天猫双十一满减活动规则和优惠力度是多少

2023年天猫淘宝双十一活动将在10月24日20时开启&#xff0c;同时包含两波正式开买时间点&#xff0c;分别为10月31日20时和11月10日20时。 一、2023天猫淘宝双十一活动时间表 第一波 (1)预售 预售预热&#xff1a;2023年10月24日14:00:00-2023年10月24日19:59:59 定金*支付…

工控机通过Profinet转Modbus RTU网关与报警控制仪通讯配置案例

本文将以工控机通过Profinet转Modbus RTU网关&#xff08;XD-MDPN100&#xff09;与报警控制仪通讯的实际案例为例&#xff0c;介绍Profinet转Modbus RTU网关&#xff08;XD-MDPN100&#xff09;在工业通信的应用。 在某个生产车间的报警系统中&#xff0c;报警控制仪是起到监…

嘉立创新建元件封装进行DRC检测发现无封装

新建元件和封装 元件就是原理图中放的主要是引脚对应正确&#xff0c;封装就是pcb设计中对应元件实际放置的焊盘。所以元件和封装需要关联 关联的时候需要注意 有时候出现元件无封装的情况&#xff0c;一般是因为没有管理封装&#xff08;简单失误&#xff09;或者是关联封…

【NPM】vuex 数据持久化库 vuex-persistedstate

在 GitHub 上找到&#xff1a;vuex-persistedstate。 安装 npm install --save vuex-persistedstate使用 import { createStore } from "vuex"; import createPersistedState from "vuex-persistedstate";const store createStore({// ...plugins: [cr…

echarts设置竖向不同区间范围颜色,并且x轴自定义轴线刻度范围

需求&#xff1a;设置竖向范围区间&#xff0c;不同范围区间颜色不同并且提示信息不同&#xff0c;之后修改x轴的固定间距范围&#xff0c;让0-200-400-600改为0-340-476-754这种&#xff0c;在这我是markLine的方式实现的&#xff0c;这边我还用到x轴的翻转所以显示的是镜像的…

视频SDK开发,多平台SDK快速接入

随着科技的不断发展&#xff0c;视频已经成为了企业业务中不可或缺的一部分。无论是在线教育、企业培训还是产品展示&#xff0c;视频都发挥着至关重要的作用。为了满足企业对视频应用的需求&#xff0c;美摄视频SDK应运而生&#xff0c;为企业提供了一站式的视频解决方案。 一…

聊一聊Spring 事务的相关操作

Java全能学习面试指南&#xff1a;https://javaxiaobear.cn 1、JdbcTemplate 1.1、简介 Spring 框架对 JDBC 进行封装&#xff0c;使用 JdbcTemplate 方便实现对数据库操作 1.2、准备工作 ①搭建子模块 搭建子模块&#xff1a;spring-jdbc-tx ②加入依赖 <dependenci…

21天打卡进阶Python基础操作

python21天打卡day3-python数据类型 #int a2 print(a) print(type(a)) #float a2.2 print(a) print(type(a)) #string anihao print(a) print(type(a)) #list a[1,2,3,4] print(a) print(a[0]) print(type(a)) #元组 a(1,2) print(a) print(type(a)) #字典dict a{name:yangyal,…

Unity3D 如何制作带厚度的透明图片详解

Unity3D是一款功能强大的游戏开发引擎&#xff0c;可以实现各种复杂的游戏效果。本文将详细介绍如何使用Unity3D制作带厚度的透明图片&#xff0c;并提供代码实现。 对惹&#xff0c;这里有一个游戏开发交流小组&#xff0c;希望大家可以点击进来一起交流一下开发经验呀&#…

react antd实现upload上传文件前form校验,同时请求带data

最近的需求&#xff0c;两个下拉框是必填项&#xff0c;点击上传按钮&#xff0c;如果有下拉框没选要有提示&#xff0c;如图 如果直接使用antd的Upload组件&#xff0c;一点击文件选择的窗口就打开了&#xff0c;哪怕在Button里再加点击事件&#xff0c;也只是&#xff08;几乎…

AutoCAD 2022 for Mac/Windows升级您的设计工具,提升工作效率

Autodesk AutoCAD 2022 是设计行业最流行的计算机辅助设计 (CAD) 软件之一。这款软件由Autodesk公司开发&#xff0c;它提供了强大的功能&#xff0c;从基本的设计和修改工具&#xff0c;到复杂的3D建模和渲染&#xff0c;一切尽在掌握。通过其直观的用户界面和不断更新的功能&…

mmDetection3D避坑指南

1 运行test.py报CUDA类错误 包括API之类的错误&#xff0c;是因为KITTI数据集有损坏&#xff0c;需要重新导入完整KITTI官方数据集,再根据官方步骤用create_data.py处理

memcpy内存拷贝函数

目录 一、memcpy内存拷贝函数 注意事项 二、memcpy与strcpy对比 三、模拟实现memcpy函数 四、memcpy函数不能进行两块存在内存重叠的空间的内存拷贝 五、改进my_memcpy函数 一、memcpy内存拷贝函数 头文件&#xff1a;string.h 函数原型&#xff1a;void* memcpy(void* …

Acwing 3306.装珠饰(十一届蓝桥java/py组J题)--dp之分组背包(hard)

分析&#xff1a; 6件装备作为一个整体去看待&#xff01;&#xff01;&#xff01;加的效果是看总的装备数目 分组背包的一个特点&#xff1a;每一个组里面只能取出一个物品&#xff0c;这里是把抽象成不同的方案数(有点多重背包的二进制处理方法的感觉。) 代码实现&#xff1…

ubuntu 20.04 passwd 指令不能使用

Linux 更改用户密码报Changing password for user 用户名. passwd: Module is unknown或更改新增用户密码passwd&#xff1a;未知的用户名 报错信息如下&#xff1a; 解决方法&#xff1a; 可以排查 /etc/pam.d/passwd配置文件 注释掉包含pam_passwdqc.so模块的行&#xff0c…

微信小程序之自定义组件(OA项目个人主页及投票)

前言 本期为大家带来微信小程序自定义组件及OA项目的个人主页布局和投票 一.自定义组件 1.学习官网 自定义组件 / 介绍 (qq.com) 2.如何自定义组件 2.1 创建目录 在根目录下依次创建components/tabs&#xff0c;然后在tabs中新建Component 创建好后会自动为我们生成对应的文…

微软Azure OpenAI支持数据微调啦!可打造专属ChatGPT

10月17日&#xff0c;微软在官网宣布&#xff0c;现在可以在Azure OpenAI公共预览版中对GPT-3.5-Turbo、Babbage-002 和Davinci-002模型进行数据微调。 使得开发人员通过自己的数据集&#xff0c;便能打造独一无二的ChatGPT。例如&#xff0c;通过海量医疗数据进行微调&#x…