一篇让你熟练掌握Spring注解(全网最全)

553 阅读11分钟

1.启动相关

@SpringBootApplication

在这里插入图片描述 在这里插入图片描述

包含了 ==@ComponentScan==、==@Configuration== 和 ==@EnableAutoConfiguration== 注解。

@ComponentScan

其中 @ComponentScan 让 spring Boot 扫描被@Component (@Service,@Controller)注解的 bean到 Configuration 类并把它加入到程序上下文。

@Configuration(下面有详细版本)

@Configuration 等同于 spring 的 XML 配置文件;允许在 Spring 上下文中注册额外的 bean 或导入其他配置类。

@EnableAutoConfiguration

@EnableAutoConfiguration 启用 SpringBoot 的自动配置机制。

2.Spring Bean 相关

@Autowired

自动导入对象到类中,被注入进的类同样要被 Spring 容器管理比如:Service 类注入到 Controller 类中。

@Slf4j
@Service
public class ProjectServiceImpl  implements ProjectService {
}

@Autowired
private ProjectService projectService;
@PostMapping ("/application")
public ResultVo findProject(@RequestBody @Validated FindProjectRequest request) {
    return projectService.findProject(request);
}

@Resource

public class Hello {

    @Resource(name = "HappyClient")
    private HappyClient happyClient;
    
    @Resource(type = HappyPlayAno .class)
    private HappyPlayAno happyPlayAno;
}

@Resource的作用相当于@Autowired,均可标注在字段或属性的setter方法上。

这个地方注意一下 这里的区别

  • a:提供方 @Autowired是Spring的注解,@Resource是javax.annotation注解,而是来自于JSR-250,J2EE提供,需要JDK1.6及以上。
  • b :注入方式 @Autowired只按照Type 注入;@Resource默认按Name自动注入,也提供按照Type 注入;
  • c:属性 @Autowired注解可用于为类的属性、构造器、方法进行注值。默认情况下,其依赖的对象必须存在(bean可用),如果需要改变这种默认方式,可以设置其required属性为false。 还有一个比较重要的点就是,@Autowired注解默认按照类型装配,如果容器中包含多个同一类型的Bean,那么启动容器时会报找不到指定类型bean的异常,解决办法是结合**@Qualifier**注解进行限定,指定注入的bean名称。 @Resource有两个中重要的属性:name和type。name属性指定byName,如果没有指定name属性,当注解标注在字段上,即默认取字段的名称作为bean名称寻找依赖对象,当注解标注在属性的setter方法上,即默认取属性名作为bean名称寻找依赖对象。 需要注意的是,@Resource如果没有指定name属性,并且按照默认的名称仍然找不到依赖对象时, @Resource注解会回退到按类型装配。但一旦指定了name属性,就只能按名称装配了。
  • d:@Resource注解的使用性更为灵活,可指定名称,也可以指定类型 ;@Autowired注解进行装配容易抛出异常,特别是装配的bean类型有多个的时候,而解决的办法是需要在增加@Qualifier进行限定。

@RestController

@RestController 注解是 ==@Controller==和 ==@ResponseBody== 的合集, 表示这是个控制器 bean, 并且是将函数的返回值直接填入 HTTP 响应体中, 是 REST 风格的控制器

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController {
    String value() default "";
}

@Repositor

标注一个DAO组件类。

@Service

标注一个业务逻辑组件类。

@Controller

@Controller:用于定义控制器类,在 spring 项目中由控制器负责将用户发来的 URL 请求转发到对应的服务接口(service 层)。一般这个注解在类中,通常方法需要配合注解 @RequestMapping使用。

@ResponseBody

@Controller
@RequestMapping("/test")
@Slf4j
public class TestController {

    @RequestMapping("/hello.json")
    @ResponseBody
    public JsonData hello() {
        log.info("hello");
        return JsonData.success("hello, permission");
    }

作用:将方法的返回值,==以特定的格式写入到response的body区域,进而将数据返回给客户端==。

当方法上面没有写ResponseBody,底层会将方法的返回值封装为ModelAndView对象。在使用此注解之后不会再走试图处理器,而是直接将数据写入到输入流中,他的效果等同于通过response对象输出指定格式的数据。

  • 如果返回值是字符串,那么直接将字符串写到客户端;
  • 如果是一个对象,会将对象转化为json串,然后写到客户端。

如果返回对象,按utf-8编码。如果返回String,默认按iso8859-1编码,页面可能出现乱码。因此在注解中我们可以手动修改编码格式,例如

@RequestMapping(value="/cat/query",produces="text/html;charset=utf-8"),

前面是请求的路径,后面是编码格式。

原理

控制层方法的返回值是如何转化为json格式的字符串的?其实是通过HttpMessageConverter中的方法实现的,它本是一个接口,在其实现类完成转换。

