基于注解以及配置类使用SpringIoc

四 基于注解方式使用SpringIoc

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

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

4.1 组件(Bean)的注册

思路: 使用注解标记组件,让spring框架识别注解并管理组件。

由于效率原因,spring框架并不会扫描所有的包,去寻找注解,这样效率很低。所以需要我们去告知spring,我们在那些包内使用了注解或者想要springioc管理的组件。

所以组件的注册分为两步: 1.添加注解,2.告知spring添加注解的包,即包扫描

ps:在使用第三方类的时候,如JdbcTemplate类,就无法使用注解去注册,还是要使用xml方式配置

4.1.1添加注解

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

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

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

与xml注册bean,相比较:

@Component
public class CommonComponent {
}
//还需要告诉spring,在哪里使用了注解
<bean  id="commonComponent" class="com.ls.pojo.CommonComponent"/>

相比较注解不用强制写id值,有默认id值类名首字母小写,当然也可以自定义id值。value=“xxx”

4.1.2包扫描

情况1:基本扫描配置

<?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.多个包可以使用 base-package="包1,包2,包3"--><context:component-scan base-package="com.ls.components"/></beans>

情况2:扫描目标包中排除组件

<!-- 情况三:指定不扫描的组件 -->
<context:component-scan base-package="com.ls.components"><!-- context:exclude-filter标签:指定排除规则 --><!-- type属性:指定根据什么来进行排除,annotation取值表示根据注解来排除 --><!-- expression属性:指定排除规则的表达式,对于注解来说指定全类名即可 --><context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

情况3:扫描目标包指定扫描组件

<!-- 情况四:仅扫描指定的组件 -->
<!-- 仅扫描 = 关闭默认规则 + 追加规则 -->
<!-- use-default-filters属性:取值false表示关闭默认扫描规则 -->
<context:component-scan base-package="com.ls.ioc.components" use-default-filters="false"><!-- context:include-filter标签:指定在原有扫描规则的基础上追加的规则 --><context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

之所以包扫描有下面两种方式是因为避免重复扫描,创建重复创建组件造成的资源浪费。

在后面的三成架构中,室友两个容器 webioc容器,rootioc容器。webioc容器用来存放controller组件,root容器存放初了controller组件的其他所有组件。

4.2 周期性方法和作用域

使用 @PostConstruc @PreDestroy注解需要导入javax-annotation-api

@Component
public class Person {//周期方法必须 public void 修饰,并且无参//导入依赖javax.annotation-api,才能使用这个注解@PostConstruct //注解指定bean的初始化方法public  void  one(){System.out.println("起床~~~~");}@PreDestroy//注解指定bean的销毁方法public void end(){System.out.println("睡觉~~~~~");}}

作用域:

@Scope(scopeName = ConfigurableBeanFactory.SCOPE_SINGLETON) //单例,默认值
@Scope(scopeName = ConfigurableBeanFactory.SCOPE_PROTOTYPE) //多例  二选一
public class BeanOne {//周期方法要求: 方法命名随意,但是要求方法必须是 public void 无形参列表@PostConstruct  //注解制指定初始化方法public void init() {// 初始化逻辑}
}

4.3Bean的依赖注入

4.3.1@Autowired 引用类型注入

**注解@Autowired **

在成员变量上直接标记@Autowired注解即可,不需要提供setXxx()方法。前提参与自动装配的组件(需要装配、被装配)全部都必须在IoC容器中。

@Service
public class UserService {@Autowiredprivate UserDao userDao;public void show(){userDao.call();}
}

这里存在的问题:

参考博客:Field injection is not recommended(Spring团队不推荐使用Field注入)-CSDN博客

注解不仅仅可以放在类上,也可以放在setter方法,和构造器上,对应着xml方式setter方法注入,和构造器注入

@Service
public class UserService {@Autowiredprivate UserDao userDao;//setter方法注入@Autowiredpublic void setUserDao(UserDao userDao) {this.userDao = userDao;}//构造器注入@Autowiredpublic UserService(UserDao userDao) {this.userDao = userDao;}public void show(){userDao.call();}
}
  1. @Autowired注解细节

    1. 标记位置

      1. 成员变量

这是最主要的使用方式!

与xml进行bean ref引用不同,他不需要有set方法!

  1. 工作流程

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

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

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

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

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

