一场寂寞凭谁诉。算前言,总轻负。



spring boot gradle 注解扫描 springboot注解扫描原理_springboot 注解


概述

spring boot注解大部分是在org.springframework.boot.autoconfigure和org.springframework.boot.autoconfigure.condition包中。让我们来了解一些常用的spring boot注解以及它们背后的工作原理。

@SpringBootApplication

Spring boot主要功能是自动配置。这种自动配置是通过组件扫描完成的,即在classspath中为@Component注解找到所有类。它还涉及到扫描@Configuration注解和初始化一些额外的bean。

@SpringBootApplication注解可一步实现所有功能。它启用了三个功能:

  1. @EnableAutoConfiguration:启用自动配置机制
  2. @ComponentScan:启用@Component扫描
  3. @SpringBootConfiguration:在上下文中注册额外的bean

用@SpringBootApplication注解的Java类是Spring Boot应用程序的主类,应用程序从此处开始。

import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplicationpublic class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); }}

@EnableAutoConfiguration

该注解支持Spring应用程序上下文的自动配置,尝试根据类路径中预定义类的存在来猜测和配置我们可能需要的bean。

例如,如果在类路径上有tomcat-embedded.jar,则可能需要TomcatServletWebServerFactory。

由于这个注解已经包含在@SpringBootApplication中,所以在主类上再次添加它没有影响。还建议使用@SpringBootApplication。

自动配置类是一些常规的Spring 配置 bean。它们使用SpringFactoriesLoader机制定位。通常,自动配置bean是@Conditional Bean(最经常使用@ConditionalOnClass和@ConditionalOnMissingBean注解)。

@SpringBootConfiguration

它表明类提供了Spring boot应用程序配置。它可以作为Spring的标准@Configuration注解的替代,这样就可以自动找到配置。

应用程序应该只包含一个@SpringBootConfiguration,大多数惯用的Spring Boot应用程序将从@SpringBootApplication继承它。

这两个注解的主要区别是@SpringBootConfiguration允许自动定位配置。这对于单元测试或集成测试特别有用。

@ImportAutoConfiguration

它只导入和应用指定的自动配置类。@ImportAutoConfiguration和@EnableAutoConfiguration之间的区别在于,后者尝试在扫描期间配置类路径中找到的bean,而@ImportAutoConfiguration只运行我们在注解中提供的配置类。

当我们不想启用默认的自动配置时,应使用@ImportAutoConfiguration。

@ComponentScan("path.to.your.controllers")@ImportAutoConfiguration({WebMvcAutoConfiguration.class ,DispatcherServletAutoConfiguration.class ,EmbeddedServletContainerAutoConfiguration.class ,ServerPropertiesAutoConfiguration.class ,HttpMessageConvertersAutoConfiguration.class})public class App { public static void main(String[] args)  { SpringApplication.run(App.class, args); }}

@AutoConfigureBefore, @AutoConfigureAfter, @AutoConfigureOrder

如果我们的配置需要以特定顺序(在应用之前或者之后),则可以使用@AutoConfigureAfter或@AutoConfigureBefore批注。

如果我们想要排序某些毫无关系的自动配置,我们还可以使用@AutoConfigureOrder。该注解与常规的@Order注解具有相同的语义,但为自动配置类提供了专用的顺序。

@Configuration@AutoConfigureAfter(CacheAutoConfiguration.class)@ConditionalOnBean(CacheManager.class)@ConditionalOnClass(CacheStatisticsProvider.class)public class RedissonCacheStatisticsAutoConfiguration { @Bean public RedissonCacheStatisticsProvider redissonCacheStatisticsProvider(){ return new RedissonCacheStatisticsProvider(); }}

Condition 注解

通常,所有自动配置类都具有一个或多个@Conditional注解。它仅在条件满足时才允许注册bean。以下是一些有用的条件注解。

@ConditionalOnBean 和 @ConditionalOnMissingBean

这些注解可根据是否存在特定bean来注册某个bean。

它的value属性用于根据类型或名称指定bean。此外,search属性允许我们限制在搜索bean时应该考虑的ApplicationContext层次结构。

如果条件不匹配,则在类级别使用这些注解可防止将@Configuration类注册为Bean。

在下面的例子中,JpaTransactionManager bean只有在应用程序上下文中还没有定义类型为JpaTransactionManager的bean时才会被加载。

@Bean@ConditionalOnMissingBean(type = "JpaTransactionManager")JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) { JpaTransactionManager transactionManager = new JpaTransactionManager(); transactionManager.setEntityManagerFactory(entityManagerFactory); return transactionManager;}

@ConditionalOnClass 和 @ConditionalOnMissingClass

这些注解允许根据特定类的存在与否来包含配置类。注意,注解是使用spring ASM模块解析的,即使在运行时没有类,也可以在注解中引用该类。

我们还可以使用value属性来引用实际的类,或者使用name属性来通过使用字符串值来指定类名。

下面的配置将创建EmbeddedAcmeService,前提是这个类在运行时可用,并且在应用程序上下文中不存在其他具有相同名称的bean。

@Configuration@ConditionalOnClass(EmbeddedAcmeService.class)static class EmbeddedConfiguration { @Bean @ConditionalOnMissingBean public EmbeddedAcmeService embeddedAcmeService() { }}

@ConditionalOnNotWebApplication 和 @ConditionalOnWebApplication

这些注解允许根据应用程序是否是web应用程序来注册bean。在Spring中,web应用程序至少满足以下三个需求之一:

  1. 使用Spring WebApplicationContext
  2. 定义session的 scope
  3. 存在StandardServletEnvironment

@ConditionalOnProperty

该注释允许基于Spring环境属性的存在和值进行配置。

例如,如果我们针对不同的环境具有不同的数据源定义,则可以使用此注解。

@Bean@ConditionalOnProperty(name = "env", havingValue = "local")DataSource dataSource() { // ...}@Bean@ConditionalOnProperty(name = "env", havingValue = "prod")DataSource dataSource() { // ...}

@ConditionalOnResource

该注释只允许在类路径中出现特定资源时才注解bean。可以使用通常的Spring约定来指定资源。

@ConditionalOnResource(resources = "classpath:vendor.properties")Properties additionalProperties() { // ...}

@ConditionalOnExpression

该注解允许基于SpEL表达式的结果进行配置。当要评估的条件是复杂的且应作为一个条件进行评估时,使用该注解。

@Bean@ConditionalOnExpression("${env} && ${havingValue == 'local'}")DataSource dataSource() { // ...}

@ConditionalOnCloudPlatform

该注解允许在指定的云平台处于活动状态时注册bean。

@Configuration@ConditionalOnCloudPlatform(CloudPlatform.CLOUD_FOUNDRY)public class CloudConfigurationExample { @Bean public MyBean myBean(MyProperties properties)  { return new MyBean(properties.getParam); }}