专栏首页有刻Java 小记 — Spring Boot 注解

Java 小记 — Spring Boot 注解

前言

本篇随笔将对 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) 的进一步封装,同理的还有 Post、Delete、Put 等等,不同类型的请求都有其对应封装,能少打不少代码。

其他的在示例中也一目了然了:@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 类似,不常用。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Java 小记 — Spring Boot 的实践与思考

    捷义
  • DSL 系列(1) - 扩展点的论述与实现

    DSL 全称为 domain-specific language(领域特定语言),本系列应当会很长,其中包含些许不成熟的想法,欢迎私信指正。

    捷义
  • Java 小记 - 时间的处理与探究

    时间的处理与日期的格式转换几乎是所有应用的基础职能之一,几乎所有的语言都会为其提供基础类库。作为曾经 .NET 的重度使用者,赖其优雅的语法,特别是可扩展方法这...

    捷义
  • 学习 Spring,看松哥这篇万余字的干货,够用了!

    我们常说的 Spring 实际上是指 Spring Framework,而 Spring Framework 只是 Spring 家族中的一个分支而已。那么 S...

    江南一点雨
  • 4.json解析

    六月的雨
  • 自己动手写区块链-发起一笔交易(Java版)

    本文我们将会做以下事情: 1、创建一个钱包(wallet)。 2、使用我们的前面创建的区块链发送一笔签名的交易出去。 3、还有其他更叼的事情等等。 听起来是不是...

    ImportSource
  • Java泛型学习

    1、泛型的概念     泛型即“参数化类型”,就比如我们定义方法的时候,定义一个变量,称为形参,变量值根据传进去的实参的值不同而改变。而泛型的出现,就是为了解决...

    JMCui
  • Java基础-day09-代码题-对象;类;封装

    Java基础-day09-代码题-对象&类&封装 一、定义一个空调类和对应的测试类 该题考查点:属性和方法的使用! 要求: 1、空调有品牌和价格两个属性,并且将...

    Java帮帮
  • Java之面向对象例子(二)

    定义一个Book类,在定义一个JavaBook类继承他 //book类 package com.hanqi.maya.model; public class B...

    二十三年蝉
  • hadoop数据类型及自定义

    自定义Hadoop数据类型后,需要明确告诉Hadoop来使用它们。这是 JobConf 所能担当的了。

    字母哥博客

扫码关注云+社区

领取腾讯云代金券