【进阶】Spring更简单的读取和存储对象
努力经营当下,直至未来明朗!
文章目录
- 一、存储Bean对象
- 一)前置工作:配置扫描路径(重要)
- 二)添加注解存储Bean对象
- 3. 五大类注解:
- 4. 方法注解:
- 6. 相关问题
- 7. 补充【结论、查看源码】
- 三)为什么要使用这么多类注解
- 四)方法注解 @Bean
- 二、获取Bean对象(对象装配)
- 1. 属性注入
- 2. 构造方法注入(官方推荐写法)
- 3. Setter注入
- 4. 三种注入方式的区别【经典面试题】
- 5. @Resource:另⼀种注⼊关键字
- 6. @Resource和@Autowired的区别【经典面试题】
- 7. 同⼀类型多个 @Bean 报错
- 小结
普通小孩也要热爱生活!
一、存储Bean对象
在spring-config.xml中配置bean标签比较麻烦,此时就可以使用注解。(注解在jdk1.5之后出现)
一)前置工作:配置扫描路径(重要)
- 配置xml文件
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: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.demo.component"></content:component-scan>
<bean id="article" class="com.demo.component.ArticleController"></bean>
</beans>
- 补充:包的平铺
二)添加注解存储Bean对象
- 类注解:将注解写到类中,将某个依赖动态地加载到类中,将类对象存储到Spring中。
- 方法注解:将方法返回的对象存储到Spring中。
3. 五大类注解:
1)@Controller(控制器存储):默认的id是类名小写。
2)@Service(服务存储)
3)@Repository(仓库存储)
4)@Component(组件存储)
5)@Configuration(配置存储)
4. 方法注解:
@Bean:将当前@Bean修饰方法的方法对象存储到Spring当中。
- 演示:
6. 相关问题
1)如果类名首字母是小写,要怎么从Spring中获取Bean?(默认id是首字母小写)
答:
① 和首字母大写时是一样的,都是使用将类名首字母小写的方式来获取Bean对象的。
② 同样的方式:获取Spring对象(ApplicationContext/BeanFactory)、获取Bean对象(getBean(“id”,类名.class))、使用Bean。
③ 【注意:但是千万不要忘记加上类注解!!否则编译失败!】
④ 默认id是小写开头,当类名是小写字母开头时,id同样也是小写开头(也就是与类名相同),此时是可以正确输出结果的。
2)如果首字母和第二个字母都是大写,会怎么样?
答:
① 当使用默认规则(id首字母小写)获取Bean对象的方法已经不适用了,会抛出NoSuchBeanDefinitionException异常。
② 正确获取Bean的方式是id直接使用原类名就能成功获取到了。
3)项目中如果没有包目录,所有的类都写在java根路径下,那么要怎么存取Bean对象呢?
答:
① 此时不管在xml的 base-package=""中配置空or其他路径都会出现NoSuchBeanDefinitionException错误,此时需要使用通配符。
② 通配符*表示匹配任意一个的,**表示匹配根路径以及根路径底下的所有子路径。
(但是执行速度巨慢,不建议使用!)
③ 使用通配符后可能会报错(不要忘记加上类注解):
④ 发现在添加了类注解之后还是报错, 此时解决方法:获取Spring对象的方法换为BeanFactory!
7. 补充【结论、查看源码】
- 结论:当使用五大类注解时,默认情况下获取Bean对象id只需要将首字母小写即可;然而,当Bean对象首字母和第二个字母均是大写时,此时需要使用原类名才能正确获取到Bean对象。【五大类注解均适用!】
- 注意:IDEA下按ctrl+r是查找替换当前文档内容,连续按两下shift是全局搜索。
- 在IDEA中进行方法跳转:ctrl+左键(查看源码时适用)
- 查看id命名规则方法:
连续shift -> 搜索beanName -> AnnotationBeanNameGenerator
-> buildDefaultBeanName跳转 -> decapitalize跳转 -> 定位当前类位置
-> 定位到rt.jar中(jdk的工具方法类)
-> 分析源代码
-> 小结:
默认是首字母小写;如果一二个字母均是大写,就直接使用原类名就ok!
-
如果出现
NoSuchBeanDefinitionException
错误,要么是没有加注解,要么是id名字写错了;亦或者是配置xml时包名没有配对。 -
如果在spring-config.xml配置package的包下还有子目录也是ok的,可以访问到!
三)为什么要使用这么多类注解
-
为什么需要五个类注解?
1)通过类注解可以了解当前类的用途(就类似:看到车牌就知道是哪个城市的车)
2)功能有细微的不同:在Spring MVC/Spring Boot中有体现,等彼时再细讲。 -
五个类注解的用途:【重要!✨】
1)@Controller(控制器):归属于业务逻辑层,用来控制用户的行为,它用来检查用户参数的有效性。
2)@Sservice(服务):归属于服务层,调用持久化类实现相应的功能。【不直接和数据库交互,它类似于控制中心】
3)@Repository(仓库):归属于持久层,是直接和数据库进行交互的。通常每一个表都会对应一个@Repository仓库类。
4)@Configuration(配置):归属于配置层,是用来配置当前项目的一些信息。
5)@Component(组件):归属于公共工具类,提供某些公共方法。
-
五大类注解有什么关系?
【使用ctrl+左键 进入源码进行查看】
1)注:@interface是自定义注解类
2)【小结】
@Component是 @Controller / @Service / @Repository / @Configuration的父类。
五大类有区别,但是具体在Spring MVC/ Spring Boot中细讲
四)方法注解 @Bean
- 方法注解@Bean实现一个类的 多次存到 Spring中,但是要注意方法注解是将 方法返回的对象 存到Spring中,所以一定要有 返回类型。
- 举栗子:
1) 方法注解(配合五大类使用)
2) 进行获取:
① 注意id默认是@Bean注解的方法的方法名
注意:获取Spring对象的时候需要使用ApplicationContext
,如果使用BeanFactory的话就会报错!
BeanFactory的话就会报错:原因可能是BeanFactory出现的太早,导致后续在jdk1.5之后出现的注解不兼容;读xml是没有问题的,但是读bean就可能会存在问题。
-
注意事项:方法注解@Bean一定要配合五大类去使用! 否则是无效的方法注解。
(主要是考虑性能问题,配合类注解更容易找到对应的路径) -
Bean是支持设置name属性的,便于区分。并且是可以设置多个name的。
注意:如果给@Bean设置name属性后,id就不能再使用默认的方法名了!!
二、获取Bean对象(对象装配)
-
对象装配(对象注入)的实现方式有以下三种:
1)属性注入
2)构造方法注入
3)Setter注入 -
以上所有的注入方法都要与类注解搭配使用! 其中构造方法注入如果只有一个构造方法的话@Autowired是可以省略的。
1. 属性注入
-
@Autowired
直接进行声明就行 -
一定要进行类注释!否则会编译错误!
2. 构造方法注入(官方推荐写法)
-
直接将Bean对象作为构造方法的参数参数传入
-
依旧要使用@
Autowired(构造方法上)
和类注解
的搭配!
-
注:如果当前类中只有一个构造方法,@Autowired是可以省略的。但是一个类中如果有多个构造方法就不可省略。
3. Setter注入
- 在设置setter方法的时候要加上 @Autowired注解,并且在类上也要加上类注解。
- 在设置setter方法的时候不加上@Autowired注解就会报错。
4. 三种注入方式的区别【经典面试题】
请说说属性注入、构造方法注入和Setter注入的区别?
【各自优缺点】
1)属性注入:
① 写法简单;
② 但是通用性不好,它只能运行在IoC容器下,如果是非IoC容器就会出现问题,并且只有在使⽤的时候才会出现 NPE(空指针异常)。
(实际开发中常用)
2)Setter注入:
① 早期Spring版本推荐的写法;
② 但是Setter注入的通用性没有构造方法注入通用(但是高于属性注入)。
3)构造方法注入:
① 通用性更好,它能确保使用注入对象之前此对象一定已经注入,可以保证注入的类不为空(因为是在构造方法中,在实例化时就注入);
② 但是当构造方法注入参数过多就会比较臃肿时,此时开发者就要检查自己所写的代码是否符合“单一设计原则”的规范了。
此注入方式也是Spring后期版本中推荐的注入方式。
单一设计原则SRP:它规定一个类只有一个发生变化的原因。如果多于一个导致类变更的原因,则违反了SRP。
5. @Resource:另⼀种注⼊关键字
- @Resource注入关键字类似于@Autowired,使用方法很像;但是有细微的差别。
- 在属性注入和Setter注入中,@Resource可以替换@Autowired,程序可以正常运行。
- 但是:构造方法注入只能使用@Autowired,使用@Resource直接报错。
- 小结:@Resource支持属性注入和Setter注入,但是不支持构造方法注入。
- 注:@Resource是jdk提供的,而@Autowired是Spring框架提供的。
6. @Resource和@Autowired的区别【经典面试题】
注意区别:
① 对象注入有几种方式:3种(属性、构造方法和Setter注入)
② 对象注入的方法:2种(@Resource和@Autowired)
(不确定时直接与面试官沟通确认是问哪一种)
1)相同点:都可以实现将一个对象注入到一个类中。(类的对象;有@Bean修饰方法的话,Spring就是存储返回类型,对象名就对应方法名/自定义名)
2)不同点:
① 出身不同:@Resource来自于JDK(java亲儿子),@Autowired是Spring框架提供的。
② 用法不同:@Autowired 支持属性注入、构造方法注入和Setter注入,@Resource不支持构造方法注入。
③ 支持的参数不同:@Resource支持更多的参数设置,如name、type等设置,而@Autowired只支持required参数设置。
(通常情况下,我们会使用@Autowired)
7. 同⼀类型多个 @Bean 报错
-
同一个类中出现多个@Bean(类型上有类注解)
-
使用属性注入获取Bean对象(不要忘记类注解)
-
获取到的Bean对象错误
-
此时:同⼀个类型,多个 bean 的解决⽅案有以下两个:
① 使⽤ @Resource(name=“xxx”) 定义。
② 使⽤ @Qualifier 注解定义名称(搭配@Autowired)。 -
使用示例:
1)使⽤@Resource(name="xxx")
定义具体的方法。
注意name和@Bean的方法名保持一致!
2)使⽤ @Qualifier
注解定义名称。
① @Qualifier(value = “xxx”)
中的value也是和@Bean修饰的方法名保持一致!
② @Qualifier必须和@Autowired配合使用
,且只能是@Autowired,不能是@Resource 。
小结
- 五大类注解及其关系
- 方法注解必须配合类注解
- Bean命名规则(id)
- 从Spring中获取Bean对象(属性、Setter、构造函数注入)
- 三种注入方式的区别(相同点+不同点)
- 注入关键字(2个)
- @Autowired 和 @Resource 区别(出身、用法、支持的参数)
- 解决同⼀类型多个 Bean 的报错(2个方法)