  • 能够找到:执行装配

  • 找不到:装配失败

  • 使用 @Qualifier 注解:根据 @Qualifier 注解中指定的名称作为 bean 的id进行匹配

  • 能够找到:执行装配

  • 找不到:装配失败

4.3.2扩展JSR-250注解@Resource

  1. **扩展JSR-250注解@Resource **
  • 理解JSR系列注解

JSR(Java Specification Requests)是Java平台标准化进程中的一种技术规范,而JSR注解是其中一部分重要的内容。按照JSR的分类以及注解语义的不同,可以将JSR注解分为不同的系列,主要有以下几个系列:

  1. JSR-175: 这个JSR是Java SE 5引入的,是Java注解最早的规范化版本,Java SE 5后的版本中都包含该JSR中定义的注解。主要包括以下几种标准注解:- `@Deprecated`: 标识一个程序元素(如类、方法或字段)已过时,并且在将来的版本中可能会被删除。- `@Override`: 标识一个方法重写了父类中的方法。- `@SuppressWarnings`: 抑制编译时产生的警告消息。- `@SafeVarargs`: 标识一个有安全性警告的可变参数方法。- `@FunctionalInterface`: 标识一个接口只有一个抽象方法,可以作为lambda表达式的目标。1. JSR-250: 这个JSR主要用于在Java EE 5中定义一些支持注解。该JSR主要定义了一些用于进行对象管理的注解,包括:- `@Resource`: 标识一个需要注入的资源,是实现Java EE组件之间依赖关系的一种方式。- `@PostConstruct`: 标识一个方法作为初始化方法。- `@PreDestroy`: 标识一个方法作为销毁方法。- `@Resource.AuthenticationType`: 标识注入的资源的身份验证类型。- `@Resource.AuthenticationType`: 标识注入的资源的默认名称。1. JSR-269: 这个JSR主要是Java SE 6中引入的一种支持编译时元数据处理的框架,即使用注解来处理Java源文件。该JSR定义了一些可以用注解标记的注解处理器,用于生成一些元数据,常用的注解有:- `@SupportedAnnotationTypes`: 标识注解处理器所处理的注解类型。- `@SupportedSourceVersion`: 标识注解处理器支持的Java源码版本。1. JSR-330: 该JSR主要为Java应用程序定义了一个依赖注入的标准,即Java依赖注入标准(javax.inject)。在此规范中定义了多种注解,包括:- `@Named`: 标识一个被依赖注入的组件的名称。- `@Inject`: 标识一个需要被注入的依赖组件。- `@Singleton`: 标识一个组件的生命周期只有一个唯一的实例。1. JSR-250: 这个JSR主要是Java EE 5中定义一些支持注解。该JSR包含了一些支持注解,可以用于对Java EE组件进行管理,包括:- `@RolesAllowed`: 标识授权角色- `@PermitAll`: 标识一个活动无需进行身份验证。- `@DenyAll`: 标识不提供针对该方法的访问控制。
  • @DeclareRoles: 声明安全角色。

但是你要理解JSR是Java提供的技术规范,也就是说,他只是规定了注解和注解的含义,JSR并不是直接提供特定的实现,而是提供标准和指导方针,由第三方框架(Spring)和库来实现和提供对应的功能。

  • JSR-250 @Resource注解

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

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

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

<dependency><groupId>jakarta.annotation</groupId><artifactId>jakarta.annotation-api</artifactId><version>2.1.1</version>
</dependency>
- @Resource使用
@Controller
public class XxxController {/*** 1. 如果没有指定name,先根据属性名查找IoC中组件xxxService* 2. 如果没有指定name,并且属性名没有对应的组件,会根据属性类型查找* 3. 可以指定name名称查找!  @Resource(name='test') == @Autowired + @Qualifier(value='test')*/@Resourceprivate XxxService xxxService;//@Resource(name = "指定beanName")//private XxxService xxxService;public void show(){System.out.println("XxxController.show");xxxService.show();}
}

4.3.3 基本属性赋值

@Value 通常用于注入外部化属性,正常情况下就直接==赋值

声明外部配置

application.properties

catalog.name=MovieCatalog

xml引入外部配置

<!-- 引入外部配置文件-->
<context:property-placeholder location="application.properties" />

@Value注解读取配置

package com.atguigu.components;import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;/*** projectName: com.atguigu.components** description: 普通的组件*/
@Component
public class CommonComponent {/*** 情况1: ${key} 取外部配置key对应的值!* 情况2: ${key:defaultValue} 没有key,可以给与默认值*/@Value("${catalog:hahaha}")private String name;public String getName() {return name;}public void setName(String name) {this.name = name;}
}

4.4总结

使用注解开发使用ioc,并不能完全摒弃xml配置,还需要使用xml配置

