java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Spring注解存储和读取 Bean对象

Spring 使用注解存储和读取 Bean对象操作方法

作者:求知.

在 Spring 中,要想更加简单的实现对 Bean 对象的储存和使用,其核心就是使用 注解 ,本文主要就是演示如何使用注解实现对 Bean 对象的存取操作,感兴趣的朋友跟随小编一起看看吧

前言

前面的文章详细的介绍了 Spring 对象的创建,以及对 Bean 对象的存取操作,但是通过配置文件注册 Bean 对象以及使用 ApplicationContext BeanFactory 的方式获取 Bean 对象的操作就显得格外的复杂。因此,本文主要就是详细介绍了一种更加简单的方式来实现对 Bean 对象更加简单的储存和读取操作。

在 Spring 中,要想更加简单的实现对 Bean 对象的储存和使用,其核心就是使用 注解 ,本文主要就是演示如何使用注解实现对 Bean 对象的存取操作。

一、使用注解储存 Bean 对象

在之前储存 Bean 对象的时候,还需在 spring-congig 文件中添加一行 <bean> 内容才行,而且,每需要新增一个 Bean 对象到 Spring 容器中就需要新增一行,这样的操作就显得非常麻烦了。

而现在只需要使用一个 注解 就能代替这一行 <bean> 内容,此时就变得非常方便。想要通过注解的方式将对象储存到 Spring 容器中,主要有两种注解类型可以实现:

1.使用类注解(五大类注解):

2.使用方法注解:

但在此之前还需要配置一下 扫描路径

1.1 配置扫描路径

spring-config.xml 文件中添加如下一行记录:

其含义是,指定一个 base package ,即所有需要添加到 Spring 容器中的 Bean 对象都在 base package 所指定包或者其子包下。这里我知道的包是 com.spring.demo ,那么就意味着,如果不是此包下的 Bean 对象,即使加上了注解,也不会被添加到 Spring 容器中。

1.2 类注解储存 Bean 对象

1.2.1 @Controller(控制器存储)

使用 @Controller 注解储存 Bean 对象:

@Controller
public class StudentController1 {
    public void sayHi(){
        System.out.println("do studentController1 sayHi().");
    }
}

使用 ApplicationContext 的方式获取 Bean 对象:

public static void main(String[] args) {
    ApplicationContext context =
            new ClassPathXmlApplicationContext("spring-config.xml");
    StudentController1 studentController1 =
            context.getBean("studentController1", StudentController1.class);
    studentController1.sayHi();
}

关于 Bean 对象的命名规则可见后文。

1.2.2 @Service(服务储存)

使用 @Service 注解储存 Bean 对象:

@Service
public class StudentController2 {
    public void sayHi(){
        System.out.println("do studentController2 sayHi().");
    }
}

获取 Bean 对象:

StudentController2 studentController2 =
        context.getBean("studentController2", StudentController2.class);

1.2.3 @Repository(仓库存储)

使用 @Repository 注解储存 Bean 对象:

@Repository
public class StudentController3 {
    public void sayHi(){
        System.out.println("do studentController3 sayHi().");
    }
}

获取 Bean 对象:

StudentController3 studentController3 =
        context.getBean("studentController3", StudentController3.class);

1.2.4 @Component(组件储存)

使用 @Component 注解储存 Bean 对象:

@Component
public class StudentController4 {
    public void sayHi(){
        System.out.println("do studentController4 sayHi().");
    }
}

获取 Bean 对象:

StudentController4 studentController4 =
        context.getBean("studentController4", StudentController4.class);

1.2.5 @Configuration(配置储存)

使用 @Configuration 注解储存 Bean 对象:

@Configuration
public class StudentController5 {
    public void sayHi(){
        System.out.println("do studentController5 sayHi().");
    }
}

获取 Bean 对象:

StudentController5 studentController5 =
        context.getBean("studentController5", StudentController5.class);

1.2.6 Bean 命名规则

