2021.7.7 关于spring注解

2021.7.7 关于spring注解

1,@AutoConfigureBefore 和 @AutoConfigureAfter 是 spring-boot-autoconfigure 包下的注解

用法:

@AutoConfigureBefore(AAAA.class),或者@AutoConfigureBefore({
    
    AAAA.class,BBBB.class})

示例:

@AutoConfigureBefore(AAAA.class)
public class CCCC{
    
    
    
}

说明 CCCC 将会在 AAAA之前加载

@AutoConfigureAfter(AAAA.class),或者@AutoConfigureAfter({
    
    AAAA.class,BBBB.class})

实例:

@AutoConfigureAfter(AAAA.class)
public class CCCC{
    
    
    
}

说明 cccc 会在 aaaa之后加载

2,ValidationAutoConfiguration : springboot 自动配置

我的理解就是加上这个注解就可以 使用 validator 进行后端校验(使用JSR303的注解进行校验)。

确切的说是,首先要导入 validation的 jar包,然后是用户没有自己定义 javax.validation.validator 类型的bean的情况下。它允许我们在bean的方法参数或者方法上添加JSR303标准的validation注解。从而在进行bean的方法调用时可以对方法参数或者方法的返回值进行有效性校验。

使用方式:

@AutoConfigureBefore(ValidationAutoConfiguration.class)

概述:

ValidationAutoConfiguration 是 springboot 对应用中验证机制的自动配置,它主要向容器贡献了两个bean。

1,LocalValidatorFactoryBean defaultValidator

2,MethodValidationPostProcessor methodValidationPostProcessor

1,LocalValidatorFactoryBean defaultValidator

1,这就是一般意义上所说的 validator bean

2,仅在容器不存在类型为Validator 的 bean 时才定义,也就是说如果开发人员自己定义了 validator bean,则这里不定义

3,该定义确保容器中总是会有一个 validator bean

这个validator bean是基础性组件,应用中更上层的验证逻辑,比如基于JSR-303 注解的bean属性和方法参数的验证,都是使用该 validator bean组件。

2,MethodValidationPostProcessor methodValidationPostProcessor

1,这是一个 beanPostProcessor ,它会检测所有带注解@validated 的bean 定义,使用一个 带有 方法参数验证逻辑的 methodValidationPostProcessor 包裹这样的每一个bean (必要时会触发bean代理对象的创建)

2,仅在容器中不存在该类型的bean时才定义。

3,所使用的 validator bean 来自容器,如果开发人员未定义 validator bean ,则所使用的 validator bean 就是 本自动配置所定义的 validator bean。

注意:

validationAutoConfiguration 自动配置仅在检测到 classpath 上存在文件META-INF/services/javax.validation.spi.ValidationProvider和类 javax.validation.executable.ExecutableValidator 时才应用,因为这两个文件/类表明开发人员引入了相应的 Validation Provider jar包

3,@EnableAotoConfiguration

org.springframework.boot.autoconfigure.EnableAutoConfiguration

这个就是注解 @EnableAotoConfiguration 的全类名

关于 @EnableAutoConfiguration 大家估计都不陌生,@springbootApplication 下的三大注解之一,

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
    
    

	String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

	/**
	 * Exclude specific auto-configuration classes such that they will never be applied.
	 * @return the classes to exclude
	 */
	Class<?>[] exclude() default {
    
    };

	/**
	 * Exclude specific auto-configuration class names such that they will never be
	 * applied.
	 * @return the class names to exclude
	 * @since 1.3.0
	 */
	String[] excludeName() default {
    
    };

}

然后在 @EnableAutoConfiguration 类中,最重要的是 @Import(AutoConfigurationImportSelector.class)

,借助 AutoConfigurationImportSelector@EnableAutoConfiguration 可以帮助springboot 应用将所有符合条件的 @Configuration 配置都加载到当前springboot 创建并使用的IOC容器。

同时,借助于spring框架原有的一个工具类:springFactoriesLoader的支持,@EnableAutoConfiguration 可以智能的自动配置功效才得以大工告成。

在 AutoConfigurationImportSelector 类中可以看到 通过

