Spring使用注解更简单的读取和存储对象的方法

 更新时间:2023年07月18日 10:14:06   作者:whisper-h  
这篇文章主要介绍了Spring使用注解更简单的读取和存储对象的方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧

在上一篇文章中实现了基本的Spring读取和存储对象。但在操作的过程中我们发现读取和存储对象并没有想象中的那么“简单”。

所以接下来我们要讲解更加简单的操作 Bean 对象的⽅法。其核心就是,使用注解

1.Spring的存储对象------存储Bean对象

之前我们存储 Bean 时,需要在 spring-config 中添加⼀⾏ bean 注册内容才⾏,如下图所示:

⽽现在我们只需要⼀个注解就可以替代之前要写⼀⾏配置的尴尬了。

类注解规则:1.类名前两位均为大写时,返回自身name

                  2.否则,首字母小写

1.前置工作,配置扫描路径

想要将对象成功的存储到 Spring 中,我们需要配置⼀下存储对象的扫描包路径,只有被配置的包下的所有类,添加了注解才能被正确的识别并保存到 Spring 中。

在spring-config.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="org.example"></content:component-scan>
</beans>

其中标红的一行为注册扫描的包,如下图所示:

注意:即使添加了注解,如果不是在配置的扫描包下的类对象,也是不能被存储到Spring中的。

2.添加注解存储Bean对象

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

1. 类注解:@Controller、@Service、@Repository、@Component、@Configuration。

2. ⽅法注解:@Bean。

1.@Controller(控制器存储)

使用@Controller存储Bean的代码如下所示:

@Controller
public class UserController {
    public void sayHi(){
        System.out.println("hi,userController~");
    }
}

在App中读取上面的UserController对象:

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

运行结果:

这里并没有在spring-config.xml中添加id,但是依旧能正确运行。是因为@Controller注解自动的起到了一个id的作用。作用与如下代码一致:

    <bean id="userController" class="org.example.UserController"></bean>

2.@service(服务存储)

使用@service存储Bean的代码如下所示:

@Service
public class UserService {
    public void doService(){
        System.out.println("doService");
    }
}

在App中读取上面的UserService对象:

public class App {
    public static void main(String[] args) {
        ApplicationContext context=new ClassPathXmlApplicationContext("spring-config.xml");
        UserService userService=(UserService) context.getBean("userService");
        userService.doService();
    }
}

3.@Repository(仓库存储)

使用@Repository存储Bean的代码如下所示:

@Repository
public class UserRepository {
    public void sayHi(){
        System.out.println("hi,repository");
    }
}

在App中读取上面的UserRepository对象:

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

4.@Component(组件存储)

使用@Component存储Bean的代码如下所示:

@Component
public class UserComponent {
    public void sayHi(){
        System.out.println("hi,component");
    }
}

在App中读取上面的UserComponent对象:

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

5.@Configuration(配置存储)

使用@Configuration存储Bean的代码如下所示:

@Configuration
public class UserConfiguration {
    public void doConfiguration(){
        System.out.println("hi,Configuration");
    }
}

在App中读取上面的UserConfiguration对象:

public class App {
    public static void main(String[] args) {
        ApplicationContext context=new ClassPathXmlApplicationContext("spring-config.xml");
        UserConfiguration userConfiguration=(UserConfiguration) context.getBean("userConfiguration");
        userConfiguration.doConfiguration();
    }
}

3.为什么这么多类注解

由以上对每个注解的介绍,可以看出,这些注解的功能都是一样的,那么为什么需要这么多类注解呢?

其目的就是让程序员看到类注解之后,就能直接了解当前类的用途。

@Controller:表示业务逻辑层,通常是指程序的入口,比如:参数校验,参数类型转换等前置处理工作。

@Service:服务层,一般写业务代码,服务编排,比如:调用DB,调用第三方接口。

@Repository:持久层,仓库,通常指DB操作相关的代码。(通常放在DAO层下面)

@Component:其它的对象。

@Configuration:配置层。

程序的工程分层,调用流程如下:

1.类注解之间的关系

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

 其实这些注解⾥⾯都有⼀个注解 @Component,说明它们本身就是属于 @Component 的“子类”。

4.方法注解@Bean

1.方法注解要搭配类注解使用

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

@Configuration
public class BeanConfig {
    @Bean
    public User user() {
        User user=new User();
        user.setName("温温");
        user.setAge(18);
        return user;
    }
}

注意:@Bean对应生产的bean名称是方法名

2.重命名Bean

可以通过设置name属性给Bean对象进行重命名操作,如下对象所示:

@Configuration
public class BeanConfig {
    @Bean(name={"wen","user"})
    public User user() {
        User user=new User();
        user.setName("温温");
        user.setAge(18);
        return user;
    }
}

此时使用wen和user都可以获取到User对象了:

        User user=(User) context.getBean("wen");
        System.out.println(user.getName());

2.Spring的读取------获取Bean对象(对象装配)

获取 bean 对象也叫做对象装配,是把对象取出来放到某个类中,有时候也叫对象注⼊

对象装配(对象注⼊)的实现⽅法以下 3 种:

1. 属性注⼊

2. 构造⽅法注⼊

3. Setter 注⼊

1.属性注入

属性注⼊是使⽤ @Autowired 实现的,将 Service 类注⼊到 Controller 类中。

Service类的代码如下:

@Service
public class UserService {
    public void doService(){
        System.out.println("doService");
    }
}

Controller类的实现代码如下:

@Controller
public class UserController {
    @Autowired
    private UserService userService;
    public void sayHi(){
        userService.doService();
        System.out.println("hi,userController~");
    }
}

最终结果如下:

2.构造方法注入

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