通过上述代码可以发现,在创建 Bean 对象的时候,都是使用的标准 “大驼峰” 的命名方式,而读取的时候 Bean 的名称则是其类名称的首字母小写,即小驼峰。

但是,此时创建一个 SController 类,并使用注解将其添加到 Spring 容器中,那么此时它的 Bean 对象的名称是什么呢?根据上面代码的规律,难道还是 SController 吗?

SController sController = context.getBean("sController", SController.class);

当运行程序的时候,发现报错了:

其意思是不存在名称为 sController 这样 Bean 对象。此时如果将其改成 SController ,会是正确的吗?

此时发现便能正常运行了。

关于 Bean 的名称生成的源码:

查找 beanname,选择 AnnotationBeanNameGenerator

继续查找

继续查找

4. 找到了源码,即 Introspector 类下的 decapitalize 方法

该方法通过检查字符串的首字母是否为大写,并且第二个字符也是大写的情况下,直接返回原字符串,不做小写化处理。这样做是为了避免一些特殊情况下,例如缩写或首字母缩写词,不被误处理。

1.3 五大类注解的作用

在Spring框架中,五大类常用的注解,分别是:@Component、@Controller、@Service、@Repository和@Configuration。

1.3.1 为什么有这么多的注解

通过上面代码的演示,发现这些注解的功能都是一样的,既然都是一样的为什么还需要有这么多不同的注解呢?

Spring 之所以提供这么多的注解,是为了更好的组织和管理应用程序的组件和依赖关系因为每个注解都有自己特定的用途,让开发人员在应用程序中能够更方便地标识和区分不同类型的类。同时也提现了程序的工程分层:

以上三个层次实现了程序的工程分层,同时也是 Java EE 标准分层的最核心分层。

1.3.2 类注解之间的关系

查看 @Controller / @Service / @Repository / @Configuration 等注解的源码发现:

它们都是 @Component 子类注解,这意味着,被标注为 @Controller / @Service / @Repository / @Configuration 的类也被视为 @Component

1.4 方法注解储存 Bean 对象

首先创建一个 User 实体类:

package com.spring.demo.entity;
/**
 * 普通的用户实体类
 */
public class User {
    private Integer uid;
    private String username;
    private String password;
    private Integer age;
    public Integer getUid() {
        return uid;
    }
    public void setUid(Integer uid) {
        this.uid = uid;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "User{" +
                "uid=" + uid +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", age=" + age +
                '}';
    }
}

1.4.1 @Bean 注解的使用

创建一个组件类 UserBeans ,并使用方法注解 @Bean 将 User 类添加到 Spring 容器中:

@Controller
public class UserBeans {
    @Bean
    public User getUser(){
        User user = new User();
        user.setUid(1);
        user.setUsername("王五");
        user.setPassword("123456");
        user.setAge(18);
        return user;
    }
}

注意,使用方法注解 @Bean 的时候需要搭配五大类注解才能生效。

获取 Bean 对象:

public static void main(String[] args) {
    ApplicationContext context =
            new ClassPathXmlApplicationContext("spring-config.xml");
    User user = context.getBean("getUser", User.class);
    System.out.println(user);
}

注意,当使用方法注解 @Bean 的时候,Bean 对象的默认名称就是其 添加到 Spring 容器中的方法名。

1.4.2 Bean 对象重命名

如果直接使用方法名作为 Bean 对象的名称,例如 getUser 就显得非常的不合理,因此往往需要对 Bean 进行改名操作。但查看 @Bean 源码的时候可以发现,其中的 name value 属性是一个数组,那么就意味着可以一个 Bean 对象取多个名称。

例如:

此时,可通过这两个名称,获取该 Bean 对象,发现它们是同一个 Bean:

另外需要注意的是,如果对 Bean 进行了重命名,则原来默认的方法名就失效了。

二、使用注解获取 Bean 对象

2.1 Bean 对象通过注解获取的方法

获取 Bean 对象也叫做 对象装配 ,即把对象取出来放到某个类当中,同时也叫做 对象注入

对象注入的实现方式有以下三种:

