spring-boot注解大全


spring boot是后端开发最主流的框架,spring boot的核心之一就是注解,它提供了很多注解来帮助我们简化配置,通过各种组合注解,极大地简化了spring项目的搭建和开发。为了方便我们在日常开发注解的使用,本文将开发所需要的注解统一并进行归类起来,并结合用例进行解析,这样收藏起来以便日后使用。

依赖注入

组件注解

@component,而其余 @Controller@Service@Repository都组合了@component注解,主要为便于使用者Class组件进行归类。默认加载IOC容器中的组件,容器启动会调用无参构造器创建对象,再进行初始化赋值等操作

注解 解析 用法
@Component 组件注解,使用了该注解会基于注释的配置和类路径扫描时。
会自动扫描并加载Class到ICO容器中
类上
@Controller 使用@Controller 注解类,在对应的方法上,视图解析器可以解析return 的 jsp,html页面
并且跳转到相应页面。此注解属于MVC中的C层(视图控制层)
类上
@RestController 相当于@ResponseBody + @Controller合在一起的作用。使用@RestController注解,
无法返回jsp页面,或者html。只返回JSON格式的数据
类上
@Service 应用在service层(业务逻辑层) 类上
@Repository 应用在dao层(数据访问层) 类上
@Mapper 如果使用@Repository则需要使用@MapperScan(“xxx.xxx.mapper”)进行扫描
然后生成Dao层的Bean才能被注入到Service层中。
@Mapper=@Repository+@MapperScane
类上

依赖注入注解

Autowired注解和@Inject、@Resource,可以与@Qualifier或者@Name配合使用,防止多实例注入时出错,以及值注入@Value。

注解 解析 用法
@Autowired 通过AutowiredAnnotationBeanPostProcessor类实现的依赖注入,默认是根据类型进行注入的
因此如果有多个类型一样的Bean候选者,则需要限定其中一个候选者,否则将抛出异常。
字段上
方法上
@Inject 作用与@Autowired一样 字段上
方法上
@Resource 默认按照名称进行装配,名称可以通过name属性进行指定 字段上
方法上
@Qualifier 限定描述符除了能根据名字进行注入,更能进行更细粒度的控制如何选择候选者
可与@Autowired或者@Inject进行组合使用,进行精确注入
字段上
方法上

作用域和生命过程

注解 解析 用法
@Scope 具有4个作用域,默认是单例模式,也就是singleton
Singleton(单例式):在整个应用中,只创建bean的一个实例。
Prototype(原型式):每次注入或者通过Spring应用上下文获取时,会创建一个新的bean实例。等同于new方式创建对象
Session(会话式):在Web应用中,为每个会话创建一个bean实例。(电子商务应用中,一个bean代表一个用户的购物车,只要同一个session一个bean)。
Request(请求式):在Web应用中,为每个请求创建一个bean实例。
类上
@PostConstruct 相当于init-method,在类的实例被初始化时执行,作用于方法上。 方法上
@PreDestroy 相当于destory-method,使用在方法上,当Bean销毁时执行 方法上

下面代码例子:

@Service //组件注入,注明为service组件
@Scope("prototype")//声明Scope为Prototype
public class UseFunctionService {

    @Autowired //默认按type注入
    @Qualifier("functionService") //精确注入
    FunctionService functionService;
    @Resource(name="baseDao")//默认按name注入,可以通过name和type属性进行选择性注入
    private BaseDao baseDao;
    @Inject
    @Qualifier("userServiceImpl") //精确注入  
    public IUserService userService;  

    @PostConstruct//在UseFunctionService类实例执行完构造函数后执行
    public postConstruct(){
        System.out.println("postConstruct");
    }
    @PreDestroy//在UseFunctionService类实例Bean被销毁前执行
    public perDestroy(){
         System.out.println("perDestroy");
    }
    @Autowired   
    public void setUserDao(@Qualifier("userDao") UserDao userDao) {   
     this.userDao = userDao;   
    }  

    public String SayHello(String word){
        return functionService.sayHello(word);
    }
}

配置注解

Configuration配置注解

@Configuration可替换xml配置文件进行配置。被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被AnnotationConfigApplicationContext或AnnotationConfigWebApplicationContext类进行扫描,并用于构建bean定义,初始化Spring容器。可与@PropertySource一起使用。