  • 扫包,注解使用的范围
  • 引入外部文件
  • 第三方提供的类,还需要在xml配置,如druid,jdbctemplate

五 使用配置类以及注解方式使用ioc

5.1 什么是配置类,以及使用

什么是配置类,就是将配置文件,改成配置类。

在上述使用注解的过程中,发现仍需要使用xml配置文件,xml配置文件的需要做的事情是:

  • 扫包   component-scan base-package=“xxx”
  • 引入外部文件   property-placeholder location=“xxxx”
  • 注册第三方提供的类

由于xml解析的效率较低,使用一个类实现以上功能,我们在此称这个类为配置类。

  • @Configuration
  • @ComponentScan
  • @PropertySource
  • @Bean
/*** 配置类代替xml文件* 1. 引入外部文件* 2. 扫包* 3. 注册第三方的类*/
@Configuration
@ComponentScan({"com.ls.dao","com.ls.service"})
@PropertySource("classpath:jdbc.properties")
public class MainConfiguration {//注册数据源---->使用druid第三方提供的类@Beanpublic DataSource dataSource(@Value("${jdbc.url}") String url,@Value("${jdbc.driver}") String driverClassname,@Value("${jdbc.username}") String username,@Value("${jdbc.password}") String password){DruidDataSource druidDataSource = new DruidDataSource();druidDataSource.setUrl(url);druidDataSource.setDriverClassName(driverClassname);druidDataSource.setUsername(username);druidDataSource.setPassword(password);return  druidDataSource;}
}

获得用配置类创建的ioc容器的时候是使用另一实现类AnnotationConfigApplicationcontext.

5.2@Bean的详细使用

