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注解部分源码

相关推荐
wellc27 分钟前
SpringBoot集成Flowable
java·spring boot·后端
Hui Baby1 小时前
springAi+MCP三种
java
hsjcjh1 小时前
【MySQL】C# 连接MySQL
java
敖正炀1 小时前
LinkedBlockingDeque详解
java
wangyadong3171 小时前
datagrip 链接mysql 报错
java
untE EADO1 小时前
Tomcat的server.xml配置详解
xml·java·tomcat
ictI CABL1 小时前
Tomcat 乱码问题彻底解决
java·tomcat
敖正炀2 小时前
DelayQueue 详解
java
敖正炀2 小时前
PriorityBlockingQueue 详解
java
shark22222222 小时前
Spring 的三种注入方式?
java·数据库·spring