注解 解析 用法
@Configuration 配置类注解,可以与@Beae、@PropertySource一起使用,进行配置 在类、接口、枚举上
@SpringBootConfiguration 组合注解,@Configuration配置、@EnableAutoConfiguration启用自动配置
@ComponentScan默认扫描@SpringBootApplication所在类的同级目录以及它的子目录
类上
@AutoConfigureAfter 在指定的自动配置类之后再配置 类上

扫描注解

@ComponentScan注解,被@Configuration注解标注的类上面,涉及了@filter过滤器注解

注解 解析 用法
@ComponentScan 定义扫描的路径,默认就会加载标识了@Controller,@Service,@Repository,@Component注解的类到spring容器中
excludeFilters 指定扫描的时候需要排除的组件,includeFilters 指定扫描的时候只包含的组件
类上
@ComponentScans 包含着@ComponentScan数组 类上
@filter 声明要用作包含过滤器或排除过滤器的类型过滤器 可注解在@ComponentScan中

资源、值等注入注解

可以将配置文件、配置文件中的属性、以及系统属性等注入所需的字段中,或者bean中

注解 解析 用法
@Value 值注入,可以注入普通字符,系统属性,表达式运算结果,其他Bean的属性
文件内容,网址请求内容,配置文件属性值等等
字段上
方法上
参数上
@Bean 声明当前方法的返回值为一个Bean,而且返回的Bean对应的类中可以定义init()方法和destroy()方法
然后在@Bean(initMethod=”init”,destroyMethod=”destroy”)定义,在构造之后执行init,在销毁之前执行destroy
方法上
注解上
@PropertySource 指定配置文件位置,与@configuration类一起使用 类上
接口上
@ImportResource 加载xml配置文件 类上
接口上
@ConfigurationProperties 将properties属性与一个Bean及其属性相关联 类上
接口上
@Import 用来导入配置类的 类上
接口上

条件注解

Conditional根据满足某一特定条件创建特定的Bean,基于@Conditional元注解可延伸很多条件注解。在spring boot的源码中很多配置类的实例化都使用到了条件注解,例如数据源类DataSource的实例化

注解 解析 用法
@ConditionalOnBean Spring容器中是否存在对应的实例,可以通过实例的类型、类名、注解、昵称去容器中查找
可以配置从当前容器中查找或者父容器中查找或者两者一起查找。这些属性都是数组,通过”与”的关系进行查找
方法上
@ConditionalOnClass 类加载器中是否存在对应的类,逻辑跟@ConditionalOnBean类似 类上
接口上
方法上
@ConditionalOnExpression 判断SpEL 表达式是否成立 类上
接口上
方法上
@ConditionalOnJava 指定Java版本是否符合要求 类上
接口上
方法上
@ConditionalOnMissingBean Spring容器中是否缺少对应的实例,逻辑跟@ConditionalOnBean类似 类上
接口上
方法上
@ConditionalOnMissingClass Spring容器中是否缺少对应的实例,逻辑跟@ConditionalOnBean类似 类上
接口上
方法上
@ConditionalOnNotWebApplication 应用程序是否是非Web程序,没有提供属性,只是一个标识 类上
接口上
方法上
@ConditionalOnProperty 是否存在指定的资源文件。只有一个属性resources,是个String数组。
会从类加载器中去查询对应的资源文件是否存在
类上
接口上
方法上
@Profile 指定某个bean属于哪一个profile:spring.profiles.active和spring.profiles.default(默认) 类上
接口上
方法上

代码使用注解例子

@Configuration
//@SpringBootConfiguration
@ComponentScan(value="com.cn",ComponentDefaultFilters=true,
  includeFilters={
    @Filter(type=FilterType.ANNOTATION,classes={Controller.class}),
    @Filter(type=FilterType.CUSTOM,classes={MyTypeFilter.class})
})
@ImportResource("classpath:condition.xml")//导入xml配置
@Import(ConditionConfig.class)//导入ConditionConfig Class,并会实例化到容器中以及ConditionConfig中的配置也一起注入
public class Config {
     @Value("I Love You!") //注入普通字符
    private String normal;
    @Value("#{systemProperties['os.name']}") //注入操作系统属性
    private String osName;

    @Value("#{ T(java.lang.Math).random() * 100.0 }") //注入表达式运算结果
    private double randomNumber;

    @Value("#{demoService.another}") //注入其他Bean的属性
    private String fromAnother;

    @Value("classpath:org/light4j/sping4/usually/el/test.txt") //注入文件内容
    private Resource testFile;

    @Value("http://www.baidu.com") //注入网址内容
    private Resource testUrl;

