@interface
- @interface是用来自定义注解类型的,可定义多个参数和默认值,核心参数使用value名称
- 必须设置@Target来指定Annotation可以应用的范围
- 应当设置@Retention(RetentionPolicy.RUNTIME)便于运行期读取该Annotation
@Ducumented
将此注解包含在Javadoc中
@Inherited
允许子类继承父类中的注解
@Target
用来定义注解应用于什么地方,取值有:
- CONSTRUCTOR:用于描述构造器
- FIELD:用于描述域
- LOCAL_VARIABLE:用于描述局部变量
- METHOD:用于描述方法
- PACKAGE:用于描述包
- PARAMETER:用于描述参数
- TYPE:用于描述类、接口(包括注解类型) 或enum声明
@Retention
定义该注解在哪一个级别可用,
- RetentionPolicy.SOURCE —— 这种类型的Annotations只在源代码级别保留,编译时就会被忽略
- RetentionPolicy.CLASS —— 这种类型的Annotations编译时被保留,在class文件中存在,但JVM将会忽略
- RetentionPolicy.RUNTIME —— 这种类型的Annotations将被JVM保留,所以他们能在运行时被JVM或其他使用反射机制的代码所读取和使用.
@Import注解的用法
SpringBoot 的 @Import 用于将指定的类实例注入之Spring IOC Container中。
- 直接导入类
@Configuration
@Import(value={UserServiceImpl.class})
public class Config {
}
- 直接导入配置类(@configuration)
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import({RocketAutoConfiguration.class})
public @interface EnableRocketMQ {
}
@Configuration
@EnableConfigurationProperties({RocketProperties.class})
@ConditionalOnBean(annotation = {EnableRocketMQ.class})
public class RocketAutoConfiguration {
@Resource
private RocketProperties rocketProperties;
@Resource
private Map<String, Object> consumerContainer;
@Resource
private RocketSerializer rocketSerializer;
public RocketAutoConfiguration() {}
@Bean
@ConditionalOnMissingBean({RocketConsumerContainer.class})
public RocketConsumerContainer rocketConsumerContainer() {
return new RocketConsumerContainer(this.rocketProperties, this.rocketSerializer);
}
}
- 依据条件选择配置类(实现 ImportSelector 接口)
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Import({AudioScoreServiceImportSelector.class})
public @interface EnableAudioVoiceScore {
AudioScoreMode mode() default AudioScoreMode.ALL;
}
public class AudioScoreServiceImportSelector extends AudioScoreModeImportSelector<EnableAudioVoiceScore> {
public AudioScoreServiceImportSelector() {
}
protected String[] selectImports(AudioScoreMode mode) {
switch(mode) {
default:
return null;
}
}
}
public abstract class AudioScoreModeImportSelector<A extends Annotation> implements ImportSelector {
private static final String DEFAULT_ADVICE_MODE_ATTRIBUTE_NAME = "mode";
public AudioScoreModeImportSelector() {
}
@NonNull
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
Class<?> annType = GenericTypeResolver.resolveTypeArgument(this.getClass(), AudioScoreModeImportSelector.class);
Assert.state(annType != null, "Unresolvable type argument for AudioScoreModeImportSelector");
AnnotationAttributes attributes = AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(annType.getName(), false));
if (attributes == null) {
throw new IllegalArgumentException(String.format("@%s is not present on importing class '%s' as expected", annType.getSimpleName(), importingClassMetadata.getClassName()));
} else {
AudioScoreMode adviceMode = (AudioScoreMode)attributes.getEnum(this.getAdviceModeAttributeName());
String[] imports = this.selectImports(adviceMode);
if (imports == null) {
throw new IllegalArgumentException("Unknown AdviceMode: " + adviceMode);
} else {
return imports;
}
}
}
@Nullable
protected abstract String[] selectImports(AudioScoreMode mode);
protected String getAdviceModeAttributeName() {
return "mode";
}
}
- 动态注册Bean(实现 ImportBeanDefinitionRegistrar接口)
package com.example.demo.bean;
public class TestBean4 {
}
public class TestImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(TestBean4.class);
registry.registerBeanDefinition("TestBean4", rootBeanDefinition);
}
}
@Import({TestImportBeanDefinitionRegistrar.class})
@Configuration
public class AppConfig {
}
@NotNull
不能为null,但可以为empty
@NotEmpty
不能为null,而且长度必须大于0
@NotBlank
只能作用在String上,不能为null,而且调用trim()后,长度必须大于0
@ConfigurationProperties
- 使用方式
- 配合@component注解直接进行注入,只有当类所在的包被 Spring @ComponentScan 注解扫描到才会生效
@Data @Component @ConfigurationProperties(prefix = AppLinkConfig.PREFIX) public class AppLinkConfig { public static final String PREFIX = "student"; private String appLink; }- 把@ConfigurationProperties还可以直接定义在@bean的注解上
@Bean @ConfigurationProperties(prefix = "connection") public ConnectionSettings connectionSettings(){ return new ConnectionSettings(); }- 配合@EnableConfigurationProperties,在该注解中其实是用了@Import(EnableConfigurationPropertiesImportSelector.class) 实现,通常配置在@configuration类上,也可用在其他@component派生类上
@ConfigurationProperties(prefix = "acme") @Data public class AcmeProperties { private boolean enabled; private InetAddress remoteAddress; } @Configuration @EnableConfigurationProperties({AcmeProperties.class}) public class AcmeConfigTest { } @RestController @RequestMapping("/properties-get") public class PropertiesTestController { //此处注入 @Autowired private AcmeProperties acmeProperties; @GetMapping("/address") public String getRemoteAddress(){ return JSON.toJSONString(acmeProperties.getRemoteAddress()); } @GetMapping("/enable") public String getEnabled(){ return JSON.toJSONString(acmeProperties.isEnabled()); } }
@RefreshScope
- 需要热加载的bean需要加上@RefreshScope注解,当配置发生变更的时候可以在不重启应用的前提下完成bean中相关属性的刷新
- RefreshScope代理的bean强制为懒加载,只有在第一次使用的时候才会生成实例,当其需要刷新配置的时候直接调用destory()方法销毁当前bean,这样在刷新配置后在需要生成的bean已经是根据新的配置信息生成,完成bean的热加载
@Valid和@Validated
@RequestBody
- 注解@RequestParam接收的参数是来自HTTP请求体或请求url的QueryString中
- @RequestParam用来处理Content-Type为application/x-www-form-urlencoded编码的内容,Content-Type默认为该属性
- @RequestParam也可用于其它类型的请求,例如:POST、DELETE等请求。
@RequestParam
- 注解@RequestBody接收的参数是来自requestBody中,即请求体。一般用于处理非 Content-Type: application/x-www-form-urlencoded编码格式的数据,比如:application/json、application/xml等类型的数据
- 常用于向表中批量插入数据
@EnableConfigurationProperties
- 使使用@ConfigurationProperties 注解的类生效
- 如果一个配置类只配置@ConfigurationProperties注解,而没有使用@Component,那么在IOC容器中是获取不到properties配置文件转化的bean。说白了@EnableConfigurationProperties 相当于把使用@ConfigurationProperties 的类进行了一次注入
@ConfigurationProperties(prefix = "service.properties")
public class HelloServiceProperties {
private static final String SERVICE_NAME = "test-service";
private String msg = SERVICE_NAME;
set/get
}
@Configuration
@EnableConfigurationProperties(HelloServiceProperties.class)
@ConditionalOnClass(HelloService.class)
@ConditionalOnProperty(prefix = "hello", value = "enable", matchIfMissing = true)
public class HelloServiceAutoConfiguration {
}
@RestController
public class ConfigurationPropertiesController {
@Autowired
private HelloServiceProperties helloServiceProperties;
@RequestMapping("/getObjectProperties")
public Object getObjectProperties () {
System.out.println(helloServiceProperties.getMsg());
return myConfigTest.getProperties();
}
}
@ConditionalOnBean
- 要求bean存在时,才会创建这个bean;如我提供了一个bean名为RedisOperBean,用于封装redis相关的操作;但是我这个bean需要依赖restTemplate这个bean,只有当应用引入了redis的相关依赖,并存在RestTemplate这个bean的时候,我这个bean才会生效
@Component
@ConditionalOnBean(name="redisTemplate")
public class RedisOperBean {
private final RedisTemplate redisTemplate;
public RedisOperBean(RedisTemplate redisTemplate) {
// ...
}
}
@DependsOn
- 该注解用于声明当前bean依赖于另外一个bean。所依赖的bean会被容器确保在当前bean实例化之前被实例化。举例来讲,如果容器通过@DependsOn注解方式定义了bean plant依赖于bean water,那么容器在会确保bean water的实例在实例化bean plant之前完成。
@ConditionalOnMissingBean
- 结合使用注解@ConditionalOnMissingBean和@Bean,可以做到只有特定名称或者类型的Bean不存在于BeanFactory中时才创建某个Bean
- 实例:
@Configuration
public class FeignClientsConfiguration {
@Bean
@ConditionalOnMissingBean
public Decoder feignDecoder() {
return new OptionalDecoder(
new ResponseEntityDecoder(new SpringDecoder(this.messageConverters)));
}
@Bean
@ConditionalOnMissingBean
public Retryer feignRetryer() {
return Retryer.NEVER_RETRY;
}
@AllArgsConstructor
- @AllArgsConstructor是Lombok中的一个注解,其功能是生成一个为类中所有非static变量以及未初始化的final变量进行赋值的构造函数,被@AllArgsConstructor注解的类内可省略@Autowired
@ConditionalOnProperty
@ConditionalOnClass
只有在classpath下能找到类才会构建这个bean