Spring笔记(2)-IOC之基于注解管理Bean

注解介绍

之前我们介绍了基于XML配置文件来管理Bean,在Spring中,还可以通过注解来完成Bean的管理。注解本身并不能执行,它只是完成标记功能,框架在检测到注解标记的位置之后,针对不同的注解来执行具体的操作。Spring为了指导程序员在哪些地方进行了标注,则需要通过扫描的方式来进行检测,然后根据注解进行后续操作。

Spring中提供有四种相关的注解:

  • @Component:将类标识为普通组件
  • @Controller:将类标识为控制层组件
  • @Service:将类标识为业务层组件
  • @Repository:将类标识为持久层组件

实际上,@Controller@Service@Repository这三个注解只是在@Component的基础上重新命名得到的注解,对于Spring来说,它们完成的功能都是相同的,都是标识当前类交由IOC进行管理,但是我们在使用的时候不能随便使用,应当利用好注解的名称来提升代码的可读性。

基于注解的Bean管理,我们只需要在需要交给IOC管理的实体类上增加对应注解,如下所示。需要注意不能标识在接口上,因为接口也不能交给IOC管理。

1
2
3
4
5
6
7
8
9
@Component
public class Shop {
private String name;
private String address;
private Integer count;

//...
//其他方法
}

之后在配置文件中开启扫描,利用component-scan标签,并指定其中的包名。这样,Spring就会扫描对应包下的所有类,如果有对应注解,则将该类进行管理。后续我们也可以从IOC容器中获取到相关的对象。

1
<context:component-scan base-package="com.syh.spring.bean"></context:component-scan>

通过注解配置的Bean对象,默认的id为类名的小驼峰形式,当然我们也可以在注解的value指定,这样对应的id就会使用我们指定的id:

1
@Component("shopBean")

注解扫描

在配置文件中进行开启注解扫描需要使用到component-scan标签,最基本的扫描方式就是指定基础的包名。除此之外,我们还可以指定要排除哪些组件或者只扫描哪些组件。

首先是指定要排除的组件。使用exclude-filter标签来指定排除规则,其中的type属性可以指定排除规则的类型,express属性指定对应全类名,在express中,也可以使用逗号来分隔多个内容。

  • type为annotation,表示根据注解排除。expression中设置要排除的注解的全类名
  • type为assignable,表示根据类型排除。expression中设置要排除的类型的全类名
1
2
3
4
<context:component-scan base-package="com.syh.spring.bean">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
<context:exclude-filter type="assignable" expression="com.syh.spring.bean.Shop"/>
</context:component-scan>

然后是指定仅扫描哪些组件。使用include-filter标签来指定包含规则,其中type属性也是指定包含规则的类型,express属性指定对应全类名。注意,这里必须额外指定component-scan标签中的use-defult-filters属性为false,即关闭默认扫描规则。默认扫描规则是扫描指定包上的所有类。如果没有关闭,则还是扫描所有类,没有起到仅扫描的作用。

  • type为annotation,表示根据注解包含。expression中设置要包含的注解的全类名
  • type为assignable,表示根据类型包含。expression中设置要包含的类型的全类名
1
2
3
4
<context:component-scan base-package="com.syh.spring.bean">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Component"/>
<context:include-filter type="assignable" expression="com.syh.spring.bean.Shop"/>
</context:component-scan>

上面的两类标签可以多次使用,但是不能同时使用。即可以有多个排除,或者多个包含,但是不能既使用排除、又使用包含。虽然语法上没有问题,但是无法达到我们所需的效果。

基于注解的自动装配

基于注解管理Bean的方式中,也提供自动装配的功能。对应注解为@Autowired,使用该注解即可完成自动装配。该注解能够标识的位置有以下三种:

  • 标识在成员变量上,此时不需要设置成员变量的set方法
  • 标识在set方法上
  • 标识在成员变量的有参构造

@Autowired注解的工作流程会涉及到byType以及byName,对应自动装配的工作流程如下:

@Qualifier注解是提供匹配id的一个注解,我们可以在其中设置属性名希望匹配的id名称。

首先根据所需要组件的类型到IOC容器中进行查找,如果能够找到唯一的Bean,就直接进行装配;如果完全找不到对应的类型,则装配失败。如果匹配到的Bean不止一个,则根据id进行匹配。如果配置了@Qualifier注解,则匹配的id为注解中的名称,如果没有配置,则按照属性名称进行匹配。如果能够匹配到,则执行装配,否则,则装配失败。

基于注解的自动装配,如果装配失败,都会报错NoSuchBeanDefinitionException。而基于XML的自动装配,如果装配失败,则使用的是默认值。

实际上该行为是由@Autowired中的属性required来指定的,它的默认值为true,表示自动装配无法找到对应的Bean的时候会装配失败,抛出错误。如果将该值设置为false的时候,如果装配失败,则使用默认值。


Spring笔记(2)-IOC之基于注解管理Bean
http://example.com/2022/10/14/Spring笔记-2-IOC之基于注解管理Bean/
作者
EverNorif
发布于
2022年10月14日
许可协议