  • 如果是bean对象,会调用对象的getXXX()方法获取属性值并且以键值对的形式进行封装,进而转化为json串。
  • 如果是map集合,采用get(key)方式获取value值,然后进行封装。

@Component、@Repository、@Service、@Controller实质上属于同一类注解,用法相同,功能相同,区别在于标识组件的类型。

@Component可以代替@Repository、@Service、@Controller,因为这三个注解是被@Component标注的。 如下代码

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Controller {
    String value() default "";
}

此处引用大神的文章blog.csdn.net/jiahao1186/…

@Scope

声明 Spring Bean 的作用域,使用方法:

@Bean
@Scope("singleton")
public Person personSingleton() {
    return new Person();
}

四种常见的 Spring Bean 的作用域:

  • singleton : 唯一 bean 实例,Spring 中的 bean 默认都是单例的。
  • prototype : 每次请求都会创建一个新的 bean 实例。
  • request : 每一次 HTTP 请求都会产生一个新的 bean,该 bean 仅在当前 HTTP request 内有效。
  • session : 每一次 HTTP 请求都会产生一个新的 bean,该 bean 仅在当前 HTTP session 内有效。

@Configuration

一般用来声明配置类,可以使用 @Component注解替代,不过使用Configuration注解声明配置类更加语义化。

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

@Configuration
public class AppConfig {
    @Bean
    public MyService myService() {
        return new MyServiceImpl();
    }
}

这和 Spring 的 XML 文件中的非常类似

<beans> 
	<bean id="myService" class="com.acme.services.MyServiceImpl"/> 
</beans>

注意:@Configuration注解的配置类有如下要求:

  • 1.@Configuration不可以是final类型;
  • 2.@Configuration不可以是匿名类;
  • 3.嵌套的configuration必须是静态类。

@Configuration的使用 可以看这篇大神的文章www.cnblogs.com/duanxz/p/74…

@Component

@Configuration
public static class Config {

    @Bean
    public SimpleBean simpleBean() {
        return new SimpleBean();
    }

    @Bean
    public SimpleBeanConsumer simpleBeanConsumer() {
        return new SimpleBeanConsumer(simpleBean());
    }
}
@Component
public static class Config {

    @Bean
    public SimpleBean simpleBean() {
        return new SimpleBean();
    }

    @Bean
    public SimpleBeanConsumer simpleBeanConsumer() {
        return new SimpleBeanConsumer(simpleBean());
    }
}
  • 第一个代码正常工作,正如预期的那样,SimpleBeanConsumer将会得到一个单例SimpleBean的链接。
  • 第二个配置是完全错误的,因为Spring会创建一个SimpleBean的单例bean,但是SimpleBeanConsumer将获得另一个SimpleBean实例(也就是相当于直接调用new SimpleBean() ,这个bean是不归Spring管理的),既new SimpleBean() 实例是Spring上下文控件之外的。

原理解析 使用@ configuration,所有标记为@ bean的方法将被包装成一个CGLIB包装器,它的工作方式就好像是这个方法的第一个调用,那么原始方法的主体将被执行,最终的对象将在spring上下文中注册。所有进一步的调用只返回从上下文检索的bean

在上面的第二个代码块中,新的SimpleBeanConsumer(simpleBean())只调用一个纯java方法。为了纠正第二个代码块,我们可以这样做

@Component
public static class Config {
    @Autowired
    SimpleBean simpleBean;

    @Bean
    public SimpleBean simpleBean() {
        return new SimpleBean();
    }

    @Bean
    public SimpleBeanConsumer simpleBeanConsumer() {
        return new SimpleBeanConsumer(simpleBean);
    }
}

大神链接:blog.csdn.net/u010648555/…

3.处理常见的 HTTP 请求类型

@RequestMapping

@RequestMapping:@RequestMapping(“/path”)表示该控制器处理所有 “/path” 的 UR L 请求。RequestMapping 是一个用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。该注解有六个属性:

params

指定 request 中必须包含某些参数值是,才让该方法处理。

headers

指定 request 中必须包含某些指定的 header 值,才能让该方法处理请求。

@RequestMapping (value= "testHeaders" , headers={ "host=localhost" , "Accept" })
    public String testHeaders() {
       return "headers" ;
    } 

headers 属性的用法和功能与params 属性相似。在上面的代码中当请求/testHeaders.do 的时候只有当请求头包含Accept 信息,且请求的host 为localhost 的时候才能正确的访问到testHeaders 方法。

