zoukankan      html  css  js  c++  java
  • 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 类似,不常用。

    结语

    近期正在寻觅新的工作机会,若有意向,欢迎留言,微信: youclk。


    我的公众号《有刻》,我们共同成长!

    作者:捷义
    出处:http://www.cnblogs.com/youclk/
    说明:转载请标明来源和作者
  • 相关阅读:
    numpy百题冲关,pandas百题冲关
    mapreduce过程以及相关类总结
    mapreduce,数据结构和类型介绍
    精确度、召回率、混淆矩阵的关系
    小程序点击图片放大效果 单张图片 多张图片
    小程序动态添加class及调接口传递多个参数
    小程序for循环嵌套
    小程序富文本转换
    jquery函数加载及生成随机数
    微信小程序 swiper 显示图片计数 当前/总数
  • 原文地址:https://www.cnblogs.com/youclk/p/8613551.html
Copyright © 2011-2022 走看看