    @Value("${book.name}") //注入属性文件
    private String bookName;
    @Bean//加载bean
    @Conditional(WindowsCondition.class) // 通过@Conditional注解,符合Windows条件则true
    @ConditionalOnResource(resources="classpath:windows.ini")//在类路径下是否存在windows.ini文件,存在为true,最后进行注解与操作,为true实例化Bean
    public ListService windowsListService(){
        return new WindowsListService();
    }

    @Bean
    @ConditionalOnClass(LinuxCondition.class) // 通过@ConditionalOnClass注解,符合Linux条件则true
    @ConditionalOnProperty(name = "synchronize", havingValue = "true"))//如果synchronize在配置文件中并且值为true
    public ListService linuxListService(){
        return new LinuxListService();
    }
    //加载配置文件中前缀为spring.datasource的属性
     @ConfigurationProperties(prefix = "spring.datasource")
      public DataSource jwcDataSource() {
         return DataSourceBuilder.create().build();
    }

    @Bean
    @ConditionalOnMissingClass({LinuxCondition.class,WindowsCondition.class})//当容器中缺失这两个Class时为true
    @Profile("dev")//在dev环境下为true  最后结果为注解和之与,true实例化该Bean
    public ListService macListService(){
        return new MacListService();
    }
}

Spring boot注解

web注解

做web开发时需要用到的注解,主要在controller层。用于请求参数,请求头数据,cookie数据获取,以及跨域支持。支持restful风格的web应用开发

注解 解析 用法
@EnableWebMvc 会开启一些默认配置,如一些ViewResolver或者MessageConverter等 类上
@RequestMapping 用来映射Web请求(访问路径和参数),处理类和方法的(即配置URL和方法之间的映射)
注解在方法上的@RequestMapping路径会继承注解在类上的路径
类上
方法上
@GetMapping 与@RequestMapping功能类似,但指定为get请求 方法上
@PostMapping 与@RequestMapping功能类似,但指定为post请求 方法上
@PutMapping 与@RequestMapping功能类似,但指定为put请求 方法上
@DeleteMapping 与@RequestMapping功能类似,但指定为delete请求 方法上
@ResponseBody 支持将返回值放在response体内 方法上
@RequestBody http请求需携带请求体 参数上
@PathVariable 用来接收路径参数,如/ccww/003,可接收003作为参数 参数上
@RequestParam 请求url后面需携带的参数 参数上
@CrossOrigin 用于支持跨域请求,此注解有两个参数
origins : 允许可访问的域列表
maxAge:准备响应前的缓存持续的最大时间(以秒为单位)。
类上
方法上
@RequestHeader 用于映射请求头数据到Controller方法的对应参数 参数上
@CookieValue 可以把Request header中关于cookie的值绑定到方法的参数上。 参数上

RequestHeader注解可获取请求头中的数据,下面介绍一下请求头(header)数据主要有哪些:

Header 解释 示例
Accept 客户端能够接收的内容类型 Accept:text/html,image/*
[告诉服务器,浏览器可以接受文本,网页图片]
Accept-Charaset 浏览器可接受的字符编码集 Accept-Charaset:ISO-8859-1
[接受字符编码:iso-8859-1]
Accept-Encoding 浏览器支持的服务器返回的压缩编码类型 Accept-Encoding:gzip,compress
[可以接受 gzip,compress压缩后数据]
Accept-Language 浏览器可接受的语言 Accept-Language:zh-cn
[浏览器支持的语言]
Accept-Ranges 用于告知客户端服务器是否能处理范围请求,以指定获取服务器端某个部分的资源 Accept-Ranges:bytes
Authorization Http授权的授权证书 Authorization:Basic YWRtaW46YWRtaW4=
Cache-Control 指定请求和响应遵循的缓存机制 Cache-Control:no-cache
Connection 表示连接是否持久(HTTP1.1默认进行持久连接) Connection:close
Cookie HTTP请求发送时,会把保存在该请求域名下的所有cookie值一起发送给web服务器 Cookie:version=1;skin=new
Content-Length 请求内容长度 Content-Length:348
Content-Type 请求与实体对于的MIME信息 Content-Type:application/x-www-form-urlencoded
Date 请求发送的时间和日期 Date:Mon, 17 Mar 2015 05:34:54 GMT
Host 浏览器要找的主机 Host:localhost:8080
Referer 告诉服务器我来自哪里,常用于防止下载,盗链 Referer:www.baidu.com
User-Agent 告诉服务器我的浏览器内核 User-Agent:Nozilla/4.0(Com…)

注解使用示例:

@Controller //声明此类是一个控制器
@RequestMapping("/ccww") //映射此类的访问路径是/ccww
//origin="*"代表所有域名都可访问  使用@CrossOrigin注解版本要求jdk1.8+ ,Spring4.2+
//maxAge飞行前响应的缓存持续时间的最大年龄,简单来说就是Cookie的有效期 单位为秒
//若maxAge是负数,则代表为临时Cookie,不会被持久化,Cookie信息保存在浏览器内存中,浏览器关闭Cookie就消失
@CrossOrigin(origins = "http://test.com",maxAge = 3600)
//@RestController // 使用@RestController,声明是控制器,并且返回数据时不需要@ResponseBody
//@RequestMapping("/ccww")
public class DemoAnnoController {

    //此方法未标注路径,因此使用类级别的路径/anno;produces可定制返回的response的媒体类型和字符集,或返回值是json对象,则设置porduces="application/json;charset=UTF-8"
    @RequestMapping(produces = "text/plain;charset=UTF-8")  
    public @ResponseBody String index(HttpServletRequest request) { //可接受HttpServletRequest作为参数,当然也可以接受HttpServletResponse作为参数。此处的@ResponseBody用在返回值前
        return "url:" + request.getRequestURL() + " can access";
    }

    @RequestMapping(value = "/demoPathVar/{str}", produces = "text/plain;charset=UTF-8")// 
    public @ResponseBody String demoPathVar(@PathVariable String str, //接受路径参数,并在方法参数前结合@PathVariable使用,访问路径为/ccww/demoPathVar/xxx
            HttpServletRequest request) {
        return "url:" + request.getRequestURL() + " can access,str: " + str;
    }
    //常规的request参数获取,访问路径为/ccww/requestParam?id=1
    @RequestMapping(value = "/requestParam", produces = "text/plain;charset=UTF-8") 
    public @ResponseBody String passRequestParam(Long id,
            HttpServletRequest request) {

        return "url:" + request.getRequestURL() + " can access,id: " + id;
    }

    @RequestMapping(value = "/obj", produces = "application/json;charset=UTF-8")
    @ResponseBody // 可注解在方法上
    public String passObj(DemoObj obj, HttpServletRequest request) {

         return "url:" + request.getRequestURL() 
                    + " can access, obj id: " + obj.getId()+" obj name:" + obj.getName();

    }
    //映射不同的路径到相同的方法,访问路径为/anno/name1或/anno/name2
    @RequestMapping(value = { "/name1", "/name2" }, produces = "text/plain;charset=UTF-8")
    public @ResponseBody String remove(HttpServletRequest request) {

        return "url:" + request.getRequestURL() + " can access";
    }

     @RequestMapping(value = "/helloWorld") 
     //以“user”为名称添加到模型对象中供视图页面展示使用
    public String helloWorld(@ModelAttribute User user) { 
     return "helloWorld"; 
    } 

    // 通过RequestHeader获取请求头中的数据
    @RequestMapping("/boweifeng")  
    @ResponseBody
    public String queryUser(@RequestHeader("Accept-Encoding") String encoding, @RequestHeader("Keep-Alive") long keepAlive,@CookieValue("JSESSIONID") String cookie)  {  
    return "encoding:" + encoding + "cookie:"+cookie;
    }  
}

应用注解

注解 解析 用法
@SpringBootApplication Spring Boot核心注解,组合注解(@Configuration、@EnableAutoConfiguration、@ComponentScan)
主要是为了开启自动配置
启动类上
@EnableAutoConfiguration 让Spring Boot根据类路径中的jar包依赖为当前项目进行自动配置
开源组件如mybatis,redis都是通过此注解实现启动自动注入的
类上

JPA注解

下面是jpa和hibernate的常用注解

注解 解析 用法
@entity 修饰一个实体类,接受一个name属性作为该实体类名称,可省略默认为该类名 类上
@Table 指定持久化类所映射的表名,可接受以下属性 类上
@Column 指定表列名和实体类的的映射关系 字段上
@Id 必须的,定义映射到数据库表的主键属性 字段上
@Transient 表示该属性并非一个到数据库表字段的映射,ORM框架将忽略该属性 字段上
@OneToOne 一对一双向外键关联:主控方的配置同一对一单向外键关联。 字段上
@ManyToOne 多对一单向外键关联:多对一,多方设置EAGER。fetch有两种:EAGER和LAZY 字段上
@ManyToOne 多对一双向外键关联 。多方:多方持有一方的引用 字段上
@ManyToMany 多对多双向外键关联:双方都持有对方的集合对象,其中一方设置 字段上
@JoinColum 用于表示两个实体的关联关系,和OneToOne,ManyToOne等注解配合使用 字段上

使用详解,通过例子来理解一对多,多对一几个注解的使用

一对多(多对一)

客户(Customer)和订单(Order)为例,客户(Customer)类为一的一方,订单(Order)类为多的一方。分别创建Customer和Order两个java类,通过jpa注解来表示他们的关系

客户(Customer)类

// 客户 ---- 一的一方
@Entity
@Table(name="t_customer")
public class Customer {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Integer id; // 主键
    private String name; // 姓名

    // 描述客户可以有多个订单
    /*
     * targetEntity="...":相当于<one-to-many class="...">
     * mappedBy="...":相当于inverse=true,即放弃关联关系的维护,不然会生成一个中间表
     */
    @OneToMany(targetEntity=Order.class,mappedBy="c")
    private Set<Order> orders = new HashSet<Order>();

    public Set<Order> getOrders() {
        return orders;
    }
    public void setOrders(Set<Order> orders) {
        this.orders = orders;
    }
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }

}

