IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Spring中Bean对象的存储和获取 -> 正文阅读

[Java知识库]Spring中Bean对象的存储和获取

1. 更简单的将bean存储到spring中

1.0 前置工作,在配置文件中设置bean扫描的根路径

在这里插入图片描述

1.1 通过注解将bean存储到spring中

想要将对象存储在 Spring 中,有两种注解类型可以实现:
1.类注解:@Controller【控制器】、@Service【服务】、@Repository【仓库】、@Component【组件】、@Configuration【配置】。
2.方法注解:@Bean。
接下来我们分别来看。

1.1.1 @Controller【控制器】

在这里插入图片描述

package com.beans;
import org.springframework.stereotype.Controller;
@Controller//将当前对象存储到spring中
public class UserController {
    public void sayHi(String name){
        System.out.println("你好,"+name);
    }
}

使用之前读取对象的方式来读取上面的 UserController 对象:

import com.beans.UserController;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
    public static void main(String[] args) {
        // 1.获取 spring 上下文
        ApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");
        // 2.得到 bean
        UserController userController = context.getBean(UserController.class);
        // 3.使用 bean
        userController.sayHi("极致千叶");
    }
}

运行结果:
在这里插入图片描述

注意事项1:即使在spring配置文件中配置了bean的扫描路径,但是5大类注解是不能省略的。
注意事项2:即使加了5大类注解,但类没有放在spring配置的bean路径下,那么也是不能将类注入到spring中的。

关于类注解的bean的名称规则:

通常情况下‘是小驼峰(也就是将类名小写)就可以获取到bean对象

UserService userService=context.getBean("userService",UserService.class);
userService.sayHi("慕远笙歌");

如果第一个字母为大写,第二个字母为小写的情况下,那么bean的命名规则就是首字母小写
如果第一个和第二个字母都是大写的情况下,那么bean命名规则是原类名

1.1.2 @Service【服务】

package com.beans;

import org.springframework.stereotype.Service;
@Service//将当前对象存储到spring中
public class UserService {
        public void sayHi(String name) {
            System.out.println("你好," + name);
        }
}
import com.beans.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
    public static void main(String[] args) {
        // 1.获取 spring 上下文
        ApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");
        UserService userService=context.getBean("userService",UserService.class);
        userService.sayHi("慕远笙歌");
    }
}

1.1.3@Repository【仓库】

package com.beans;

import org.springframework.stereotype.Repository;

@Repository//将当前对象存储到spring中
public class UserRepository {
    public void sayHi(String name) {
        System.out.println("你好," + name);
    }
}

import com.beans.UserRepository;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
    public static void main(String[] args) {
        // 1.获取 spring 上下文
        ApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");
        UserRepository userRepository=context.getBean("userRepository", UserRepository.class);
        userRepository.sayHi("谋长节短");
    }
}

1.1.4@Component【组件】

package com.beans;

import org.springframework.stereotype.Component;

@Component//将当前对象存储到spring中
public class UserComponent {
    public void sayHi(String name) {
        System.out.println("你好," + name);
    }
}

import com.beans.UserComponent;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
    public static void main(String[] args) {
        // 1.获取 spring 上下文
        ApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");


        UserComponent userComponent=context.getBean("userComponent",UserComponent.class);
        userComponent.sayHi("百战百胜");
    }
}

1.1.5 @Configuration【配置】

package com.beans;

import org.springframework.context.annotation.Configuration;

@Configuration//将当前对象存储到spring中
public class UserConfiguration {
    public void sayHi(String name) {
        System.out.println("你好," + name);
    }
}

import com.beans.UserConfiguration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
    public static void main(String[] args) {
        // 1.获取 spring 上下文
        ApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");
        UserConfiguration userConfiguration=context.getBean("userConfiguration",UserConfiguration.class);
        userConfiguration.sayHi("难知如阴");
    }
}

1.2 为什么要这么多类注解?

  1. @Component【组件】是其他四个注解的父类;
  2. 在这里插入图片描述
    @Controller:表示的是业务逻辑层(控制器,和前端打交道【验证前端的有效性】);
    @Servie:服务层(组织数据调用相应的接口);
    @Repository:持久层(数据持久层【dao/repository】,和数据库直接打交道,执行具体的CRUD操作);
    @Configuration:配置层(存放所有的配置信息)。

