深入浅出spring boot2.x 学习笔记(三) Spring Ioc中的常用注解
什么是ioc
ioc(控制反转)是一个理念,ioc技术并不是spring也不是java独有的。ioc是一种通过描述来创建或者获取对象的技术。
通过描述来创建对象,我个人的理解是:如在传统的web项目中,我们创建了一个User类,它包含userName、pwd两个属性。这个User.class就是一个类的描述。在没有使用spring框架时,需要通过new User()来创建一个对象,然后对这个对象进行属性修改以及方法调用等相关操作。而引入spring后,我们通过xml来配置配置一个User对象,把它命名为user,这个user与我们创建的User.class对应,我们可以在xml里面给这个user对象的属性赋予相应的初始值。这时候,相当于我们把User这个类的描述以及该类对象属性的描述(给定初始值或者默认)给了spring ioc容器,告诉他以后可能会用到这样一个对象,而这个对象由你spring来给我创建;而我在使用的时候只需要知道对象名字(即user)直接拿来用就可以了,而不需要我自己再去写new XXX来创建对象。
spring中每一个需要管理的对象称之为Spring Bean,简称Bean;而管理这些Bean的容器就是spring ioc容器。所以被管理的对象我们也可以叫做:被spring ioc容器所管理的java bean。ioc容器中的对象并不是相互独立的,他们可以存在相应的依赖关系。
ioc容器的基本功能:
- 通过描述来管理bean,包括发布或获取(即创建、使用bean)
- 完成各个bean之间的以来关系,即di(依赖注入)
通过注解来装配Bean
在springmvc中,我们一般使用xml进行装配,而springboot使用全注解的形式。
-
Component注解
标明哪个类被扫描进ioc容器,一般标注在实体类上。如:
该注解告诉spring容器有一个Cars类型的bean需要被管理,容器启动时,spring会创建一个Cars类型的对象,对象名称默认为类名首字母小写。当然我们也可以自定义bean的名称,如:@Component(“anotherName”)。 -
ComponentScan注解
标明采用何种策略去扫描装配。扫描当前类所在的包及其子包。还可以指定扫描的包、过滤不需要装配进ioc容器的类。如:新建一个自定义配置类MyConfig.class。
(1)只加上ComponentScan注解则表示ioc容器会对该类所在的包及其子包进行扫描
(2)@ComponentScan(basePackages=“com.example.demo."),表示我们指定了扫描demo下所有的包。
(3)@ComponentScan(basePackages="com.example.demo.”,
excludeFilters = {@Filter(classes= {Service.class})})。表示扫描demo包下的所有包,并且不扫描被@Service注解标注的类(@Filter及@Service所在的包需要注意一下)。
在启动类XXXApplication.class中的@SpringBootApplication注解也可以指定需要被扫描的包,下图可以看到,它存在exclude 和excludeName这两个方法,但它们只对容器内部的自动配置类生效。若要排除其他自定义的类,则可以结合@ComponentScan注解来使用。 -
自定义[email protected]注解
如:我们定义一个切面类MyAspect。
@ Aspect注解标注这个类为切面。我们可以使用@Component注解将该类注册进ioc容器,则该bean默认名称为myAspect 。当然我们还可以使用@Bean注解。
启动类中加入红色框线代码,他表示容器启动时会产生一个MyAspect类型的bean存放在ioc容器中。name属性则用来指定该bean的名称,若不指定,则bean的名称为方法名,即initMyAspect。在配置第三方数据源时,也可以使用该方法进行配置。
依赖注入
此处对spring中常用的注解做一个总结
@Autowired | @Resource |
---|---|
spring提供的注解 | java提供的注解 |
只按照类型(byType)注入 | 默认按照名称(byName)注入,有name和type两个属性 |
默认要求依赖对象必须存在 |
-
对于@Autowired,若要使用名称进行装配,则需要结合@Qualifier注解。若一个父类Cars有若干个子类Audi、Bmw、Volvo,要求使用Bmw进行注入,则可些为:
-
还可以使用@Primary注解来进行优先权的选择。若使用@Primary(“volvo”),则是告诉spring在注入的时候不论存在几个Cars类型的bean,都优先使用名称为volvo的bean进行注入。
-
@Resource的装配顺序
- 同时指定了name和type时,则从容器中找到唯一匹配的bean进行装配,类似与@Autowired与@Qualifier结合使用,找不到则抛出异常。
- 只指定了name属性,则从容器中查找名称(id)匹配的bean进行装配,找不到则抛出异常。(bean的名称是唯一的)
- 只指定了type属性,则从容器中查找唯一匹配类型的bean进行装配,此时相当于@Autowired,找不到或找到多个,都会抛出异常。