前言
本篇随笔将对 Spring Boot 中的常用注解做一个简单的整理归档, 写作顺序将从启动类开始并逐步向内外扩展, 目的即为了分享也为了方便自己日后的回顾与查阅
1. Application
启动类示例如下:
- @SpringBootApplication
- public class Application {
- public static void main(String[] args) {
- SpringApplication.run(Application.class, args);
- }
- }
第一个要讲解的注解是:@SpringBootApplication, 从直观的感受来看, 他是 SpringApplication 能够进入一系列复杂启动流程的先决条件进入源码我们可以观察到这是一个组合注解, 其切面之上还有三个注解, 分别为:@SpringBootConfiguration@EnableAutoConfiguration@ComponentScan
@SpringBootConfiguration 中真正起作用的是 @Configuration, 即标注当前类为 JavaConfig 配置类 (这里扩展一下, 任何标注了 @Configuration 的类都为配置类, 任何标注了 @Bean 的方法其返回值都是一个 Bean 的定义)
@EnableAutoConfiguration 是构成上诉组合注解的核心, 从名称上就能获取到浅显的信息: 启用自动配置, 他借助 @Import 将所有符合条件的 @Configuration 配置都注入到 IoC 容器中, 定义如下:
- @Target(ElementType.TYPE)
- @Retention(RetentionPolicy.RUNTIME)
- @Documented
- @Inherited
- @AutoConfigurationPackage
- @Import(AutoConfigurationImportSelector.class)
- public @interface EnableAutoConfiguration {
- String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
- Class<?>[] exclude() default {};
- String[] excludeName() default {};
- }
@ComponentScan 顾名思义, 他会扫描带有特定标注的组件 (如 @Controller@Component@Service@Repository), 并将其注入到 IoC 容器中
2. Test
测试类示例如下:
- @RunWith(SpringRunner.class)
- @SpringBootTest
- public class ApplicationTests {
- @Test
- public void contextLoads() {
- }
- }
@RunWith(SpringRunner.class) 翻译一下就是使用 Spring 的 IoC 容器运行测试;@SpringBootTest 创建了 SpringApplication 的上下文;@Test 标注测试方法在此推荐阅读 SpringBoot 单元测试 , 写得很详细, 我就不再赘述了, 待有空补几篇复杂测试的案例分析
3. 基本注解
3.1 @Service & @Repository
他们是在 Spring Boot 中轻松实现面向接口编程的关键, 一个用于逻辑层, 一个用于数据层, 示例如下:
- public interface HelloService {
- String notSay();
- }
- @Service
- public class HelloServiceImpl implements HelloService {
- @Override
- public String notSay() {
- return "shut up";
- }
- }
个人认为此处非常形象地体现了 约定优于配置, 可以理解为 Spring Boot 默认生成了这么一条 Bean:
- <bean id="HelloService" class="com.youclk.annotation.service.impl.HelloServiceImpl"></bean>
- 3.2 @Component
标注组件, 可以作用在任何层次
3.3 @Controller
控制器示例如下:
- @RestController
- public class HelloController {
- private final HelloService helloService;
- @Autowired
- public HelloController(HelloService helloService) {
- this.helloService = helloService;
- }
- @GetMapping("/{id}")
- public String say(@PathVariable("id") Integer id, @RequestParam("name") String name) {
- return (String.format("id=%d,name=%s;please %s", id, name, helloService.notSay()));
- }
- }
@RestController 查看源码可观察出其为 @Controller + @ResponseBody 的组合注解:
- @Target(ElementType.TYPE)
- @Retention(RetentionPolicy.RUNTIME)
- @Documented
- @Controller
- @ResponseBody
- public @interface RestController {
- @AliasFor(annotation = Controller.class)
- String value() default "";
- }
@GetMapping 其实就是对 @RequestMapping(method = RequestMethod.GET) 的进一步封装, 同理的还有 PostDeletePut 等等, 不同类型的请求都有其对应封装, 能少打不少代码
其他的在示例中也一目了然了:@Autowired 自动转配;@PathVariable 从 Url 中取值;@RequestParam 从参数中取值
4. 异常处理
示例如下:
- @ControllerAdvice
- public class GlobalException {
- @ResponseBody
- @ExceptionHandler
- public String processException(Exception e) {
- return "error:" + e.getMessage();
- }
- }
没啥好说的,@ExceptionHandler 可以过滤具体的异常类型:
@ExceptionHandler(Exception.class)
5. 配置
通过 @Value 可以直接拿到配置文件中的属性, 不过意义不是很大, 例:
- @Value("${my.name}")
- private String name;
更多的时候应该去拿到一个对象, 例:
- @Component
- @ConfigurationProperties(prefix = "my")
- public class My {
- private String name;
- private Integer age;
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public Integer getAge() {
- return age;
- }
- public void setAge(Integer age) {
- this.age = age;
- }
- }
@Profiles 按环境变量激活, 我觉得很不是很好的解决方案, 没怎么用过, 示例:
- @profile("dev")
- @profile("prod")
Spring Boot 提倡约定优于配置, 但有的时候我们不想守约, 如下:
- @Configuration
- public class DbConfiguration {
- private final Db db;
- @Autowired
- public DbConfiguration(Db db) {
- this.db = db;
- }
- @Bean(name = "dataSource")
- public DataSource dataSource() {
- BasicDataSource dataSource = new BasicDataSource();
- dataSource.setDriverClassName(db.driverClassName);
- dataSource.setUrl(db.driverUrl);
- dataSource.setUsername(db.driverUsername);
- dataSource.setPassword(db.driverPassword);
- return dataSource;
- }
- @Bean
- public PlatformTransactionManager transactionManager() {
- return new DataSourceTransactionManager(dataSource());
- }
- }
6. 其他
@Qualifier 是为了解决一个接口对应多个实现的冲突, 不过在设计上一般都会避免这种情况, 所以不是很常用, 示例:
- @Service("service1")
- public class HelloServiceImpl1 implements HelloService {
- }
- @Service("service2")
- public class HelloServiceImpl2 implements HelloService {
- }
- @Autowired
- @Qualifier("service1")
- HelloService helloService;
@Resource(name="name",type="type") 和 @Autowired 类似, 不常用
结语
近期正在寻觅新的工作机会, 若有意向, 欢迎留言, 微信: youclk
来源: https://www.cnblogs.com/youclk/p/8613551.html