Springboot以其强大的功能而广受开发者的喜爱,其中非常优秀的一个功能就是注解非常智能化,本文探讨springboot的自动发现功能。

spring框架中用来定义bean的注解有@Repository,@Component,@Bean(@Configuration注解的类中),@Controller,@Service,等注解。

这些注解用来标记对应的类是一个bean,然而,如何在spring容器启动的时候,通过扫描生成bean,需要引起注意。

在springboot当中,默认扫描springboot starter类所在目录以及该目录的所有子路径下的特定注解都可以扫描。

假如有一个项目结构如下,其中SpringbootApplication为启动类,那么entry目录下所有注解了bean标签的类都会在spring容器启动的时候生成对应的bean。

├─src
│  ├─main
│  │  ├─java
│  │  │  └─com
│  │  │      │  KnightAspect.java
│  │  │      │
│  │  │      └─liguang
│  │  │          └─springboot
│  │  │              │  SpringbootApplication.java
│  │  │              │
│  │  │              └─entry
│  │  │                  ├─config
│  │  │                  │      KnightConfig.java
│  │  │                  │
│  │  │                  ├─controller
│  │  │                  │      KnightController.java
│  │  │                  │
│  │  │                  ├─dto
│  │  │                  │      Minstrel.java
│  │  │                  │
│  │  │                  └─soundSystem
│  │  │                          CDPlayerConfig.java
│  │  │                          CompactDisc.java

│  │  │                          SgtPeppers.java

而com.KnightAspect尽管也有@Component注解,但是因为不在目录作用范围,从而无法生成bean,那么,如何绕过这一限制呢?

联想到@ComponentScan注解的作用就是用来指定扫描范围的,那么我们只要在启动类作用范围内的一个@Configuration注解类当中使用@ComponentScan注解即可。

package com.liguang.springboot.entry.soundSystem;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan
public class CDPlayerConfig {
}

然而,启动之后发现,仍然会报错,为什么呢?

通过查看@ComponentScan的源代码注释,会发现该注解的value默认参数含义为:

/**
	 * Alias for {@link #basePackages}.
	 * <p>Allows for more concise annotation declarations if no other attributes
	 * are needed — for example, {@code @ComponentScan("org.my.pkg")}
	 * instead of {@code @ComponentScan(basePackages = "org.my.pkg")}.
	 */
	@AliasFor("basePackages")
	String[] value() default {};

通过制定该参数,才可以精确制定扫描范围,而默认值是不知道我们需要从哪里开始扫描的。

package com.liguang.springboot.entry.soundSystem;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan(basePackages = {"com"})
public class CDPlayerConfig {
}

加上对应的值后,该bean可以成功生成。

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