Spring~用注解读取bean(属性注入、构造方法注入、set注入)


通过注解从spring中储存和获取bean对象是非常简单的一种方法,前面我们已经介绍了如何将 bean存入 spring容器中,这里我们将了解如何通过注解将 beanspring容器中再读取出来。

读取bean对象也叫对象装配、对象注入、依赖注入,就是将获取出的对象放到某个类中,让这个类进行使用。

对象注入
如果类A需要使用类B的实例,可以直接在类A中创建一个类B的实例,也可以将类B的实例对象从Spring容器中拿出来,像打针一样“注入”类A中,由Spring动态的管理和使用,这就是“注入”。

注解@Autowired.

通过使用注解@Autowired来进行对象的注入,这个注解是Spring容器配置的一个注解,与其同属容器配置的注解还有:@Required,@Primary, @Qualifier 等等.这个注解根据字面意思理解是autowired,自动装配。即将bean对象和需要这个bean的类装配到一起。

用法如下:

属性注入

 //属性注入
    @Autowired
    private UserService userService;

举例:我们将Service类的实例注入到Controller类中进行使用。

创建一个UserService类:

package com.Service;

import com.User.User;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

@Service
public class UserService {
    
    

    public User findById(int id){
    
    
        User user=new User();
        if(id==1){
    
    
            user.setName("张三");
            user.setAge(18);
            user.setId(1);
        }else if(id==2){
    
    
            user.setName("李四");
            user.setAge(18);
            user.setId(2);
        }
        return user;
    }
}

创建UserController类:

package com.Controller;

import com.User.User;
import com.Service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;

@Controller
public class UserController {
    
    

    //属性注入
    @Autowired
    private UserService userService;

    public User findById(Integer id){
    
    
        if(id==null){
    
    
            return  new User();
        }
        return userService.findById(id);
    }
}

创建测试类:

import com.Controller.UserController;
import com.User.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
    
    
    public static void main(String[] args) {
    
    
        ApplicationContext context=new ClassPathXmlApplicationContext("a.xml");
      UserController userController=(UserController) context.getBean("userController",UserController.class);
       User user= userController.findById(2);
        System.out.println(user);
    }
}

输出:

User{
    
    name='李四', age=18, Id=2}

Setter注入

public class UserController {
    
    

    //设置一个字段
    private UserService userService;

     //为这个字段生成一个set方法,然后加上注解
    @Autowired  
    public void setUserService(UserService userService) {
    
    
        this.userService = userService;
    }
  
    //调用bean对象的方法进行使用
    public User findById(Integer id){
    
    
        return userService.findById(id);
    }
}

构造方法注入

public class UserController3 {
    
    
    //先生成一个字段
    private UserService userService;
    
    //然后生成构造方法,前面加上注解
    @Autowired
    public UserController3(UserService userService) {
    
    
        this.userService = userService;
    }
}

注意:

  • 使用注解获取bean的前提是这个类能被spring扫描到,即类前需要加注解@Controller、@Component、@Service等等几个类似注解中的一个。
  • 这三种注入的第一步操作都是先生成一个要注入对象的字段,第一种直接在字段上注解,第二种为这个字段生成一个set方法然后注解,第三种为这个字段生成一个构造方法,然后在方法上注解。使用方式类似,功能相同,第一种更简便。
  • 通过构造方法注入时,如果当前类只有一个构造方法,那么@Autowired注解可以被省略,如果有多个构造方法,就不能省略。
    在这里插入图片描述
    在这里插入图片描述

三种注入的优缺点

属性/字段注入:

  • 优点:简洁、方便
  • 缺点:只能用于IOC容器,非IOC容器会出现空指针异常,而且默认是非final的,容易出现循环依赖问题

构造方法注入:

  • 优点:通用性强,不受IOC容器的限制,能保证注入的类不为空,在代码中能一眼就能看出当前类需要哪些类才能工作。
  • 缺点:多个注入会显得代码非常繁琐,且多个注入不符合单一设计的思想,一旦使用了构造方法注入,那么默认的构造方法就无法使用

Set方法注入:

  • 优点:对于循环依赖问题免疫
  • 缺点:不能将对象设置为final

注解@Resource.

@Resource中有两个重要的属性:name和type.
spring将name属性解析为bean的名字 ,type属性解析为bean的类型。

进行对象注入也可以通过@Resource实现,使用方法与@Autowired类似:

1.属性注入

public class UserController {
    
    
    //添加注解在字段上
    @Resource
    private UserService userService;
    
    public User findUser(Integer id){
    
    
        return userService.findById(id);
    }
}

2.构造方法注入

public class UserController2 {
    
    
   
    private UserService userService;
    
    //先创建字段,然后添加注释在构造方法上
    @Resource
    public void setUserService(UserService userService) {
    
    
        this.userService = userService;
    }

    public User findUser(Integer id){
    
    
        return userService.findById(id);
    }
}

注意!!

  • @Resource没有构造方法注入
    在这里插入图片描述

@Resource与@Autowired区别

  • 来源不同,@Autowired来自于Spring框架,而@Resource来自于JDK
  • 作用范围不同,@Autowired可以进行属性注入,Setter注入,构造器注入;而@Resource只能进行属性注入和Setter注入
  • 功能不同,@Resource可以配合更多的属性进行使用,而@Autowired支持的属性比较少,比如@Resource可以配合name属性使用,完成对象的别名注入。
  • 注入方式不同,@Autowired是按照byType注入,即按照bean的类型注入,而@Resource是按照byName进行注入的。

注入对象名称问题

当我们把一个对象注入到一个类中的时候,@Autowired和@Resource会尝试着去获取这个对象,首先得先找到这个对象。

在查找这个对象的时候,按照两个标准进行查找,一个是对象名称,另一个是对象类型。
在这里插入图片描述

  • 先根据名称进行获取,如果获取不到,就会根据类型进行获取,如果也获取不到,就会抛出异常。
  • 如果名称不匹配,但是类型匹配,且类型匹配相同的对象有多个,也会抛出异常,无法确定是哪一个。

所有在查找时,我们有多种解决方法:
可以通过@Resource(name=“”)来指定bean:
在这里插入图片描述
也可以使用@Qualifier限定符,限定一个bean来进行查找。

   @Resource
    @Qualifier("user1")
    private UserService userService;

猜你喜欢

转载自blog.csdn.net/Merciful_Lion/article/details/124064384