2.2 三种注入方法的使用

下⾯按照实际开发中的模式,将 Service 类注入到 Controller 类中,然后通过 main 方法获取 Controller 中的 Bean 对象。首先创建一个 UserService 类和 UserController 类:

@Service
public class UserService {
    public void sayHi(){
        System.out.println("hi, userService.");
    }
}

2.2.1 属性注入

@Controller
public class UserController {
    // 1. 属性注入
    @Autowired
    private UserService userService;
    public void sayHi(){
        System.out.println("do userController sayHi().");
        userService.sayHi();
    }
}

2.2.2 Setter 注入

@Controller
public class UserController {
    // 2. setter 注入
    private UserService userService;
    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }
    public void sayHi(){
        System.out.println("do userController sayHi().");
        userService.sayHi();
    }
}

2.2.3 构造方法注入

@Controller
public class UserController {
    // 3. 构造方法注入
    private UserService userService;
    // @Autowired
    public UserController(UserService userService) {
        this.userService = userService;
    }
    public void sayHi(){
        System.out.println("do userController sayHi().");
        userService.sayHi();
    }
}

注意,如果此时只有一个构造方法,则 @Autowired 可以省略。

2.3 三种注入方法的优缺点

属性注入

Setter注入:

构造方法注入:

2.4 @Resource 注入

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

属性注入:

public class UserController {
    // 1. 属性注入
    @Resource
    private UserService userService;
    public void sayHi(){
        System.out.println("do userController sayHi().");
        userService.sayHi();
    }
}

Setter注入:

@Controller
public class UserController {
    // 2. setter 注入
    private UserService userService;
    @Resource
    public void setUserService(UserService userService) {
        this.userService = userService;
    }
    public void sayHi(){
        System.out.println("do userController sayHi().");
        userService.sayHi();
    }
}

遗憾的是, @Resource 不支持构造方法注入:

2.5 @Autowired 和 @ Resource的区别

2.6 注入同一类型的多个 @Bean 报错问题

当存在多个类型相同的 Bean 对象,并且需要通过注解将其注入到其他 Bean 对象中时,如果没有明确指定注入哪个 Bean,就会导致报错。

2.6.1 报错问题

例如,通过 Component 中的 UserBeans 将 User 注入到 Controller 中的 UserController 中。

首先,在 UserBeans 使用 @Bean 添加两个 User 对象到 Spring 容器中:

@Controller
public class UserBeans {
    @Bean(name = {"user1", "u1"})
    public User getUser1(){
        User user = new User();
        user.setUid(1);
        user.setUsername("张三");
        user.setPassword("123456");
        user.setAge(18);
        return user;
    }
    @Bean(name = "user2")
    public User getUser2(){
        User user = new User();
        user.setUid(1);
        user.setUsername("李四");
        user.setPassword("123456");
        user.setAge(18);
        return user;
    }
}

UserController 中分别使用 @Autowired @Resource 注入获取 Bean 对象:

@Autowired

此时,由于存在两个相同类型的 Bean 对象,但是其名称不同,所以使用 @Autowired 注解不知道获取哪个对象。

@Resource

使用 @Resource 注解同样无法判断获取哪一个对象。

  • 关于 @Autowired @Resource 查找 Bean 对象的顺序:

  • @Autowired 首先按照类型查找,然后再按照名称查找;
  • @Resource 首先按照名称查找,然后再按照类型查找。

2.6.2 使用 @Resource(name=“XXX”) 解决

@Controller
public class UserController {
    @Resource(name = "user1")
    private User user;
    public void sayHi(){
        System.out.println("do userController sayHi().");
    }
}

2.6.3 @Autowired 配合使用 @Qualifier 解决

@Controller
public class UserController {
    @Autowired
    @Qualifier(value = "user1")
    private User user;
    public void sayHi() {
        System.out.println("do userController sayHi().");
    }
}

到此这篇关于Spring 使用注解存储和读取 Bean对象的文章就介绍到这了,更多相关Spring注解存储和读取 Bean对象内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文