Java 小記 — Spring Boot 註解

前言

本篇隨筆將對 Spring Boot 中的經常使用註解作一個簡單的整理歸檔,寫做順序將從啓動類開始並逐步向內外擴展,目的即爲了分享也爲了方便本身往後的回顧與查閱。
java

1. Application

啓動類示例以下:spring

@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 容器中,定義以下:app

@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 容器中。ide

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 中輕鬆實現面向接口編程的關鍵,一個用於邏輯層,一個用於數據層,示例以下:this

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 相似,不經常使用。

結語

近期正在尋覓新的工做機會,如有意向,歡迎留言,微信: youclk。


個人公衆號《有刻》,咱們共同成長!

相關文章
相關標籤/搜索