1.3.方法注解:@Bean

类注解是添加到某个类上的,而方法注解是放到某个方法上的。

1.3.1 方法注解要配合类注解使用

在 Spring 框架的设计中,方法注解 @Bean 要配合类注解才能将对象正常的存储到 Spring 容器中,如下代码所示:

package com.beans;

import com.model.User;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Controller;

@Controller
public class UserBeans {

    @Bean//将当前方法返回的对象存储到spring中,默认bean名称为方法名
    public User user1(){
        User user=new User();
        user.setId(1);
        user.setName("极致千叶");
        user.setPassword("123");
        return user;
    }
}

1.3.2 重命名bean

可以通过设置 name 属性给 Bean 对象进行重命名操作

package com.beans;

import com.model.User;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Controller;

@Controller
public class UserBeans {
//给当前对象起一个别名
    @Bean(name="user2")//将当前方法返回的对象存储到spring中,默认bean名称为方法名
    public User user1(){
        User user=new User();
        user.setId(1);
        user.setName("极致千叶");
        user.setPassword("123");
        return user;
    }
}

这个重命名的 name 其实是一个数组,一个 bean 可以有多个名字:

package com.beans;

import com.model.User;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Controller;

@Controller
public class UserBeans {
//给当前对象起一个或多个别名
    @Bean(name={"user2","user"})//将当前方法返回的对象存储到spring中,默认bean名称为方法名
    public User user1(){
        User user=new User();
        user.setId(1);
        user.setName("极致千叶");
        user.setPassword("123");
        return user;
    }
}

并且 name={} 可以省略,如下代码所示:

package com.beans;

import com.model.User;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Controller;

@Controller
public class UserBeans {

    @Bean({"user2","user"})//将当前方法返回的对象存储到spring中,默认bean名称为方法名
    public User user1(){
        User user=new User();
        user.setId(1);
        user.setName("极致千叶");
        user.setPassword("123");
        return user;
    }
}

@Bean重命名后,使用方法名不能获取到Bean对象!!!如果没有对Bean进行重命名,那么可以使用方法名获取Bean对象

2.获取 Bean 对象(对象装配)

获取 bean 对象也叫做对象装配,是把对象取出来放到某个类中,有时候也叫对象注入
对象装配(对象注入)的实现方法以下 3 种:

  1. 属性注入
  2. 构造方法注入
  3. Setter 注入
    接下来,我们分别来看。
    下面我们按照实际开发中的模式,将 Service 类注入到 Controller 类中。

2.1 属性注入

属性注入是使用 @Autowired 实现的,将 Service 类注入到 Controller 类中。
Service 类的实现代码如下:

package com.beans;

import com.model.User;
import org.springframework.stereotype.Service;
@Service//将当前对象存储到spring中
public class UserService {
    /**
     * 根据id获取用户
     * @param id
     * @return
     */
    public User getUserById(int id){
            //伪代码
            User user=new User();
            user.setId(id);
            user.setName("刑天");
            user.setPassword("123");
            return user;
        }
}

Controller 类的实现代码如下:

package com.beans;

import com.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

@Controller//将当前对象存储到spring中
public class UserController {
    //1.属性注入
    @Autowired
    private UserService userService;

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

App方法:

import com.beans.*;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.beans.Introspector;

public class App {
    public static void main(String[] args) {
        // 1.获取 spring 上下文
        ApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");
        UserController userController=context.getBean(UserController.class);
        System.out.println(userController.getUserById(10));

    }
}

2.2 构造方法注入

构造方法注入是在类的构造方法中实现注入,如下代码所示:

package com.beans;

import com.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

@Controller//将当前对象存储到spring中
public class UserController2 {
    private UserService userService;
    //1.构造方法注入
    @Autowired//如果当前类只有一个构造方法,那么@Autowired可以省略
    public UserController2(UserService userService){
        this.userService=userService;
    }
    
    public void sayHi(String name){
        System.out.println("你好,"+name);
    }

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

如果当前类只有一个构造方法,那么@Autowired可以省略;但是如果当前方法中存在多个构造方法,那么@Autowired是不能省略的。

2.3 Setter 注入

Setter 注入和属性的 Setter 方法实现类似,只不过在设置 set 方法的时候需要加上 @Autowired 注解,如下代码所示:

package com.beans;

import com.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

@Controller//将当前对象存储到spring中
public class UserController3 {
    private UserService userService;
    //3.Setter 注入
    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    public void sayHi(String name){
        System.out.println("你好,"+name);
    }

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

2.4 三种注入优缺点分析