  • value: 指定请求的实际地址,指定的地址可以是 URI Template 模式
@RequestMapping(value = "bkpic.page", method = RequestMethod.POST)
@ResponseBody
public JsonData upload(@RequestParam(value = "picture", required = false) MultipartFile picture, HttpServletRequest request) {
}

consumes

  • 指定处理请求的提交内容类型(Content-Type),如 application/json,text/html;

produces

  • 指定返回的内容类型,仅当 request 请求头中的 (Accept) 类型中包含该指定类型才返回

@RequestParam

@RequestMapping("/changeUsers.json")
@ResponseBody
public JsonData changeUsers(@RequestParam("roleId") int roleId, @RequestParam(value = "userIds", required = false, defaultValue = "") String userIds) {
    List<Integer> userIdList = StringUtil.splitToListInt(userIds);
    sysRoleUserService.changeRoleUsers(roleId, userIdList);
    return JsonData.success();
}

@PathVariable: 路径变量。如

@RequestMapping(method = RequestMethod.GET)
public List<AccessDTO> searchAccess(@RequestParam(required = false) String service,
                                    @RequestParam(required = false) String application,
                                    @PathVariable String env) {
                                    }

method

指定请求的 method 类型, GET、POST、PUT、DELETE 等

  • GET :请求从服务器获取特定资源。举个例子:GET /users(获取所有学生)
@GetMapping("users") 等价于@RequestMapping(value="/users",method=RequestMethod.GET)
@GetMapping("/users")
public ResponseEntity<List<User>> getAllUsers() {
 return userRepository.findAll();
}
  • POST :在服务器上创建一个新的资源。举个例子:POST /users(创建学生)
@PostMapping("users") 等价于@RequestMapping(value="/users",method=RequestMethod.POST)
@PostMapping("/users")public ResponseEntity<User> createUser(@Valid @RequestBody UserCreateRequest userCreateRequest) {
 return userRespository.save(user);
}
  • PUT :更新服务器上的资源(客户端提供更新后的整个资源)。举个例子:PUT /users/12(更新编号为 12 的学生)
@PutMapping("/users/{userId}") 等价于@RequestMapping(value="/users/{userId}",method=RequestMethod.PUT)
@PutMapping("/users/{userId}")public ResponseEntity<User> updateUser(@PathVariable(value = "userId") Long userId,
  @Valid @RequestBody UserUpdateRequest userUpdateRequest) {
  ......
}
  • DELETE :从服务器删除特定的资源。举个例子:DELETE /users/12(删除编号为 12 的学生)
@DeleteMapping("/users/{userId}")等价于@RequestMapping(value="/users/{userId}",method=RequestMethod.DELETE)
@DeleteMapping("/users/{userId}")public ResponseEntity deleteUser(@PathVariable(value = "userId") Long userId){
  ......
}
  • PATCH :更新服务器上的资源(客户端提供更改的属性,可以看做作是部分更新),使用的比较少,这里就不举例子了。
一般实际项目中,我们都是 PUT 不够用了之后才用 PATCH 请求去更新数据。
@PatchMapping("/profile")
  public ResponseEntity updateStudent(@RequestBody StudentUpdateRequest studentUpdateRequest) {
        studentRepository.updateDetail(studentUpdateRequest);
        return ResponseEntity.ok().build();
    }

4.读取配置信息

数据源application.yml

wuhan2020: 2020年武汉加油!中国加油!
my-profile:
  name:哥
  email:@163.com
library:
  location: 湖北武汉加油中国加油
  books:
    - name: 1
      description: 11
    - name: 2
      description: 22
    - name: 3
      description: 33

@value(常用)

使用 @Value("${property}") 读取比较简单的配置信息:

@Value("${wuhan2020}")
String wuhan2020;

@ConfigurationProperties

@Component
@ConfigurationProperties(prefix = "library")
class LibraryProperties {
    @NotEmpty
    private String location;
    private List<Book> books;

    @Setter
    @Getter
    @ToString
    static class Book {
        String name;
        String description;
    }
  省略getter/setter
  ......
}

通过@ConfigurationProperties读取配置信息并与 bean 绑定。

@PropertySource

@PropertySource读取指定 properties 文件

@Component
@PropertySource("classpath:website.properties")

class WebSite {
    @Value("${url}")
    private String url;