@Controller
public class UserController2 {
    private UserService us;
    public UserController2(UserService us) {
        this.us = us;
    }
    public void sayHi(){
        us.doService();
        System.out.println("hi,userController~");
    }
}

注意:1.如果只有一个构造方法,那么@Autowired可以省略

           2.如果有多个构造方法,那么需要添加上@Autowired来明确指定到底使用哪个构造方法,否则程序会报错。

3.Setter注入

Setter 注⼊和属性的 Setter ⽅法实现类似,只不过在设置 set ⽅法的时候需要加上 @Autowired 注

解,如下代码所示:

@Controller
public class UserController1 {
    private UserService us;
    @Autowired
    public void setUs(UserService us) {
        this.us = us;
    }
    public void sayHi(){
        us.doService();
        System.out.println("hi,userController~");
    }
}

4.三种注入方法的优缺点

优点缺点
属性注入简介,使用方便

补充:final修饰的属性,需要具备下列两个条件之一:

1.初始化赋值

2.构造函数赋值

 5.@Resource:另一种注入关键字

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

@Controller
public class UserController3 {
    @Resource
    private UserService us;
    public void sayHi(){
        us.doService();
        System.out.println("hi,userController~");
    }
}

@Resource和@Autowired的区别

  • 出身不同:@Autowired来自于Spring,⽽ @Resource 来⾃于 JDK 的注解;
  • 使⽤时设置的参数不同:相⽐于 @Autowired 来说,@Resource ⽀持更多的参数设置,例如 name 设置,根据名称获取 Bean。
  • @Autowired 可⽤于 Setter 注⼊、构造函数注⼊和属性注⼊,⽽ @Resource 只能⽤于 Setter 注⼊和属性注⼊,不能⽤于构造函数注⼊。

补充:

@Autowired

根据类型来获取bean,如果同一个类型的bean只有一个,直接注入成功

如果同一个类型的bean有多个,以名称匹配,注入相同名称的bean

如果没有名称相同的,就报错

6.同一类型多个@Bean报错

1.现象

当出现以下多个 Bean,返回同⼀对象类型时程序会报错,如下代码所示:

@Component
public class Users {
 @Bean
 public User user1() {
 User user = new User();
 user.setId(1);
 user.setName("Java");
 return user;
 }
 @Bean
 public User user2() {
 User user = new User();
 user.setId(2);
 user.setName("MySQL");
 return user;
 }
}

在另一个类中获取User对象:

@Controller
public class UserController4 {
 // 注⼊
 @Resource
 private User user;
 public User getUser() {
 return user;
 }
}

报错了,报错原因为:非唯一的Bean对象

 2.报错处理

解决同⼀个类型,多个 bean 的解决⽅案有以下两个:

使⽤ @Resource(name="user1") 定义。 使⽤ @Qualifier 注解定义名称。 使⽤ @Resource(name="xxx")

使⽤ @Qualifier

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

相关文章

  • Java Collection集合iterator方法解析

    Java Collection集合iterator方法解析

    这篇文章主要介绍了Java Collection集合iterator方法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-01-01
  • 从内存地址解析Java的static关键字的作用

    从内存地址解析Java的static关键字的作用

    这篇文章主要介绍了从内存地址解析Java的static关键字的作用,包括静态成员变量和静态方法等重要内容,需要的朋友可以参考下
    2015-10-10
  • Java实现选择排序算法的实例教程

    Java实现选择排序算法的实例教程

    这篇文章主要介绍了Java实现选择排序算法的实例教程,选择排序的时间复杂度为О(n&sup2;),需要的朋友可以参考下
    2016-05-05
  • 使用java + selenium + OpenCV破解网易易盾滑动验证码的示例

    使用java + selenium + OpenCV破解网易易盾滑动验证码的示例

    这篇文章主要介绍了使用java + selenium + OpenCV破解网易易盾滑动验证码,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-02-02
  • java String类常量池分析及

    java String类常量池分析及"equals"和"==”区别详细介绍

    这篇文章主要介绍了java String类常量池分析及"equals"和"==”区别详细介绍的相关资料,需要的朋友可以参考下
    2016-12-12
  • Java map的学习及代码示例

    Java map的学习及代码示例

    这篇文章主要介绍了Java map的学习及代码示例,简单介绍了map与collection的比较,map的相关内容,分享了map的一些简介代码示例,具有一定参考价值,需要的朋友可以了解下。
    2017-11-11
  • Java中使用正则检查有效日期的实现

    Java中使用正则检查有效日期的实现

    要判断一个字符串是否符合时间格式,可以使用正则表达式,本文主要介绍了Java中使用正则检查有效日期的实现,具有一定的参考价值,感兴趣的可以了解一下
    2023-10-10
  • 一篇文章带你使用SpringBoot基于WebSocket的在线群聊实现

    一篇文章带你使用SpringBoot基于WebSocket的在线群聊实现

    这篇文章主要介绍了一篇文章带你使用SpringBoot基于WebSocket的在线群聊实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-10-10
  • Lombok同时使⽤@Data和@Builder踩坑总结

    Lombok同时使⽤@Data和@Builder踩坑总结

    这篇文章主要介绍了Lombok同时使⽤@Data和@Builder踩坑总结,文章围绕主题展开详细的内容介绍,具有一定的参考价值需要的小伙伴可以参考一下,希望对你的学习有所帮助
    2022-05-05
  • Java中关键字final finally finalize的区别介绍

    Java中关键字final finally finalize的区别介绍

    这篇文章主要给大家分享的是 Java中final,finally,finalize 到底有什么区别,文章围绕final,finally,finalize的相关资料展开详细内容,具有一定的参考的价值,需要的朋友可以参考一下
    2022-04-04

最新评论