您现在的位置是:首页 >技术杂谈 >Spring(五大类注解,对象的三种注入方式及其优缺点)网站首页技术杂谈

Spring(五大类注解,对象的三种注入方式及其优缺点)

wwwllsuper 2024-06-22 12:01:02
简介Spring(五大类注解,对象的三种注入方式及其优缺点)

目录

1.存储 Bean 对象

1.1前置工作:配置扫描路径

1.2添加注解存储 Bean 对象

1.2.1 @Controller [控制器存储]

1.2.2 @Service(服务存储)

1.2.3 @Repository(仓库存储)

1.2.4 @Component(组件存储)

1.2.5 @Configuration(配置存储)

1.3 五大类注解各自的作用域与联系

1.3.1 为什么需要五个类注解?

1.3.2 五大类注解的命名规则

 1.4 方法注解 @Bean

1.4.1 @Bean的用法

1.4.2 重命名 Bean

2.获取对象

2.1 属性注入

 2.1.1 优点分析

2.1.2 缺点分析

2.2 setter 方法注入

 2.2.1 优点分析

2.2.2 缺点分析

2.3 构造方法注入

2.3.1 优点分析

注意:面试题

3. @Resource:另一种注入关键字

3.1 @Autowired 和 @Resource 的区别

4.同一类型多次 @Bean 报错


经过前⾯的学习,我们已经可以实现基本的 Spring 读取和存储对象的操作了,但在操作的过程中我们 发现读取和存储对象并没有想象中的那么“简单”,所以接下来我们要学习更加简单的操作 Bean 对象的 ⽅法。
在 Spring 中想要更简单的存储和读取对象的核⼼是使⽤注解,也就是我们接下来要学习 Spring 中的相 关注解,来存储和读取 Bean 对象。

1.存储 Bean 对象

前面在存储 Bean 时,需要在 spring-config 中添加一行 bean 注册内容,这个XML文件有一点不好的是调试,而且XML文件报错了是不影响项目运行的,即使报错了,也可能发现不了.

1.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:content="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">
    <content:component-scan base-package="com.bit.service"></content:component-scan>
</beans>

要将那个路径底下的那个类注入到spring包

告诉spring,那个目录低下的类有可能托管给spring管理

但是即使添加了注解,如果不是在配置的扫描包下的类对象,也是不能被存储到 Spring 中的

1.2添加注解存储 Bean 对象

想要将对象存储在 Spring 中,有两种注解类型可以实现:
1. 类注解:@Controller、@Service、@Repository、@Component、@Configuration。
2. ⽅法注解:@Bean

1.2.1 @Controller [控制器存储]

 

 

我们在xml中配置了一个扫描路径com.demo.component,component中有一个叫ArticleController的类,我们给它加了一个注解叫Controller,这个Controller的含义就是告诉spring,因为spring在加载的时候就会去扫描这个路径,及路径低下的所有包,去检查是否加了五大类注解,当检查发现加了后机会将这个对象存储到spring当中,就可以去取它了。

但是我们可以知道我们在之前会给 Bean 起一个id的,但是在注解这里并没有其他的

默认情况下,当我们使用spring注解将一个对象存储到spring的时候,他的id就是类的首字母进行小写的

 

1.2.2 @Service(服务存储)

 

1.2.3 @Repository(仓库存储)

1.2.4 @Component(组件存储)

1.2.5 @Configuration(配置存储)

1.3 五大类注解各自的作用域与联系

1.3.1 为什么需要五个类注解?

@Controller(控制器):归属于业务逻辑层,用来控制用户的行为,它用来检查用户的合法性/有效性的。如果说参数是无效的,说明是非法访问所以不能使其继续向下走了,用户进来之后,访问的第一个就是控制器,当控制器校验后没问题才继续往下走。

@Service(服务):归属于服务处,用来调用持久化类实现相应的功能,【不是直接和数据库交互的,就是一个控制中心(就是做服务编排的,来决定这个功能应该调用哪些持久层的代码组合实现功能的)】。

@Repository(仓库):归属于持久层,是直接和数据库交互的,通常每一个表都会对应一个仓库类(@Repository)

@Configuration(配置);归属于配置层,是用来配置当前项目的一些信息的。

@Component(组件):归属于公共工具类,提供的是某些公共方法。

这就是为什么要设置五个注解的原因,因为每个注解都有自己的职责,职责所对应的功能也是不同的

在五大注解类中 Component 可以当做其他注解的父类

其他类之间的关系可以当做是兄弟

对比源码:

 

1.3.2 五大类注解的命名规则

我们可以看到在上方解释五大类中的命名都是采用小驼峰的方式

那么在这里我给出三个问题:

问题1:如果类名首字母是小写,要怎么从Spring中获取Bean?

问题2:如果首字母和第二字母都是大写会怎样?

问题一:

 和首字母是大写的获取方法是一样的,都是使用类的首字母进行小写来获取对象的

 问题二:

当时使用默认规则使用首字母小写的时候,失败了,但是

正确获取Bean的方式:使用原类名,就能成功获取到了 

问题1:如果类名首字母是小写,要怎么从Spring中获取Bean?

答:和首字母是大写是一致的,都是用的是将类名首字母小写的方式来获取对象.

问题2:如果首字母和第二字母都是大写会怎样?

答:当使用默认规则,首字母小写获取Bean对象时,失败了!
正确获取Bean 的方式是使用原类名,就能成功获取到了。

结论:当使用5大类注解时,默认情况下获取Bean对象,只需要将类名首字母小写即可;然而,当Bean 对象首字母和第二个字母都是大写时,此时需要使用原类名才能正确的获取到Bean对象。

这是为什么呢?我们来深扒源码:

 

 

 1.4 方法注解 @Bean

1.4.1 @Bean的用法

@Bean 是加在方法上的,并且只使用一个 @Bean 是无法将对象存储到容器中的,所以还要给类加个注解

Bean 就是类注解的基础上缩小范围

 

 

注意事项:@Bean注解使用的时候不能单独使用,一定是需要配合五大类注解一起使用,否则是无效的方法注解

原因:和xml中的配置路径是一样的,在实际需求中我们的方法的大量的,不能说所有类中的所有方法都去扫描一遍,看看有没有加上Bean注解的,如果加了Bean注解了就把其返回的对象存到spring当中,这样做的话性能是非常的低的,方法是远多于类的,如果不配合五大类注解去使用的话,效率是极低的

1.4.2 重命名 Bean

可以通过设置 name 属性给 Bean进行重命名

@Bean 命名规则,当没有设置name属性时,那么 bean 默认的名称就是方法名,

当设置name属性后,只能通过重命名的name属性对应的值来获取,也就是说再使用方法就获取不到 bean 对象了,

并且也可以 一个bean 有多个名字,像数组一样在{}中写上多个名字,就可以了

 

 

2.获取对象

获取 bean 对象也叫做对象装配,是把对象取出来放到某个类中,有时候也叫对象注⼊。
对象装配(对象注⼊)的实现⽅法以下 3 种:
1. 属性注⼊
2. 构造⽅法注⼊
3. Setter 注⼊

2.1 属性注入

属性注入是我们最熟悉,也是日常开发中使用最多的一种注入方式

使用@Autowired实现的

 

 

 2.1.1 优点分析

属性注入最大的优点就是实现简单、使用简单只需要给变量上添加一个注释(@Autowired),就可以在不 new 对象的情况下,直接获得注入的对象了(这就是 DI 的功能和魅力所在),所以它的优点就是使用简单。

2.1.2 缺点分析

1.功能性问题:无法注入一个不可变的对象(final修饰的对象);

2.通用性问题:只能适应于loC容器:如果将属性注入的代码移植到其他非 IoC 的框架中,那么代码就无效了,所以属性注入的通用性不是很好。


3.设计原则问题:更容易违背单一设计原则。

 

2.2 setter 方法注入

Setter 注入,写要注入的属性的 setter方法,然后加上注解 @Autowired

 

 2.2.1 优点分析

相较于属性注入,它更符合单一设计原则

2.2.2 缺点分析

1.不能注入不可变对象(final修饰的对象);

 

2.注入的对象可被修改:被注入的对象可能随时被修改

2.3 构造方法注入

写构造方法,参数传入要注入的对象,然后写上注解 @AutoWired (如果当前类中只有一个构造方法,那就可以省略注解)

 

2.3.1 优点分析

1.可注入不可变对象;

 

2.注入对象不会被修改:构造方法在对象创建时只会执行一次,因此它不存在注入对象被随时(调用)修改的情况。

3.注入对象会被完全初始化;

4.通用性更好:构造方法注入可适用于任何环境,无论是 IoC 框架还是非 IoC 框架,构造方法注入的代码都是通用的,所以它的通用性更好。

注意:面试题

以上实现方式是一个常见的面试问题:
面试官:Spring有几种注入方式?它们有什么区另

3. @Resource:另一种注入关键字

@Resource: 支持 属性注入 和 Setter 注入,但不支持构造方法注入

 

 

3.1 @Autowired 和 @Resource 的区别

相同点:都是用来实现依赖注入的。

不同点:
1.功能支持不同: @Autowired 支持属性注入、 setter注入、构造方法注入;@Resource支持属性、setter注入,但不支持构造方法注入

2.出身不同:@Autowired来自Spring框架;而@Resource来自于JDK.


3.参数支持不同:@Resource支持更多的参数设置;而@Autowired 只支持required参数。

4.同一类型多次 @Bean 报错

 

 解决方法:

(1) 精确的描述 bean 的名称 (将注入的名称写对)

 

(2) 使用 @Resource 设置 name 的方式来重命名注入对象

 

(3) 如果限定不能删除 @Autowired ,那就可以再加上使用 @Qualifier,来删选 bean 对象

 

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。