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);
方法进行集合的排序。