SpringBoot 注解

74 阅读8分钟

@Api

Swagger 中的一个注解,用于指定一个类的方法或者字段的 API 相关信息。在 Spring Boot 项目中,通常用于 Swagger 文档的生成。

@Api修饰controller类,标识这个类是swagger的资源 
@ApiOperation修饰controller的方法,表示一个http请求的操作
@ApiParam修饰方法的参数,用于添加参数说明与是否必填等元数据

例子:

@Api(tags={"用户操作接口"})
@RestController
public class UserController {
     @ApiOperation(value="获取用户信息",tags={"获取用户信息copy"},notes="注意问题点")
     @GetMapping("/getUserInfo")
     public User getUserInfo(@ApiParam(name="id",value="用户id",required=true) Long id,@ApiParam(name="username",value="用户名") String username) {
     // userService可忽略,是业务逻辑
      User user = userService.getUserInfo();
 
      return user;
  }
}

@Autowired/@Resource

依赖注入。

1.来源不同

Autowired 和 Resource 注解来自不同的“父类”,其中Autowired注解是 Spring 定义的注解,而Resource 注解是 Java 定义的注解,它来自于 JSR-250(Java 250 规范提案)。

2、注入规则不同

Autowired注解是spring的注解,此注解只根据type进行注入,不会去匹配name。但是如果只根据type无法辨别注入对象时,就需要配合使用@Qualifier注解或者@Primary注解使用。

Resource注解有两个重要的属性,分别是name和type,如果name属性有值,则使用byName的自动注入策略,将值作为需要注入bean的名字,如果type有值,则使用byType自动注入策略,将值作为需要注入bean的类型。如果既不指定name也不指定type属性,这时将通过反射机制使用byName自动注入策略。即@Resource注解默认按照名称进行匹配,名称可以通过name属性进行指定,如果没有指定name属性,当注解写在字段上时,默认取字段名,按照名称查找,当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。

3、依赖查找的顺序不同

Autowired注解先根据类型(byType)查找,如果存在多个(Bean)再根据名称(byName)进行查找;
Resource注解先根据名称(byName)查找,如果(根据名称)查找不到,再根据类型(byType)进行查找。

4、支持的参数不同

Autowired注解只支持设置 1 个参数,而Resource注解支持设置 7 个参数。

5、依赖注入的用法支持不同

Autowired注解支持属性注入、构造方法注入和 Setter 注入,而Resource注解只支持属性注入和 Setter 注入。

6、编译器 IDEA 的提示不同

当使用 IDEA 专业版在编写依赖注入的代码时,如果注入的是 Mapper 对象,那么使用Autowired注解编译器会提示报错信息。虽然 IDEA 会出现报错信息,但程序是可以正常执行的。 然后,我们再将依赖注入的注解更改为Resource注解就不会出现报错信息了

7、使用位置不同

两者都可以写在字段和setter方法上,如果写在字段上,那么就不需要在写setter方法。推荐使用Resource注解在字段上,这样不仅不需要写setter方法了,而且由于Resource注解属于J2EE,降低与spring的耦合。

共同点

  1. @Resource注解和@Autowired注解都可以用作bean的注入;
  2. 在接口只有一个实现类的时候,两个注解可以互相替换,效果相同。

@PathVariable

获取url中的数据,绑定路径中的占位符参数到方法参数变量中.

如果没有指定 required 属性,或者设置为 true(默认值),则该路径变量是必需的。如果路径中缺少这个变量或者变量不匹配,将会抛出异常。

// 假设 URL 模板为 "/users/{userId}",userId 是必需的
@RequestMapping(value = "/users/{userId}", method = RequestMethod.GET)
public String getUser(@PathVariable(name = "userId", required = true) String userId) {
    // 方法实现
}
 
// 如果 userId 不是必需的,可以这样设置
@RequestMapping({"/statusCount/{outletId}","/statusCount/"})
public String getUserOptional(@PathVariable(required = false) String outletId) {
    // 方法实现
}

设置成false,不带参数时,应该可以做到全局搜索

@Qualifier

区分具有相同类型的多个Bean,用于明确指定要注入的Bean的名称或限定符。通常为要注入的Bean添加

如:有一个UserService接口,但有两个实现类。就需要使用qualifier,不然不知道是哪个实现类,会报NoUniqueBeanDefinitionException异常

例子:

  • 在定义Bean的地方,使用@Qualifier注解为Bean添加一个限定符,这个限定符可以是任何字符串,用于区分同一类型的多个Bean。
@Bean
@Qualifier("database")
public DataSource dataSource() {
    // 返回一个数据库数据源的实现
    return new DatabaseDataSource();
}
  • 在需要进行注入Bean的地方,使用@Qualifier注解并指定相同的限定符值,具体来说,假设有两个名为"databaseDataSource"和"fileDataSource"的DataSource类型的Bean,并且它们都使用了@Qualifier注解并指定了不同的限定符值。
@Autowired
@Qualifier("database")
private DataSource dataSource;

@PreAuthorize

在方法执行前进行权限验证

这个是由spring security提供的。Spring Security提供了Spring EL表达式,允许我们在定义接口访问的方法上面添加注解,来控制访问权限