  省略getter/setter
  ......
}

这里借鉴了大神的文章segmentfault.com/a/119000002…

5.参数校验

JSR(Java Specification Requests) 是一套 JavaBean 参数校验的标准,它定义了很多常用的校验注解,我们可以直接将这些注解加在我们 JavaBean 的属性上面,这样就可以在需要校验的时候进行校验了,非常方便!

一些常用的字段验证的注解

@NotEmpty 被注释的字符串的不能为 null 也不能为空
@NotBlank 被注释的字符串非 null,并且必须包含一个非空白字符
@Null 被注释的元素必须为 null
@NotNull 被注释的元素必须不为 null
@AssertTrue 被注释的元素必须为 true
@AssertFalse 被注释的元素必须为 false
@Pattern(regex=,flag=)被注释的元素必须符合指定的正则表达式
@Email 被注释的元素必须是 Email 格式。
@Min(value)被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@Max(value)被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@DecimalMin(value)被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@DecimalMax(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@Size(max=, min=)被注释的元素的大小必须在指定的范围内
@Digits (integer, fraction)被注释的元素必须是一个数字,其值必须在可接受的范围内
@Past被注释的元素必须是一个过去的日期
@Future 被注释的元素必须是一个将来的日期
......

示例

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {

    @NotNull(message = "classId 不能为空")
    private String classId;

    @Size(max = 33)
    @NotNull(message = "name 不能为空")
    private String name;

    @Pattern(regexp = "((^Man$|^Woman$|^UGM$))", message = "sex 值不在可选范围")
    @NotNull(message = "sex 不能为空")
    private String sex;

    @Email(message = "email 格式不正确")
    @NotNull(message = "email 不能为空")
    private String email;

}

我们在需要验证的参数上加上了@Valid注解,如果验证失败,它将抛出

MethodArgumentNotValidException。
@RestController
@RequestMapping("/api")
public class PersonController {

    @PostMapping("/person")
    public ResponseEntity<Person> getPerson(@RequestBody @Valid Person person) {
        return ResponseEntity.ok().body(person);
    }
}

一定一定不要忘记在类上加上 Validated 注解了,这个参数可以告诉 Spring 去校验方法参数。

@RestController
@RequestMapping("/api")
@Validated
public class PersonController {

    @GetMapping("/person/{id}")
    public ResponseEntity<Integer> getPersonByID(@Valid @PathVariable("id") @Max(value = 5,message = "超过 id 的范围了") Integer id) {
        return ResponseEntity.ok().body(id);
    }
}

6.@Transactional

在要开启事务的方法上使用@Transactional注解即可!

@Transactional(rollbackFor = Exception.class)
public void save() {
  ......
}

我们知道 Exception 分为运行时异常 RuntimeException 和非运行时异常。 在@Transactional注解中如果不配置rollbackFor属性,==那么事务只会在遇到RuntimeException的时候才会回滚,加上rollbackFor=Exception.class,可以让事务在遇到非运行时异常时也回滚==。

@Transactional 注解一般用在可以作用在类或者方法上。

  • 作用于类:当把@Transactional 注解放在类上时,表示所有该类的public 方法都配置相同的事务属性信息。
  • 作用于方法:当类配置了@Transactional,方法也配置了@Transactional,方法的事务会覆盖类的事务配置信息。

示例

@Service
public class CompanyServiceImpl implements CompanyService {
  @Autowired
  private CompanyDAO companyDAO;

  @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = Exception.class)
  public int deleteByName(String name) {

    int result = companyDAO.deleteByName(name);
    return result;
  }
  ...
}

未完待续。。。。。。。 欢迎留言。。。

@Inherited blog.csdn.net/ab411919134… @ConditionalOnClass blog.csdn.net/lbh199466/a…

@Target blog.csdn.net/qq_30347133…

@Retention blog.csdn.net/b_just/arti…

@SuppressWarnings blog.csdn.net/u012994320/… @Aspect blog.csdn.net/zhengchao19…

blog.csdn.net/fz137688842… @Slf4j

@EnableWebMvc

@Primary

@EnableSwagger2

@EnableAsync

@Authority(needLogin = true)

@ResponseStatus(HttpStatus.CREATED)

@PmsKey(code = "application", title = "应用列表")

@SerializedName("biz_id")

@ControllerAdvice(annotations = ResponseBody.class)

@ExceptionHandler(value = Exception.class)

@Order(0)

@Around("execution(* org.apache.dubbo.admin.controller..(..))")

@SPI("zookeeper")

@EnableTransactionManagement

@MapperScan(basePackages = "org.apache.dubbo.admin.dao.mapper")

@ComponentScan(basePackageClasses = {org.apache.dubbo.admin.DubboAdminApplication.class, PermitContextManager.class}) 在这里插入图片描述

本公众号分享自己从程序员小白到经历春招秋招斩获10几个offer的面试笔试经验,其中包括【Java】、【操作系统】、【计算机网络】、【设计模式】、【数据结构与算法】、【大厂面经】、【数据库】期待你加入!!!

1.计算机网络----三次握手四次挥手 2.梦想成真-----项目自我介绍 3.你们要的设计模式来了 4.一字一句教你面试“个人简介” 5.接近30场面试分享