前言
2021SC@SDUSC
概述
本篇博客延续上次的话题,对项目Controller层源码进行进一步分析
源码
源码如下:
@RestController
@RequestMapping("/problemset")
public class ProblemsetController {
@Autowired
private ProblemsetService problemsetService;
@Autowired
private ProblemService problemService;
private final Logger log = LoggerFactory.getLogger(ProblemController.class);
@PostMapping("/getProblemset")
@PreAuthorize("hasRole('ROLE_COMMON')")
public ResultEntity getProblemset(@RequestParam("id") int id) {
try {
Problemset problemset = problemsetService.getProblemset(id);
List<Problem> problemList = problemsetService.getProblemList(id);
problemset.setProblems(problemList);
return ResultEntity.success("题目集", problemset);
} catch (Exception e) {
log.error("查看题目集错误", e);
return ResultEntity.error("查看题目集错误,请重试");
}
}
}
在上一篇博客中已经分析了两个注解的实现原理:@RestController 和 @RequestMapping
下面我们将对其余关键点进行分析
@Autowired实现原理
使用方法
目前@Autowired最常用的使用方法有两种:
1.属性注入:
public Class Outer {
@Autowired
private Inner inner;
}
2.方法注入:
public Class Outer {
private Inner inner;
public Inner getInner() {
return inner;
}
@Autowired
public void setInner(Inner inner) {
this.inner = inner;
}
}
这两种使用方法的内部实现原理其实是一样的
源代码
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
boolean required() default true;
}
分析原理
其实基本原理比较简单,主要也是利用了Java的反射机制。在容器启动,为对象赋值的时候,遇到@Autowired注解,会用后置处理器机制,来创建属性的实例,然后再利用反射机制,将实例化好的属性,赋值给对象上,这就是Autowired的原理。
具体代码流程可以参考:
@Autowired注解注入实现原理_小燃儿的博客-CSDN博客_autowired实现原理
slf4j日志
对应代码:
private final Logger log = LoggerFactory.getLogger(ProblemController.class);
和catch Exception后:
log.error("查看题目集错误", e);
是关于slf4j日志插件的使用,网上也有很多教程和解释,这里不是我们的关键代码,因此不再赘述,有兴趣的可以自行了解
@PostMapping实现原理
使用
@PostMapping(value = "/user/login")
等价于
@RequestMapping(value = "/user/login",method = RequestMethod.POST)
其实@PostMapping是一个复合注解,相当于@RequestMapping对于POST模式的简化版本
源代码
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@RequestMapping(
method = {RequestMethod.POST}
)
public @interface PostMapping {
@AliasFor(
annotation = RequestMapping.class
)
String name() default "";
@AliasFor(
annotation = RequestMapping.class
)
String[] value() default {};
@AliasFor(
annotation = RequestMapping.class
)
String[] path() default {};
@AliasFor(
annotation = RequestMapping.class
)
String[] params() default {};
@AliasFor(
annotation = RequestMapping.class
)
String[] headers() default {};
@AliasFor(
annotation = RequestMapping.class
)
String[] consumes() default {};
@AliasFor(
annotation = RequestMapping.class
)
String[] produces() default {};
}
分析原理
我们可以很清楚的看到,其内部就是对于@RequestMapping的一层封装,内部默认RequestMapping的method为POST,其实是对于Restful风格的一种支持
以下同类型注解:
@GetMapping、@PutMapping、@PatchMapping和@DeleteMapping,与@PostMapping实现类似
总结
至此,Controller层源码已经快要分析完成了,预计下一篇博客会完成收尾并开启下一个专题分析,希望大家能在会使用的同时,对代码的内部实现有更深入的理解。
参考资料
spring源码16: @Autowired实现原理_bugpool的博客-CSDN博客_@autowired实现原理
https://segmentfault.com/a/1190000018077152
Spring MVC的@PostMapping注解 - 程序员大本营