注解分类:
元注解:可以注解到别的注解上的注解。组合注解:被注解的注解我们就称之为组合注解。当多个注解被标注在同一个类上时,可以将这多个注解合并成一个注解。这个被合并的注解就是组合注解,如@SpringBootApplication @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @SpringBootConfiguration @EnableAutoConfiguration// 自动配置注解 @ComponentScan( excludeFilters = {@Filter( type = FilterType.CUSTOM, classes = {TypeExcludeFilter.class} ), @Filter( type = FilterType.CUSTOM, classes = {AutoConfigurationExcludeFilter.class} )} ) public @interface SpringBootApplication {// SpringBootApplication是一个组合注解 @AliasFor( annotation = EnableAutoConfiguration.class, attribute = "exclude" ) Class<?>[] exclude() default {}; @AliasFor( annotation = EnableAutoConfiguration.class, attribute = "excludeName" )@Value 就相当于传统 xml 配置文件中的 value 字段。
<bean class="RequestTestRunnerService"> <property name ="APP_ENV" value="pre"></property> </bean>@Value取值来源:
字面量 @Value("值")通过 ${key} 方式从环境变量中获取值通过 ${key} 方式全局配置文件 application.yml中获取值#{SpEL} @Slf4j @Service("requestTestRunnerService") public class RequestTestRunnerService { public static String APP_ENV; @Value("${appEnv}") private void setAppEnv(String appEnv) { // static 变量只能通过set方法注入值 APP_ENV = appEnv; } }@Value 的升级版,@ConfigurationProperties将标注的类中的属性和配置文件中的配置项绑定起来。默认配置文件是主配置文件application.yml
// 线程池配置项 task: pool: corePoolSize: 20 maxPoolSize: 40 keepAliveSeconds: 300 queueCapacity: 50 threadNamePrefix: nanaThread- // 如下是@ConfigurationProperties标注的配置项类,类中属性与配置文件中的配置项一一绑定, // 类中属性名和配置文件中的属性名必须相同,且配置项类必须有setter和getter方法,否则无法注入成功。 @Data @ConfigurationProperties(prefix = "task.pool") public class ThreadPoolProperties { private int corePoolSize; private int maxPoolSize; private int keepAliveSeconds; private int queueCapacity; private String threadNamePrefix; }注:
如果一个配置类只配置@ConfigurationProperties注解,而没有使用@Component,那么在IOC容器中是获取不到properties 配置文件转化的bean,即获取不到ThreadPoolProperties。
@EnableConfigurationProperties可以解决上述,没有使用配置属性类@Component时,获取不到ThreadPoolProperties 的bean的问题。
当@EnableConfigurationProperties注解应用到你的@Configuration时, 任何被@ConfigurationProperties注解的beans将自动被Environment属性配置。 这种风格的配置特别适合与SpringApplication的外部YAML配置进行配合使用。如下所示:
// 线程池配置类 @Slf4j @Configuration @EnableConfigurationProperties({ThreadPoolProperties.class}) @EnableAsync public class ThreadPoolAutoConfiguration { private static final int THREADS = Runtime.getRuntime().availableProcessors() + 1; @Autowired private ThreadPoolProperties threadPoolProperties; /** * 异步任务执行器 * @return */ @Bean public Executor asyncServiceExecutor() { log.info("start asyncServiceExecutor"); ThreadPoolTaskExecutor executor = new VisiableThreadPoolTaskExecutor(); //配置核心线程数 executor.setCorePoolSize(THREADS); //配置最大线程数 executor.setMaxPoolSize(threadPoolProperties.getMaxPoolSize()); //配置队列大小 executor.setQueueCapacity(99999); //配置线程池中的线程的名称前缀 // executor.setThreadNamePrefix("AsyncService-"); executor.setThreadNamePrefix(threadPoolProperties.getThreadNamePrefix()); // rejection-policy:当pool已经达到max size的时候,如何处理新任务 // CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行 executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); //执行初始化 executor.initialize(); return executor; } }
@Import 注解支持导入普通 java 类,并将其声明成一个bean。主要用于将多个分散的 java config 配置类融合成一个更大的 config 类。
(1)导入普通的java类
// 普通java类 public class Circle { public void sayHi() { System.out.println("Circle sayHi()"); } } // 导入java类,成为IOC容器中的bean @Import({Circle.class}) @Configuration public class MainConfig { } public static void main(String[] args) { ApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class); Circle circle = context.getBean(Circle.class); circle.sayHi(); }(2)配合自定义的 ImportSelector 使用
ImportSelector 是一个接口,该接口中只有一个 selectImports 方法,用于返回全类名数组。所以利用该特性我们可以给容器动态导入 N 个 Bean。
public class Triangle { public void sayHi(){ System.out.println("Triangle sayHi()"); } } public class MyImportSelector implements ImportSelector { @Override public String[] selectImports(AnnotationMetadata annotationMetadata) { // 返回的是全路径类名 return new String[]{"annotation.importannotation.waytwo.Triangle"}; } } // 导入类 @Import({Circle.class,MyImportSelector.class}) @Configuration public class MainConfigTwo { }
@Conditional 注解:只有在特定条件满足时才启用配置。
Spring 还为我们扩展了一些常用的 Condition。
扩展注解 作用
ConditionalOnBean 容器中存在指定 Bean,则生效。
ConditionalOnMissingBean 容器中不存在指定 Bean,则生效。
ConditionalOnClass 系统中有指定的类,则生效。
ConditionalOnMissingClass 系统中没有指定的类,则生效。
ConditionalOnProperty 系统中指定的属性是否有指定的值。
ConditionalOnWebApplication 当前是web环境,则生效。
springboot应用通过注解@SpringBootApplication标注的类是应用启动的入口,是应用的主类。
而@SpringBootApplication注解定义中包含自动配置注解@EnableAutoConfiguration
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @SpringBootConfiguration @EnableAutoConfiguration// 自动配置注解 @ComponentScan( excludeFilters = {@Filter( type = FilterType.CUSTOM, classes = {TypeExcludeFilter.class} ), @Filter( type = FilterType.CUSTOM, classes = {AutoConfigurationExcludeFilter.class} )} ) public @interface SpringBootApplication { @AliasFor( annotation = EnableAutoConfiguration.class, attribute = "exclude" ) Class<?>[] exclude() default {}; @AliasFor( annotation = EnableAutoConfiguration.class, attribute = "excludeName" )