  • bean的详细使用 name,initMethod,destroyMethod,以及作用域Scope(“singleton"or"prototype”)
  • bean之间的依赖
@Configuration
@ComponentScan({"com.ls.dao","com.ls.service"})
@PropertySource("classpath:jdbc.properties")
public class MainConfiguration {@Value("${jdbc.url}")private String url;@Value("${jdbc.driver}")private String driverClassname;@Value("${jdbc.username}")private String username;@Value("${jdbc.password}")private String password;//注册数据源---->使用druid第三方提供的类@Beanpublic DataSource dataSource(){DruidDataSource druidDataSource = new DruidDataSource();druidDataSource.setUrl(url);druidDataSource.setDriverClassName(driverClassname);druidDataSource.setUsername(username);druidDataSource.setPassword(password);return  druidDataSource;}//bean的详细使用 name,initMethod,destroyMethod,以及作用域Scope("singleton"or"prototype")/**bean之间的依赖  ------->jdbcTemplate--->datasource* 方式一: 如果需要注入的依赖,也是@Bean标签下的,可以直接使用方法引用* 方式二: 使用参数注入,就是将需要注入的依赖,以参数的形式传入被注入的bean。*          确保参数一定存在参数类型的bean*          如果有多个类型,可以直接使用需要注入的名*/@Bean(name = "jdbcTemplate", initMethod = "",destroyMethod = "")@Scope("singleton")public JdbcTemplate jdbcTemplate(){JdbcTemplate jdbcTemplate = new JdbcTemplate();//如果需要注入的依赖,也是@Bean标签下的,可以直接使用方法引用jdbcTemplate.setDataSource(dataSource());return jdbcTemplate;}//使用参数传值,就是将需要注入的依赖,以参数的形式传入被注入的bean。@Beanpublic JdbcTemplate jdbcTemplate1(DataSource dataSource){JdbcTemplate jdbcTemplate = new JdbcTemplate();jdbcTemplate.setDataSource(dataSource());return jdbcTemplate;}
}

5.3 @Import使用

@Import 注释允许从另一个配置类加载 @Bean 定义,如以下示例所示:

@Configuration
public class ConfigA {@Beanpublic A a() {return new A();}
}@Configuration
@Import(ConfigA.class)
public class ConfigB {@Beanpublic B b() {return new B();}
}

@Import的使用是作用在注解类上的,目的就是整合注解类,减少创建ioc时的参数

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

extends继承

目录 什么时候用继承? 继承的格式? 继承的特点 子类可以继承父类的哪些呢&#xff1f; 是否可以继承父类的构造方法呢&#xff1f; 是否可以继承成员变量&#xff1f; 是否可以继承成员方法&#xff1f; 在Java中&#xff0c;extends关键字用于实现继承关系。通过使用…

Go gin框架(详细版)

目录 0. 为什么会有Go 1. 环境搭建 2. 单-请求&&返回-样例 3. RESTful API 3.1 首先什么是RESTful API 3.2 Gin框架支持RESTful API的开发 4. 返回前端代码 go.main index.html 5. 添加静态文件 main.go 改动的地方 index.html 改动的地方 style.css 改动…

洛谷 P9532 [YsOI2023] 前缀和

题目背景 Ysuperman 模板测试的试机题。 小心立秋&#xff0c;小心秋丽。 题目描述 立秋有一个长度为 n 的数组 a&#xff0c;所有数字都是正整数&#xff0c;并且除了其中第一个数字以外其它数字都等于前面所有数字的和。 例如&#xff0c;数组 [1,1,2,4,8,16] 就有可能是…

基于U-Net的图像分割算法介绍

U-Net是一种用于图像分割的深度学习架构,其设计初衷是用于生物医学图像分割,尤其是医学影像中的细胞分割任务。U-Net结构独特,具有编码器-解码器结构,能够有效地捕捉图像中的局部和全局信息,并在像素级别上进行精确的分割。 相关论文: U-Net: Convolutional Networks for…

RISCV指令集体系简读之RV32I

RV32I 指令格式 用于寄存器-寄存器操作的R类型指令用于短立即数和访存load操作的I型指令用于访存store操作的s型指令用于条件跳转操作的B类型指令用于长立即数的U型指令用于无条件跳转的J型指令 特点&#xff1a; 所有指令都是32bits&#xff0c; 简化了指令解码&#xff1b;…

Python数据可视化库—Bokeh与Altair指南【第161篇—数据可视化】

&#x1f47d;发现宝藏 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。【点击进入巨牛的人工智能学习网站】。 在数据科学和数据分析领域&#xff0c;数据可视化是一种强大的工具&#xff0c;可以帮助我们…

Mac电脑安装蚁剑

1&#xff1a; github 下载源码和加载器&#xff1a;https://github.com/AntSwordProjectAntSwordProject GitHubAntSwordProject has 12 repositories available. Follow their code on GitHub.https://github.com/AntSwordProject 以该图为主页面&#xff1a;antSword为源码…

关于SpringCloud,你了解多少?

Why SpringCloud&#xff1f; Spring cloud 是一系列框架的有序集合。它利用 spring boot 的开发便利性巧妙地简化了分布式系统基础设施的开发&#xff0c;如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等&#xff0c;都可以用 spring boot 的开发风格做到一…

MercadoLibre(美客多)入仓预约系统操作流程-自动化约号(开篇)

目录 一、添加货件信息 二、输入货件信息 三、选择发货 四、填写交货日期 五、注意事项 MercadoLibre&#xff08;美客多&#xff09;于2021年10月18号上线了新预约入仓系统&#xff0c;在MercadoLibre美客多平台上&#xff0c;新入仓预约系统是一项非常重要的功能&#x…

通用设计的四大原则,大厂设计师带案例讲解!

作为数字产品设计师&#xff0c;在进行产品设计时要考虑产品的各种因素&#xff0c;例如功能、美观、安全等&#xff0c;要尽可能地满足所有用户的需求&#xff0c;做出对所有用户都尽可能公平的解决方案。但是&#xff0c;对于新手来说&#xff0c;在实际进行产品设计时&#…

Cesium 无人机航线规划

鉴于大疆司空平台和大疆无人机app高度绑定&#xff0c;导致很多东西没办法定制化。 从去年的时候就打算仿大疆开发一套完整的平台&#xff0c;包括无人机app以及仿司空2的管理平台&#xff0c;集航线规划、任务派发、实时图像、无人机管理等功能的平台。 当前阶段主要实现了&…