spring中存储和获取bean对象

文章目录

  • [1. 存储bean对象](#1. 存储bean对象)
    • [1.1 使用配置文件存储bean对象](#1.1 使用配置文件存储bean对象)
    • [1.2 使用五大类注解存储bean对象](#1.2 使用五大类注解存储bean对象)
      • [1.2.1 类注解](#1.2.1 类注解)
      • [1.2.2 五大类注解的作用](#1.2.2 五大类注解的作用)
      • [1.2.3 方法注解](#1.2.3 方法注解)
  • 2.获取bean对象
    • [2.1 属性注入](#2.1 属性注入)
    • [2.2 构造器注入](#2.2 构造器注入)
    • [2.3 getter注入](#2.3 getter注入)
    • [2.4 注入对象的时候有`spring`中有多个`bean`对象怎么办](#2.4 注入对象的时候有spring中有多个bean对象怎么办)
      • [2.4.1 将类中属性的名字,改成和要注入的`bean`对象的名字一样](#2.4.1 将类中属性的名字,改成和要注入的bean对象的名字一样)
      • [2.4.2 在 `@Autowired`注解下面加`@Qualifier`注解](#2.4.2 在 @Autowired注解下面加@Qualifier注解)
      • [2.4.3 抛弃`@Autowired`注解, 使用`@Resource`注解](#2.4.3 抛弃@Autowired注解, 使用@Resource注解)
    • [2. 5 @Autowired和@Resource注解的区别](#2. 5 @Autowired和@Resource注解的区别)

1. 存储bean对象

存储 Bean 分为以下 2 步:

  1. 存储 Bean 之前,先得有 Bean 才⾏,因此先要创建⼀个 Bean, 说白了也就是写一个类。
  2. 告诉spring,把这个类的对象存起来。

1.1 使用配置文件存储bean对象

  1. 编写User类, 有sayHi方法。
java 复制代码
public class User {
    public void sayHi() {
        System.out.println("你好");
    }
}
  1. 告诉spring,把这个类的对象存起来。
    在配置文件中可以通过<bean>标签来告诉spring把对象存起来。
xml 复制代码
<bean id="user1" class="demo.User"></bean>
  • id : 是用来标识一个对象的,就像我们的身份证一样。
    也称为bean对象的name(名字), 后面通过这个名字就能找到这个对象。
  • class:是带包的类名, 让spring知道我们要存的是哪一个类的对象。

完整的xml文件如下:

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:content="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
    <bean id="user1" class="demo.User"></bean>
</beans>

注意:配置文件其他的标签不用管,直接复制粘贴,需要关注的是<bean>标签。


怎么知道Spring把对象存起来了呢?我们查找一下这个bean对象的name(名字) 就行了。

使用BeanFactory或者ClassPathXmlApplicationContext就能查找bean对象了。

BeanFactory的代码如下:

java 复制代码
public class Test {
    public static void main(String[] args) {
        //创建BeanFactory的实现类的对象
        BeanFactory beanFactory =
                new XmlBeanFactory(new ClassPathResource("spring-config.xml"));
                
        //根据名字查找bean对象
        User user1 = (User)beanFactory.getBean("user1");
        
        //调用sayHi()方法
        user1.sayHi();
    }
}

结果:

如何创建BeanFactory对象:

  • BeanFactory是一个接口,XmlBeanFactory是其中的一个实现类,因为我们用xml文件来告诉spring存储bean对象,所以用XmlBeanFactory这个类。
  • XmlBeanFactory 其中的一个构造器的参数类型是:Resource
    Resource也是一个接口, 所以还需要创建Resource接口的实现类。

使用ClassPathXmlApplicationContext上下文对象,查找bean对象。

java 复制代码
public class Test {
    public static void main(String[] args) {
        test2();
    }

    public static void test2() {
        //创建上下文对象
        ClassPathXmlApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");

        //查找bean对象,第二个参数传了User的类型,得到bean对象后就无需转型了
        User user1 = context.getBean("user1", User.class);
        user1.sayHi();
    }
}

结果:

1.2 使用五大类注解存储bean对象

xml的形式来存储对象会比较麻烦,如果需要存很多个对象,就需要在xml配置文件中写多个<bean>标签。

这样子会很麻烦。所以spring提供了更加简便的方式来存储bean对象, 那就是使用注解。

下面介绍使用注解存储bean对象。

使用注解的方式,也要配置xml文件,不过只需要配置一个标签:<content:component-scan>

配置文件如下:

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:content="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
    <content:component-scan base-package="demo"></content:component-scan>
</beans>

说明:
<content:component-scan>这个标签用来配置包扫描路径, base-package="demo"配置的就是具体的包。

作用就是告诉spring在哪个包下扫描带有注解的类。spring扫描到带有注解的类就会为这个类创建对象。

xml 复制代码
<content:component-scan base-package="demo"></content:component-scan>

想要将对象存储在 Spring 中,有两种注解类型可以实现:

  1. 类注解:
    @Controller(控制器)、@Service(服务)、
    @Repository(仓库)、@Component(组件)、@Configuration(配置)。
  2. ⽅法注解:
    @Bean

1.2.1 类注解

  1. 使用@Controller类注解

在下面的代码中创建了ControllerTest类,有sayHello方法,类的上面有@Controller注解

有了这个@Controller注解,spring就能扫描到这个类,然后spring就会创建对象了。

java 复制代码
@Controller
public class ControllerTest {
    public void sayHello() {
        System.out.println("hello, 正在测试@Controller注解");
    }
}

测试类:

java 复制代码
public class Test {
    public static void main(String[] args) {
        test3();
    }

   public static void test3() {
        //创建上下文对象
        ClassPathXmlApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");

        //获取bean对象, 如果没有在注解上加参数,默认用类名的首字母小写获取bean对象
        ControllerTest controllerTest = context.getBean("controllerTest", ControllerTest.class);
        controllerTest.sayHello();
    }

结果:

注意:

如果在注解上没有指定bean对象的名字,将类名的首字母小写后作为bean对象的名字获取bean对象。
ControllerTest类名小写后是controllerTest,所以用controllerTest可以获取到bean对象。

也可以在注解上传参,指定bean对象的名字。

根据名字获取bean对象

  1. 使用@Service注解
    @Service注解跟@Controller的用法几乎一模一样。
java 复制代码
@Service
public class ServiceTest {
    public void sayHello() {
        System.out.println("hello, 正在测试@Service注解");
    }
}
java 复制代码
public class Test {
    public static void main(String[] args) {
        test4();
    }
    
    public static void test4() {
        //创建上下文对象
        ClassPathXmlApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");

        //获取bean对象, 如果没有在注解上加参数,默认用类名的首字母小写获取bean对象
        ServiceTest serviceTest = context.getBean("serviceTest", ServiceTest.class);
        serviceTest.sayHello();
    }
}


@Repository, @Component, @Configuarion注解用法跟上面的代码差不多,就不再演示了。

1.2.2 五大类注解的作用

因为后端程序是分层的,这五个类注解,分别就代表不同的层。
@Controller代表了业务逻辑层。
@Service代表了服务层。
@Repository代表了数据层。
@Configuration是配置层。

这些类注解功能是一样的,都是告诉spring存储bean对象。

但是当我们看到一个类上带了@Controller注解的时候,我们就清楚了,这个类处于 哪一层的,是干什么的。

这样做这样可以大大提高程序的可阅读性。

1.2.3 方法注解

@Bean方法注解用来将方法返回的对象存到spring中。

ControllerTest类中,写一个getObj方法,这个方法返回的ArrayList对象会存到spring

java 复制代码
@Controller("con")
public class ControllerTest {
    public void sayHello() {
        System.out.println("hello, 正在测试@Controller注解");
    }

    @Bean(name = "list")
    public ArrayList<Integer> getObj() {
        ArrayList<Integer> list = new ArrayList<>();
        list.add(1);
        return list;
    }
}

测试列:

java 复制代码
public class Test {
    public static void main(String[] args) {
        test5();
    }
    
   public static void test5() {
        //创建上下文对象
        ClassPathXmlApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");
        //根据name获取bean对象
        ArrayList<Integer> list = context.getBean("list", ArrayList.class);
        System.out.println(list.get(0));
    }
}

输出:

2.获取bean对象

获取 bean 对象也叫做对象装配,是把对象取出来放到某个类中,也可以叫对象注⼊。

对象注⼊的实现⽅法以下 3 种:

  1. 属性注⼊
  2. 构造⽅法注⼊
  3. Setter 注⼊

使用@Autowired或者@Resource注解实现spring中的bean对象注入。

这里用@Autowired注解进行演示。

2.1 属性注入

UserService

java 复制代码
@Service
public class UserService {
    public void sayHi() {
        System.out.println("Hi");
    }
}

UserController

获取spring中的对象使用@Autowired注解,将UserService类的bean对象注入进来

java 复制代码
@Controller
public class UserController {
    @Autowired
    private UserService userService;

    public void sayHi() {
        userService.sayHi();
    }
}

测试类:

java 复制代码
public class Test {
    public static void main(String[] args) {
        test6();
    }
    
	public static void test6() {
        //创建上下文对象
        ClassPathXmlApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");
        //获取bean对象
        UserController userController = context.getBean("userController", UserController.class);
        userController.sayHi();
    }
}

输出了HiUserSevice类的bean对象成功被注入了。

2.2 构造器注入

@Autowired注解放在构造器的上面,加一个形参,就可以实现构造器注入了。

java 复制代码
@Controller
public class UserController {
    private UserService userService;

    @Autowired
    public UserController(UserService userService) {
        this.userService = userService;
    }
    public void sayHi() {
        userService.sayHi();
    }
}

2.3 getter注入

getter注入也一样,将@Autowired注解放在getter方法上即可。

java 复制代码
@Controller
public class UserController {
    private UserService userService;

    public void sayHi() {
        userService.sayHi();
    }

    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }
}

2.4 注入对象的时候有spring中有多个bean对象怎么办

当注入对象的时候,spring中有多个对象的时候,就要告诉spring获取的是哪个bean对象。

但是@Autowired注解不能传入bean对象的名字,所以要用其他的方式来解决这个问题。

这时候有三种做法:

  1. 将类中属性的名字,改成和要注入的bean对象的名字一样
  2. @Autowired注解下面加@Qualifier注解
  3. 抛弃@Autowired注解, 使用@Resource注解

下面演示这三种不同处理方法:

2.4.1 将类中属性的名字,改成和要注入的bean对象的名字一样

Student类, 有idnameage属性, set方法和toString方法。

java 复制代码
public class Student {
    private int id;
    private String name;
    private int age;
    
    public void setId(int id) {
        this.id = id;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

StudentService类, 使用了方法注解@Bean将两个Student类的对象存到spring中。

java 复制代码
@Service
public class StudentService {
    @Bean("stu1")
    public Student getStu1() {
        Student student = new Student();
        student.setId(1);
        student.setName("张三");
        student.setAge(22);
        return student;
    }

    @Bean("stu2")
    public Student getStu2() {
        Student student = new Student();
        student.setId(2);
        student.setName("李四");
        student.setAge(23);
        return student;
    }
}

StudentController类中,有属性stu1showStuInfo方法, 使用@Autowired将对象注入到属性上。

java 复制代码
@Controller("stucon")
public class StudentController {
    @Autowired
    private Student stu1;

    public void showStuInfo() {
        System.out.println(stu1.toString());
    }
}

stu1属性名和bean对象的名字一样。

测试类:

java 复制代码
public class Test {
    public static void main(String[] args) {
        test7();
    }
    
	public static void test7() {
        //创建上下文对象
        ClassPathXmlApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");
        
        StudentController studentController = context.getBean("stucon", StudentController.class);
        studentController.showStuInfo();
    }
}

输入出:

2.4.2 在 @Autowired注解下面加@Qualifier注解

@Qualifier注解的源码,使用注解的时候,可以传递value的值

@Qualifier注解的中加上bean对象的名字,spring就知道要注入哪一个bean对象了。

StudentController类如下。

java 复制代码
@Controller("stucon")
public class StudentController {
    @Autowired
    @Qualifier("stu1")
    private Student stu;

    public void showStuInfo() {
        System.out.println(stu.toString());
    }
}

2.4.3 抛弃@Autowired注解, 使用@Resource注解

@Resource注解的部分源码。

在注解上传递一个参数即可,name = "stu1"就表示要注入名为stu1bean对象

java 复制代码
@Controller("stucon")
public class StudentController {
    @Resource(name = "stu1")
    private Student stu;

    public void showStuInfo() {
        System.out.println(stu.toString());
    }
}

2. 5 @Autowired和@Resource注解的区别

  • 出身不同。@Autowired来自于spring,而@ResourceJDK自带的。
  • 传参不同。@Resource相比@Autowired,可以传递的参数更多。
  • @Autowired注解可以用于属性注入,构造方法注入,setter注入。
    @Resource注解只能用于属性注入和setter注入, 不同用于构造方法注入。
    因为@Autowried注解可以修饰属性,构造器,和方法,@Resource不能修饰构造器,但可以修饰属性和方法。

@Autowried注解部分源码

@Resource注解部分源码

相关推荐
程序媛小果1 分钟前
基于java+SpringBoot+Vue的宠物咖啡馆平台设计与实现
java·vue.js·spring boot
追风林6 分钟前
mac m1 docker本地部署canal 监听mysql的binglog日志
java·docker·mac
芒果披萨21 分钟前
El表达式和JSTL
java·el
duration~1 小时前
Maven随笔
java·maven
zmgst1 小时前
canal1.1.7使用canal-adapter进行mysql同步数据
java·数据库·mysql
跃ZHD1 小时前
前后端分离,Jackson,Long精度丢失
java
blammmp2 小时前
Java:数据结构-枚举
java·开发语言·数据结构
暗黑起源喵2 小时前
设计模式-工厂设计模式
java·开发语言·设计模式
WaaTong2 小时前
Java反射
java·开发语言·反射
九圣残炎3 小时前
【从零开始的LeetCode-算法】1456. 定长子串中元音的最大数目
java·算法·leetcode