  1. 属性注入的优点是简洁,使用方便;缺点是不通用,只能用于 IoC 容器,如果是非 IoC 容器不可用,并且只有在使用的时候会出现空指针异常。
  2. 构造方法注入是 Spring 推荐的注入方式,它的缺点是可能存在多个参数来实现构造方法的初始化,会显得比较臃肿,但出现这种情况你应该考虑一下当前类是否符合程序的单一职责的设计模式了,它的优点是通用性,并且能保证再调用对象之前,此对象一定存在。
  3. Setter 方式是 Spring 前期版本推荐的注入方式,但通用性不如构造方法,所有 Spring 现版本已经推荐使用构造方法注入的方式来进行类注入了。

2.5 @Resource:另一种注入关键字

在进行类注入时,除了可以使用 @Autowired 关键字之外,我们还可以使用 @Resource 进行注入,如下代码所示:

package com.beans;

import com.model.User;
import org.springframework.stereotype.Controller;

import javax.annotation.Resource;

@Controller//将当前对象存储到spring中
public class UserController5 {
    @Resource
    private UserService userService;

   // @Resource
    public UserController5(UserService userService){
        this.userService=userService;
    }

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

2.6@Autowired 和 @Resource 的区别

出身不同:@Autowired 来自于 Spring,而 @Resource 来自于 JDK 的注解;

使用时设置的参数不同:相比于 @Autowired 来说,@Resource 支持更多的参数设置,例如 name设置,根据名称获取 Bean。

支持的注入类型不同:@Autowired 支持属性注入、构造方法注入 和Setter 注入,@Resource 支持属性注入和 Setter 注入,不支持构造方法注入。

2.7 同一类型多个 @Bean 报错

一个类型被注册到Spring多次时,程序运行就会出现异常。

package com.beans;

import com.model.User;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Controller;

@Controller
public class UserBeans {

//    @Bean("user2")//将当前方法返回的对象存储到spring中,默认bean名称为方法名
    @Bean(name="user1")
    public User user1(){
        User user=new User();
        user.setId(1);
        user.setName("极致千叶");
        user.setPassword("123");
        return user;
    }

    @Bean(name="user2")
    public User user2(){
        User user=new User();
        user.setId(2);
        user.setName("慕远笙歌");
        user.setPassword("456");
        return user;
    }
}

解决异常的办法:

  1. 使用正确的bean name。
  2. 设置bean name
  3. 使用@Autowired+@Qualifier
    ① 使用 @Resource(name=“XXX”)
package com.beans;

import com.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;

import javax.annotation.Resource;

@Controller
public class UserController6 {
    @Resource(name="user1")
    private User user;
    public void saiHi(){
        System.out.println(user);
    }
}

② 使用 @Qualifier(" ")

package com.beans;

import com.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;

import javax.annotation.Resource;

@Controller
public class UserController6 {
    @Autowired
    @Qualifier(value ="user2")
    private User user;

    public void saiHi(){
        System.out.println(user);
    }
}

3.总结

  1. 将对象存储在Spring中:
  • a.实用类注解:@Controller【控制器】、@Service【服务】、@Repository【仓库】、@Component【组件】、@Configuration【配置】,【它们之间的关系】
  • b.使用方法注解:@Bean【注意事项:必须配合类注解一起使用】
  1. Bean的命名规则:首字母和第二个字母都非大写,首字母小写来获取Bean,如果首字母和第二个字母都是大写,那么直接使用原Bean名来获取Bean。
  2. 从Spring中获取对象:
  • a.属性注入
  • b.Setter注入
  • c.构造函数注入(推荐)
  1. 注入的关键字有:
  • a.@Autowired
  • b.@Resource
  1. @Autowired和@Resource的区别:出身不同;使用时设置参数不同,@Resource支持更多的参数,比如name。
  2. 解决同一类型多个Bean的报错:
  • a.使用 @Resource(name=“XXX”)
  • b. 使用 @Qualifier(" ")
  • c.构造函数注入(推荐)
  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-07-17 16:07:52  更:2022-07-17 16:11:35 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/18 5:55:41-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码