方法参数描述
hasPermiString验证用户是否具备某权限
lacksPermiString验证用户是否不具备某权限,与hasPermi逻辑相反
hasAnyPermiString验证用户是否具有以下任意一个权限
hasRoleString判断用户是否拥有某个权限
lacksRoleString验证用户是否不具备某个权限,与hasRole逻辑相反
hasAnyRolesString验证用户是否具有以下任意一个角色,多个逗号分隔

其中@ss代表的是PermissionService (opens new window)服务,对每个接口拦截并调用PermissionService的对应方法判断接口调用者的权限。

A. ss 是一个注册在 Spring容器中的BEAN,对应的类是cn.hadoopx.framework.web.service.PermissionService;

B. hasPermi 是PermissionService类中定义的方法;

C.当Spring EL 表达式返回TRUE,则权限校验通过;

1.数据示例

// 符合system:user:list权限要求
@PreAuthorize("@ss.hasPermi('system:user:list')")

// 不符合system:user:list权限要求
@PreAuthorize("@ss.lacksPermi('system:user:list')")

// 符合system:user:add或system:user:edit权限要求即可
@PreAuthorize("@ss.hasAnyPermi('system:user:add,system:user:edit')")

2.角色权限示例

// 符合system:user:list权限要求
@PreAuthorize("@ss.hasPermi('system:user:list')")

// 不符合system:user:list权限要求
@PreAuthorize("@ss.lacksPermi('system:user:list')")

// 符合system:user:add或system:user:edit权限要求即可
@PreAuthorize("@ss.hasAnyPermi('system:user:add,system:user:edit')")

@Async和@EnableAsync

解释

异步的优点:

  • 提高应用程序的响应能力
  • 提高系统的吞吐量
  • 节约资源:异步操作可以避免在请求处理期间占用过多的线程资源,减少服务器的负载。
  • 优化用户体验

需要注意的问题:

  • 事务问题:异步处理时,需要注意在事务没有结束时做异步操作,可能会导致读取不到甚至覆盖事务中新增或更新的数据内容。

在 Spring Boot 中,可以通过 @EnableAsync 注解来启动异步方法调用的支持,通过 @Async 注解来标识异步方法,

1.@EnableAsync 注解

@EnableAsync 是一个 Spring Boot 中用于启动异步方法调用的注解。使用 @EnableAsync 注解时,需要将其放置在一个配置类上,并且在配置类中通过 @Bean 方法创建一个线程池。

2.@Async 注解

@Async 注解是一个 Spring Boot 中用于标识异步方法的注解,通过在方法上添加 @Async 注解,可以让该方法在异步线程中执行。

  • 假如只配置了一个线程池,直接用 @Async 注解就会用自定义的线程池执行。
  • 假如配置了多个线程池,用 @Async("name") 来指定使用哪个线程池,如果没有指定,会用默认的 SimpleAsyncTaskExecutor 来处理。

@Data

‌@Data注解是‌Lombok库中的一个功能强大的注解,它自动为类生成一系列有用的方法,从而显著减少样板代码的编写工作。

依赖

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.4</version>
    <scope>provided</scope>
</dependency>

提供的方法:

image.png

  1. 其他相关注解

@Data : 注在类上,提供类的get、set、equals、hashCode、toString等方法

@AllArgsConstructor :注在类上,提供类的全参构造

@NoArgsConstructor :注在类上,提供类的无参构造

@Setter :注在属性上,提供 set 方法

@Getter :注在属性上,提供 get 方法

@EqualsAndHashCode :注在类上,提供对应的 equals 和 hashCode 方法

@Log4j/@Slf4j :注在类上,提供对应的 Logger 对象,变量名为 log

@ConfigurationProperties

作用

@ConfigurationProperties注解(将配置文件中的配置,以属性的形式自动注入到实体中)可以注入在application.properties配置文件中的属性,和@Bean 或者 @Component 等能生成spring bean 的注解结合起来使用;

原理

注入后该类在加载过程中会调用AbstractAutowireCapableBeanFactory中的applyBeanPostProcessorsBeforeInitialization接口进行一些前置处理。

@ConfigurationProperties 注解其对应的bean的后置处理器为ConfigurationPropertiesBindingPostProcessor,

它实现了Spring容器的postProcessBeforeInitialization方法,会在bean初始化之前被调用注解处理器会读取@ConfigurationProperties 注解的对象获取配置文件中的prefix,和注解对象的类成员变量然后递归将配置属性赋值给类成员变量。

和@value获取值进行比较

image.png

注意:

1、要特别说明的一个注属性 ignoreUnknownFields = false 这个超好用,自动检查配置文件中的属性是否存在,不存在则在启动时就报错。

2、必须在pom.xml文件中配置该注解,否则报错:

       <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>

3、@ConfigurationProperties注解支持属性文件和javabean的映射,而@Value支持spel表达式。如果是多个属性映射,而且常常被复用,推荐使用@ConfigurationProperties,如果只读取单个属性则使用@Value要方便许多。

4、在JavaBean类上或与@Bean注解使用时,必须在使用到的JavaBean类上面添加@Component,否则在容器无法获取,若只使用@ConfigurationProperties需要结合@EnableConfigurationProperties(PropertisInject.class)将其注册到spring容器中。