订单(Order)类

// 订单 ---- 多的一方
@Entity
@Table(name="t_order")
public class Order {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Integer id;
    private Double money;
    private String receiverInfo; // 收货地址

    // 订单与客户关联
    @ManyToOne(targetEntity=Customer.class)
    @JoinColumn(name="c_customer_id") // 指定外键列
    private Customer c; // 描述订单属于某一个客户

    public Customer getC() {
        return c;
    }
    public void setC(Customer c) {
        this.c = c;
    }
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public Double getMoney() {
        return money;
    }
    public void setMoney(Double money) {
        this.money = money;
    }
    public String getReceiverInfo() {
        return receiverInfo;
    }
    public void setReceiverInfo(String receiverInfo) {
        this.receiverInfo = receiverInfo;
    }

}

多对多

以学生与老师为例,使用@ManyToMany注解来配置多对多,只需要在一端配置中间表,另一端使用mappedBy表示放置外键的维护权。

学生(Student )类

@Entity
@Table(name="t_student")
public class Student {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Integer id;

    private String name;

    @ManyToMany(targetEntity=Teacher.class)
    // @JoinTable:使用@JoinTable来描述中间表,并描述中间表中外键与Student、Teacher的映射关系
    // joinColumns:它是用来描述Student与中间表的映射关系
    // inverseJoinColumns:它是用来描述Teacher与中间表的映射关系
    @JoinTable(name="s_t", joinColumns={@JoinColumn(name="c_student_id",referencedColumnName="id")}, inverseJoinColumns={@JoinColumn(name="c_teacher_id")}) 
    private Set<Teacher> teachers = new HashSet<Teacher>();

    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Set<Teacher> getTeachers() {
        return teachers;
    }
    public void setTeachers(Set<Teacher> teachers) {
        this.teachers = teachers;
    }

}

老师(Teacher )类

@Entity
@Table(name="t_teacher")
public class Teacher {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Integer id;

    private String name;

    @ManyToMany(targetEntity=Student.class, mappedBy="teachers") // 代表由对方来维护外键
    private Set<Student> students = new HashSet<Student>();

    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Set<Student> getStudents() {
        return students;
    }
    public void setStudents(Set<Student> students) {
        this.students = students;
    }

}

Author: 顺坚
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint polocy. If reproduced, please indicate source 顺坚 !
评论
 Previous
从零搭建Gin的web项目 从零搭建Gin的web项目
Go语言(又称 Golang)是谷歌公司开发的强类型,编译型语言。Go 语言语法与 C相近,但功能上有:内存安全,GC(垃圾回收),结构形态及 CSP-style 并发计算。其实Go语言在2009就推出了,似乎不温不火。但是最近一两年在中国
2020-04-06
Next 
vue和react实现组织架构树 vue和react实现组织架构树
公司项目需求,要在页面中实现一个公司组织架构图,并实现每个节点可以通过点击事件增加子节点,删除子节点。当时首先想到的是用echart的树图实现,但是echart的树图的节点不能自定义样式,而且点击事件也不是那么方便,于是就放弃了。然后在gi
2020-04-01
  TOC