List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
              getBeanClassLoader());

SpringFactoriesLoader.loadFactoryNames()把spring-boot-autoconfigure.jar /MATE-INF/spring.factories 中每一个 xxxAutoConfiguration 文件都加载到容器中,spring.factories 文件里每一个 xxxAutoConfiguration 文件一般都会有下面的条件注解:

  • @ConditionalOnClass : classpath中存在该类时起效
  • @ConditionalOnMissingClass : classpath中不存在该类时起效
  • @ConditionalOnBean : DI容器中存在该类型Bean时起效
  • @ConditionalOnMissingBean : DI容器中不存在该类型Bean时起效
  • @ConditionalOnSingleCandidate : DI容器中该类型Bean只有一个或@Primary的只有一个时起效
  • @ConditionalOnExpression : SpEL表达式结果为true时
  • @ConditionalOnProperty : 参数设置或者值一致时起效
  • @ConditionalOnResource : 指定的文件存在时起效
  • @ConditionalOnJndi : 指定的JNDI存在时起效
  • @ConditionalOnJava : 指定的Java版本存在时起效
  • @ConditionalOnWebApplication : Web应用环境下起效
  • @ConditionalOnNotWebApplication : 非Web应用环境下起效
...
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration,\

SpringFactoriesLoader

SpringFactoriesLoader 属于 spring 框架私有的一种扩展方案(类似java的spi方案 java.util.ServiceLoader),其主要功能就是从指定的配置文件MATE-INF/spring-factories 加载配置,spring-factories 时一个典型的java properties 文件。只不过 key 和 value都是 java 类型的完整类名,比如:

org.springframework.boot.autoconfigure.EnableAutoConfiguration
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
    
    
		List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
				getBeanClassLoader());
		Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you "
				+ "are using a custom packaging, make sure that file is correct.");
		return configurations;
	}

对于 @EnableAutoConfiguration 来说,SpringFactoriesLoader 的用途稍微不同一些,其本意是为了提供 spi 扩展的场景,而在 @EnableAutoConfiguration 场景中,它更多提供了一种配置查找的功能支持,即根据 @EnableAutoConfiguration 的完整类名 org.springframework.boot.autoconfigure.EnableAutoConfiguration

作为查找的key ,获得对应的一组 @Configuration 类。

SpringFactoriesLoader :是一个抽象类,类中定义的静态属性定义了其加载资源的路径:public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";此外还有三个静态方法:

  • loadFactories:加载指定的factoryClass并进行实例化
  • loadFactoryNames:加载指定的factoryClass的名称集合
  • instantiateFactory:对指定的factoryClass进行实例化。

在loadFactories 方法中调用了 loadFactoryNames 以及 instantiateFactory 方法

public static <T> List<T> loadFactories(Class<T> factoryType, @Nullable ClassLoader classLoader) {
    
    
        Assert.notNull(factoryType, "'factoryType' must not be null");
        ClassLoader classLoaderToUse = classLoader;
        if (classLoader == null) {
    
    
            classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
        }

        List<String> factoryImplementationNames = loadFactoryNames(factoryType, classLoaderToUse);
        if (logger.isTraceEnabled()) {
    
    
            logger.trace("Loaded [" + factoryType.getName() + "] names: " + factoryImplementationNames);
        }

        List<T> result = new ArrayList(factoryImplementationNames.size());
        Iterator var5 = factoryImplementationNames.iterator();

        while(var5.hasNext()) {
    
    
            String factoryImplementationName = (String)var5.next();
            result.add(instantiateFactory(factoryImplementationName, factoryType, classLoaderToUse));
        }

        AnnotationAwareOrderComparator.sort(result);
        return result;
    }

loadFactories 方法首先获取类加载器,然后调用 loadFactoryNames 方法获取所有指定资源的名称集合 ,接着调用 instantiateFactory 方法实例化这些资源类并将其添加到result集合中,最后调用 AnnotationAwareOrderComparator.sort(result); 方法进行集合的排序。

猜你喜欢

转载自blog.csdn.net/dearand/article/details/118610914