朱亮亮

Stay Hungry, Stay Foolish.

0%

SpringBoot 核心注解

我们在写 SpringBoot 程序的时候,总要写一个主程序,这个主程序最大的特点就是在其类上包含了一个@SpringBootApplication注解,这个正式 SpringBoot 的核心。

@SpringBootApplication 注解是一个组合注解,主要包含如下三个注解

1
2
3
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan

其中,@SpringBootConfiguration 注解包含 @Configuration 注解,实际上两者基本没啥区别。SpringBoot 推荐使用 JavaConfig 的方式为 SpringBoot 来配置容器。启动类使用 @Configuration 注解标记之后,本身就是一个 IoC 容器的配置类了。

@Configuration

以前我们使用 xml 来配置 Bean,例如:

1
2
3
4
5
6
7
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"
default-lazy-init="true">
<!--bean定义-->
<bean id="myBean" class="com.example.MyBean"></bean>
</beans>

使用 JavaConfig 方式配置则如下:

1
2
3
4
5
6
7
@Configuration
public class AppConfiguration {
@Bean
public MyBean() {
return new MyBean();
}
}

任何一个使用 @Bean 标注的方法,其返回值将作为一个 Bean 定义注册到容器当中,id 为方法名。

使用 JavaConfig 也能表示 Bean 的依赖关系。

1
2
3
4
5
6
7
8
9
10
11
12
@Configuration
public class AppConfiguration {
@Bean
public MyBean createMyBean() {
return new MyBean();
}

@Bean
public MyService createService() {
return new MyService(createMyBean());
}
}

总结:@Configuration 注解可以作为 Spring IoC 容器 Bean定义 的来源,@Bean 注解则定义了一个需要注册到 Spring 容器的对象。

@ComponentScan

@ComponentScan 用于自动扫描并加载符合条件的组件(使用 @Component@Service@Repository 标记的类)或者 Bean 定义,最终将这些组件加载到 Spring 容器中。我们可以通过 basePackages等属性来定制需要扫描的包。如果不指定,则默认 Spring 框架从声明@ComponentScan类的 package进行扫描。

@ComponentScan有两个属性需要注意下:

  1. includeFilters,表示要扫描哪些类型的包,如果 useDefaultFilters 设置为 false,则只扫描 includeFilters 指定的包
  2. excludeFilters,表示要排除哪些类型的包。

@EnableAutoConfiguration

@EnableAutoConfiguration注解上的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

Class<?>[] exclude() default {};

String[] excludeName() default {};
}

其中,比较重要的注解是@Import({AutoConfigurationImportSelector.class}),有了这个注解,@EnableAutoConfiguration就能根据类路径中 jar 的依赖进行自动检查,例如:添加了 spring-boot-starter-web 依赖,会自动添加 Tomcat 和 SpringMVC 的依赖,Spring Boot 会对 Tomcat 和 Spring MVC 进行自动配置。其中起作用的主要是 AutoConfigurationImportSelector 这个类,它帮助 SpringBoot 应用将符合条件的 @Configuration 配置都加载到 SpringBoot 容器中。

AutoConfigurationImportSelector 依赖 SpringFactoriesLoader(在 Spring-Core 中) 来加载配置,它的主要功能就是从指定配置 META/spring.factories 加载配置。

1
2
3
4
5
6
7
8
9
10
public final class SpringFactoriesLoader {
//...
public static <T> List<T> loadFactories(Class<T> factoryType, @Nullable ClassLoader classLoader) {
...
}

public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
....
}
}

spring.factories 的主要配置如下:

这里 EnableAutoConfiguration 包含了非常多的自动配置项,如:jdbc、redis 等。我们可以看看我们熟悉的KafkaAutoConfiguration

1
2
3
4
5
6
7
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(KafkaTemplate.class)
@EnableConfigurationProperties(KafkaProperties.class)
@Import({ KafkaAnnotationDrivenConfiguration.class, KafkaStreamsAnnotationDrivenConfiguration.class })
public class KafkaAutoConfiguration {
……
}

几个主要的注解说明如下:

  1. @Configuration,如上文介绍,标明这个类是一个配置类,自动加载类中 @Bean
  2. @ConditionalOnClass,这个注解可以输入一个或多个 Class,相当于一个开关,当检测到存在输入的类时,该配置生效,否则将不实例化。一个典型的场景,如果在项目 pom 中加入 spring-boot-starter-web依赖,那么在启动 spring 的时候会检测到 web 相关的 Config,服务就会以 web 的形式启动。
  3. @EnableConfigurationProperties ,这个注解使@ConfigurationProperties注解生效。通常括号内的类就含有 @ConfigurationProperties注解,并且一般会指定一个 prefix,例如 spring.kafka,对应 application.yaml 中 spring.kaka 相关的配置。
  4. @Import({ KafkaAnnotationDrivenConfiguration.class, KafkaStreamsAnnotationDrivenConfiguration.class }),这个注解用于导入使用@Configuration标注的配置类。