本文主要介绍Spring
中一些常见注解的部分属性配置介绍以及一些不常用注解的简单介绍。下面让我们直接进入主题吧。
@RequestMapping
@RequestMapping
可以说是SpringMVC
以及OpenFeign
中最常用的注解,其主要用于映射Web
请求。
produces属性配置
当前主流服务大部分都是使用JSON
作为数据交换格式,即通过配置MappingJackson2HttpMessageConverter
或者GsonHttpMessageConverter
定义数据交换时使用JSON
进行格式转换。这时候默认的响应数据格式就是application/json
,如果想要让RequestMapping
请求返回text/html
或者其他非application/json
数据。那么RequestMapping#produces
就可以派上用场了。
produces
属性配置可以调整数据响应格式,比如下面这段代码:
@RequestMapping(value = "/html", produces = {MediaType.TEXT_HTML_VALUE})
public String html() {
return "<!DOCTYPE html>n" +
"<html lang="en">n" +
" <head>n" +
" <meta charset="UTF-8">n" +
" <title>HTML</title>n" +
" </head>n" +
" <body>n" +
" <p>Hello World!</p>n" +
" </body>n" +
"</html>n";
}
这时候请求该页面返回的数据格式就是text/html;charset=UTF-8
了。如果我们不添加produces
配置,那么由于我们也配置了StringHttpMessageConverter
,并且配置的StringHttpMessageConverter
执行顺序早于MappingJackson2HttpMessageConverter
等JSON
消息转换器,那么这时候返回的数据格式就是text/plain;charset=UTF-8
。具体看各自应用的消息转换器配置情况。
consumes属性配置
既然有produces
属性可以配置数据的响应格式,那么当然也有对应的consumes
配置用来限定请求映射的数据格式。如下面这段代码:
@PostMapping(value = "/htmlReq", consumes = {MediaType.TEXT_HTML_VALUE})
public R<Void> htmlReq(@RequestBody String html) {
log.info("html: {}", html);
return R.status(true);
}
@PostMapping("/htmlReq")
public R<Void> htmlReqNoConsumes(@RequestBody String html) {
log.info("html: {}", html);
return R.status(true);
}
这里我们定义了两个同样的请求映射/htmlReq
,其中一个通过consumes
限定了请求映射的数据格式必须是text/html
,另一个不限定数据映射格式。
可以看到请求的数据格式如果是text/html
,那么将会被映射到htmlReq
方法。其他格式则被映射到htmlReqNoConsumes
方法。
produces
和consumes
属性通常用于与外部的对接,使用频率较低,有时候外部对接文档不完善,这时候我们就要通过直接发送请求确认他们的请求响应数据格式要求,然后相应的使用produces
和consumes
进行调整。
派生注解
说到@RequestMapping
,就不得不提及它的派生注解:@GetMapping
、@PostMapping
、@DeleteMapping
等注解。这些注解首先都标注了@RequestMapping
,即他们本身都是@RequestMapping
注解,然后通过@AliasFor
注解将注解的属性别名映射到@RequestMapping
的属性上。最后使用的使用通过AnnotationUtils
和AnnotatedElementUtils
进行别名配置合并或者同义化处理,注意派生注解在Spring
框架注解中用的相当多,我们可以通过派生注解的方法进一步增强@RequestMapping
,比如添加版本号映射功能等。这些后续有机会再讲。
@Ordered 和 @Priority
@Ordered
注解和@Priority
注解以及org.springframework.core.Ordered
接口都可以定义Bean
的实例化顺序,同时Spring
提供了org.springframework.core.annotation.AnnotationAwareOrderComparator
工具类让我们可以对特定的Bean
数组或者列表依照从小到大进行排序。如下代码:
public interface XxHandler {
}
@Component
@Priority(1)
public class AHandler implements XxHandler {
}
@Component
@Priority(3)
public class BHandler implements XxHandler {
}
@Component
@Order(2)
public class CHandler implements XxHandler {
}
@Component
@Priority(1)
public class DHandler implements XxHandler, Ordered {
@Override
public int getOrder() {
return 4;
}
}
那么启动容器后,通过AnnotationAwareOrderComparator#sort
方法排序所有XxHandler
实例的时候,将能够得到ACBD
处理器有序列表。
@EnableAutoConfiguration
@EnableAutoConfiguration
注解用于激活Spring
的自动配置,在SpringBoot
项目可能看得比较少,因为实际上该注解已经默认组合到@SpringBootApplication
注解了。该注解的主要作用简单理解就是搜索所有classpath
路径下的META-INF/spring.factories
配置文件中的org.springframework.boot.autoconfigure.EnableAutoConfiguration
配置项中定义的类完全限定名,然后将这些类统一作为配置类交给Spring
进行自动配置。搜索可以发现classpath
下有很多的spring.factories
配置文件:
spring.factories
配置文件的org.springframework.boot.autoconfigure.EnableAutoConfiguration
配置项是自定义SpringBootStarter
的核心,通过该配置项和@EnableAutoConfiguration
我们可以实现高度可插拔的SpringBootStarter
,这个有机会可以另外开篇讲解。
@Import
@Import
注解是一个比较有趣的注解,它既可以自由选择需要加载的配置类,也可以高度自由地定义Bean
的注册。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Import {
/**
* {@link Configuration}, {@link ImportSelector}, {@link ImportBeanDefinitionRegistrar}
* or regular component classes to import.
*/
Class<?>[] value();
}
它只有一个必填属性value
,具体有三种用法:
导入配置类
这种方法导入的类通常标注有@Configuration
,当然这不是硬性要求。比如Druid
的数据源自动配置:
@Configuration
@ConditionalOnClass(DruidDataSource.class)
@AutoConfigureBefore(DataSourceAutoConfiguration.class)
@EnableConfigurationProperties({DruidStatProperties.class, DataSourceProperties.class})
@Import({DruidSpringAopConfiguration.class,
DruidStatViewServletConfiguration.class,
DruidWebStatFilterConfiguration.class,
DruidFilterConfiguration.class})
public class DruidDataSourceAutoConfigure {
private static final Logger LOGGER = LoggerFactory.getLogger(DruidDataSourceAutoConfigure.class);
@Bean(initMethod = "init")
@ConditionalOnMissingBean
public DataSource dataSource() {
LOGGER.info("Init DruidDataSource");
return new DruidDataSourceWrapper();
}
}
选择性加载配置类
这种方式导入的类必须实现org.springframework.context.annotation.ImportSelector
接口,通过该接口的selectImports(AnnotationMetadata importingClassMetadata)
方法确定导入的配置类。比如:@CacheAutoConfiguration
。
动态注册Bean
这种方式导入的类必须实现org.springframework.context.annotation.ImportBeanDefinitionRegistrar
接口,通过registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry)
方法动态注册SpringBean
。比如:MyBatis
的@MapperScan
注解导入的MapperScannerRegistrar
。是自
@Import
通常会结合@EnableXxx
(Spring
的自动配置类)注解使用。算是自动化配置的一个核心类。
@Role
这个注解应该说大部分人没见过,即使见过应该也不会用到。这个注解主要用户标注SpringBean
的角色。总共有三种角色:
ROLE_APPLICATION
简单理解就是这个Bean
属于用户,是应用大部分Bean
的角色。通常我们的Bean
默认就是这种。
ROLE_SUPPORT
指示Bean
同样属于用户,但是一般是外部配置的比较复杂的Bean
。
ROLE_INFRASTRUCTURE
指示Bean
不属于用户,属于Spring
内部的基础设施Bean
,通常给Spring
内部工作使用。
这个注解在高度自定义校验器(抽离成独立依赖并提供给其他服务集成使用,而不是在各个应用中单独配置)的时候会用到,如果你自己注册到Spring
的LocalValidatorFactoryBean
没有添加@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
注解,那么运行时将直接报错。默认的ValidationAutoConfiguration
自动配置如下:
public class ValidationAutoConfiguration {
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@ConditionalOnMissingBean(Validator.class)
public static LocalValidatorFactoryBean defaultValidator() {
LocalValidatorFactoryBean factoryBean = new LocalValidatorFactoryBean();
MessageInterpolatorFactory interpolatorFactory = new MessageInterpolatorFactory();
factoryBean.setMessageInterpolator(interpolatorFactory.getObject());
return factoryBean;
}
}
目前该角色的Bean
主要由org.springframework.aop.framework.autoproxy.InfrastructureAdvisorAutoProxyCreator
进行判断是否生成自动代理切面。
限于篇幅原因,本文不少注解没有实例讲解,后续有机会我们会单独开篇讲解。如有勘误,欢迎斧正!
原文始发于微信公众号(三维家技术实践):Spring注解介绍
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/30585.html