您现在的位置是:首页 >技术杂谈 >Spring(五大类注解,对象的三种注入方式及其优缺点)网站首页技术杂谈
Spring(五大类注解,对象的三种注入方式及其优缺点)
目录
3.1 @Autowired 和 @Resource 的区别
经过前⾯的学习,我们已经可以实现基本的 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 对象