bean相关

bean是spring架构的一大支柱,它构建了spring的框架。

bean是什么

bean可以是xml中的字段,也可以是用户定义的类。在定义他们后,spring会自动的查找这些bean并把它们加入到spring的bean容器中。然后在我们需要的时候可以从容器中拿取bean对象。

大致过程为:

  1. 注册: 根据xml文档和注解(@Bean, @Component等)找到相应的对象,并将这些这些对象的定义信息保存起来(并没有实例化,定义信息包括一些xml中的初始值等)。
  2. 发布到springloc容器中,但是此时还是没有实例化
  3. 装配: 在这些资源都找到后,会根据@Autowired进行实例化加入到各个类中,类似于链接过程。

bean的生命周期为:

图片源自

spring的容器又叫ioc容器(控制反转), bean就是被这个容器实例化、管理、组装的对象。

  • 依赖注入: spring启动时会把所需的类实例化为对象,如果该对象有依赖,那么他会寻找依赖对象并且实例化放到该对象中,这便是依赖注入。
  • 控制反转: new操作现在基本交给spring去做了,而不是使用传统的构造函数传参方式,这实际上是将控制权交由程序管理,也就是控制反转。

bean实例化时间:

  1. 如果使用BeanFactory作为Spring Bean的工厂类,所有bean都是使用该bean时初始化
  2. 如果ApplicationContext作为Spring Bean的工厂类
    1. 如果bean的scope是signleton的,并且lazy-init=false,则启动时实例化
      1. 如果lazy-init=true,则第一次使用时实例化
      2. bean的scope是prototype的,则该Bean的实例化是在第一次使用该Bean的时候进行实例化

注解

  • @Autowired(required=true):

    他会在对象被实例化后调用,初始化一些成员变量.required=true时没有搜索到对象会报错,required=false不会报错但是不会初始化变量。

    @Service
    public class TextEditor {
    @Autowired
    private SpellChecker spellChecker;
    public TextEditor() {
    System.out.println("Inside TextEditor constructor." );
    }
    public SpellChecker getSpellChecker( ){
    return spellChecker;
    }
    public void spellCheck(){
    spellChecker.checkSpelling();
    }
    }

    在TextEditor时会自动根据容器中的内容初始化spellChecker.如果容器中没有注册这个类会抛出异常。

    只有在调用getBean()获得对象的情况下才会初始化Autowired注释的变量,如果使用new创建对象不会调用Autowired. getBean()其实会查询依赖,如果发现有Autowired会调用那对象的getBean()然后递归生成对象。

    它有四种搜索模式:

    @Autowired还可以用于setter函数,它会按照bytype的方式进行装配,例如

    package com.tutorialspoint;
    import org.springframework.beans.factory.annotation.Autowired;
    public class TextEditor {
    private SpellChecker spellChecker;
    @Autowired
    public void setSpellChecker( SpellChecker spellChecker ){
    this.spellChecker = spellChecker;
    }
    public SpellChecker getSpellChecker( ) {
    return spellChecker;
    }
    public void spellCheck() {
    spellChecker.checkSpelling();
    }
    }
  • @Component: 通用的注解,可以标记任意类为bean对象,下面的注解也都会标记为bean对象。
  • @Repository: 负责持久化管理(数据存取),他属于DAO层(Data access object 数据访问对象),它可以自动对一些数据库异常进行处理翻译成一些spring专有的数据库异常
  • @Service: 处理一些业务逻辑,需要用到DAO层
  • @Controller: 他用来处理业务请求,主要用于和前端交互。如果Controller类上有@RequestMapping,那么方法中的RequestMapping路径去要加上类名上的路径
  • @Configuration: 和@Component类似,只是名字更清晰些
  • @Bean(name= , initMethod= , destroyMethod= ): 它作用于一个方法之上,将方法返回的类加入Bean容器中,其中initMethod和destroyMethod是指定初始化和销毁方法

       //@Bean注解注册bean,同时可以指定初始化和销毁方法
    @Bean(name="testBean",initMethod="start",destroyMethod="cleanUp")
    @Scope("prototype")
    public TestBean testBean() {
    return new TestBean();
    }

bean对象作用域:

@Scope(name)用于声明变量的作用域,共有四种作用域等级:

  • signleton: 单例,默认都是单例
  • prototype: 每次请求都会返回一个新的实例
  • request: 每次HTTP请求会返回一个新的实例,并且只在当前request内有效
  • session: 每次HTTP请求会返回一个新的实例,并且只在当前session内有效

HTTP注解

  • @GetMapping(“/user”): 相当于@RequestMapping(value="/user", method=RequestMethod.GET).它是在在这个路径下有一个GET请求时会调用该函数,返回值给请求者。

    @GetMapping("/users")
    public ResponseEntity<List<User>> getAllUsers() {
    return userRepository.findAll();
    }
  • @PostMapping(“/user”): 推送给服务器一个新的资源,路径为/user
  • @PutMapping(path): 请求更新某一个路径下的资源,例如:

    @PutMapping("/users/{userId}")
    public ResponseEntity<User> updateUser(@PathVariable(value = "userId") Long userId, @Valid @RequestBody UserUpdateRequest userUpdateRequest) {
    ......
    }
  • @DeleteMapping(path): 删除某个位置的内容

前后端传值

  • @PathVariable获得路径参数,@RequestParam获得查询参数

    例如:

    @GetMapping("/klasses/{klassId}/teachers")
    public List<Teacher> getKlassRelatedTeachers(
    @PathVariable("klassId") Long klassId,
    @RequestParam(value = "type", required = false) String type ) {
    ...
    }
    请求的url为/klasses/123456/teachers?type=web

    其中123456就是路径参数,而type=web就是查询参数
  • RequestBody: 用于获得body部分的Content-type为Application/json格式的数据,他会将json数据转化为java对象。只可以有一个RequestBody,但是可以有多个RequestParam(RequestParam就是请求json数据中的某一项).如果使用了RequestParam并且前端没有提供这个数据那么会报错。
    @PostMapping("/sign-up")
    public ResponseEntity signUp(@RequestBody @Valid UserRegisterRequest userRegisterRequest) {
    userService.save(userRegisterRequest);
    return ResponseEntity.ok().build();
    }

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class UserRegisterRequest {
    @NotBlank
    private String userName;
    @NotBlank
    private String password;
    @FullName
    @NotBlank
    private String fullName;
    }
    我们请求的数据为: {"userName":"coder","fullName":"shuangkou","password":"123456"}
  • @JsonAlias: 给变量起别名,例如:
    @JsonAlias(value = {"name", "name1"}
    private String tag_name;
    //它可以被识别为tag_name name name1