文章目录

  • 前言
  • 1、存储 Bean 对象
    • 1.1 前置工作
    • 1.2 添加注解存储 Bean 对象
      • @Controller(控制器存储)
      • @Service (服务存储)
      • @Repository(仓库存储)
      • @Configuration(配置存储)
      • @Component(组件存储)
      • 为什么需要五大类注解以及它们的关系
      • 方法注解 @Bean
  • 2、获取 Bean 对象(对象装配)
    • 2.1 属性注入
    • 2.2 构造方法注入
    • 2.3 Setter 注入
    • 2.4 三种注入方式的区别
    • 2.5 @Autowired 和 @Resource

前言

在 Spring 中想要更简单的存储和读取对象的核心是使用注解

1、存储 Bean 对象

之前我们存储 Bean 时,需要在 spring-config 中添加一行 bean 注册内容才行,并且每个 bean 都要进行注册,例如:

而现在我们只需要⼀个注解就可以替代之前要写一行配置

1.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="com.beans"></content:component-scan>
</beans>

Spring会以 com.beans 为根路径,进行递归式的扫描,如果类上添加了注解,就会被存储到Spring中。但是如果类添加了注解,却不在配置的扫描路径下,是不会被存储到Spring中的

1.2 添加注解存储 Bean 对象

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

  1. 五大类注解:@Controller、@Service、@Repository、@Component、@Configuration
  2. 方法注解:@Bean

@Controller(控制器存储)

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

@Controller
public class UserController {public void sayHi() {System.out.println("hello Controller");}
}

读取 UserController 对象:

public class App {public static void main(String[] args) {//1.先得到上下文对象ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");//2.得到 beanUserController userController = context.getBean("userController", UserController.class);//调用 bean 方法userController.sayHi();}
}

在 spring-config 中,我们并没有注册 UserController,因此也就没有 UserController 对应的 name(id),此时,我们在得到 UserController 时,如何知道 UserController 的 name(id)呢?
这里的 name 其实就是 UserController 的小驼峰命名,也就是 userController
如果是 APIController,此时的 name 就是 APIController,和原来的类名保持一致,至于为什么是这样的,可以看一下源码

@Service (服务存储)

使用 @Service 存储 bean 的代码如下所示:

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

读取 UserService 对象:

public class App {public static void main(String[] args) {//1.先得到上下文对象ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");//2.得到 beanUserService userService = context.getBean("userService", UserService.class);//调用 bean 方法userService .sayHi();}
}

@Repository(仓库存储)

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

@Repository
public class UserRepository {public void sayHi() {System.out.println("你好 Repository");}
}

读取 UserRepository 对象:

public class App {public static void main(String[] args) {//1.先得到上下文对象ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");//2.得到 beanUserRepository userRepository = context.getBean("userRepository", UserRepository.class);//调用 bean 方法userRepository.sayHi();}
}

@Configuration(配置存储)

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

@Configuration
public class UserConfig {public void sayHi() {System.out.println("你好 Configuration");}
}

读取 Configuration 对象:

public class App {public static void main(String[] args) {//1.先得到上下文对象ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");//2.得到 beanUserConfiguration userConfiguration = context.getBean("userConfiguration", UserConfiguration.class);//调用 bean 方法userConfiguration.sayHi();}
}

@Component(组件存储)

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

@Component
public class UserComponent {public void sayHi() {System.out.println("你好 Component");}
}

读取 UserComponent 对象:

public class App {public static void main(String[] args) {//1.先得到上下文对象ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");//2.得到 beanUserComponent userComponent = context.getBean("userComponent", UserComponent.class);//调用 bean 方法userComponent.sayHi();}
}

上述获取 bean 时,除了根据 bean name(id) 和类型获取 bean,还可以根据 bean type 获取 bean,也可以根据 bean name(id) 来获取 bean

为什么需要五大类注解以及它们的关系

通过对这五大类注解的使用,我们发现它们的功能似乎是⼀样的,既然功能是一样的,那为什么需要这么多的类注解呢?

先举个例子:

每个省/市都有自己的车牌号。例如重庆的车牌号就是:渝X:XXXXXX,四川的车牌号是:川X:XXXXXX。甚至⼀个省不同的县区也是不同的,例如重庆,渝A:XXXXXX,表示重庆市区——江南,渝B:XXXXXX,表示重庆市区——江北,渝F:XXXXXX,表示重庆市万州区。
这样做的好处除了可以节约号码之外,更重要的作用是可以直观的标识⼀辆车的归属地

那么为什么需要怎么多的类注解也是相同的原因,让代码的可读性提高,让程序员能够直观的判断当前类的用途。比如:

  • @Controller:表示的是业务逻辑层
  • @Servie:服务层
  • @Repository:持久层
  • @Configuration:配置层

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

在实际的工程中,分层只会比这四层多,不可能会少

如何知道五大类注解是否有关系,只需要查看它们的源码即可

通过源码,我们发现 @Controller,@Service,@Repository,@Configuration 都是基于 @Component 实现的,所以可以认为 @Component 是其它四个注解的父类

方法注解 @Bean

@Bean 只能添加到方法上,如果添加到类上,则会显示的报错

先定义一个User类

public class User {private int id;private String name;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "User{" + "id=" + id + ", name=" + name + "}";}
}

使用 Bean 注解

@Component
public class UserBeans {@Beanpublic User user1() {User user = new User();user.setId(721);user.setName("fl");return user;}
}

注意:只使用一个 @Bean 是无法将对象存储到容器当中的,必须要还要配合五大类注解才行

获取并使用

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

这里是通过 name 来获取 bean 对象的,也可以使用类型来获取,但需要保证这个类型的对象只被注入一次,否则将会报错

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

@Component
public class UserBeans {@Bean(name = "u1")public User user1() {User user = new User();user.setId(721);user.setName("fl");return user;}
}

name 属性可以设置多个名字,但需要使用{}括起来,例如:

@Bean(name = {"u1", "u2", "u3"})

此时我们使用 u1 就可以获取到 User 对象了

public class App {public static void main(String[] args) {//1.先得到上下文对象ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");//2.得到 beanUser user = (User) context.getBean("u1");//3.掉用 bean 方法System.out.println(user);

@Bean 命名规则:

当没有设置name属性时,那么bean默认的名称就是方法名,当设置了name属性之后,只能通过重命名的name属性对应的值来获取,也就是说重命名之后,再使用方法名就获取不到bean对象。

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

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

  1. 属性注入
  2. 构造方法注入
  3. Setter注入

2.1 属性注入

属性注⼊是使用 @Autowired 或者 @Resource 实现的,将UserBeans类注入到UserController类中。
UserBeans类代码实现:

@Component
public class UserBeans {@Beanpublic User user1() {User user = new User();user.setId(721);user.setName("fl");return user;}@Beanpublic User user2() {User user = new User();user.setId(127);user.setName("lf");return user;}
}

UserController类的代码实现:

@Controller
public class UserController {@Autowiredprivate User user;public void sayHi() {System.out.println("hello Controller");}@Overridepublic String toString() {return "UserController{" +"user=" + user +'}';}
}

因为 UserController 类只被注入了一次,因此采用类型来获取 UserController 对象

public class App {public static void main(String[] args) {//1.先得到上下文对象ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");//2.得到bean对象UserController userController = context.getBean(UserController.class);//3.调用bean方法System.out.println(userController);}
}

结果却报错了,原因就是在 UserController 使用 User 对象,会根据名称 user 去找,没有名称为 user 的对象,就会根据类型去找,但是类型为 User 的对象出现了两次(user1,user2),不知道该用哪一个,所以报错了

只要我们将 user 改为 user1 或者 user2 ,或者将 User 对象只注入一次,就能解决这个问题

还能用 @Resource 设置 name 的方式来重命名注入对象

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

除此之外, 可以使用@ Autowired + @Qualifier来筛选bean 对象

@Controller
public class UserController {@Autowired@Qualifier("user1")private User user;public void sayHi() {System.out.println("hello Controller");}@Overridepublic String toString() {return "UserController{" +"user=" + user +'}';}
}

@Qualifier中也可以时用键值对的方式来指定对象,例如:@Qualifier(value = “user1”)

2.2 构造方法注入

构造方法注入是在类的构造方法中实现注入,将 Service 类注⼊到 Controller 类中

Service 类的代码实现:

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

UserController 类的代码实现:

@Controller
public class UserController {private UserService userService;@Autowiredpublic UserController(UserService userService) {this.userService = userService;}public void sayHi() {userService.sayHi();}
}

调用构造方法时,会直接从 Spring 中取出 userService 对象,赋值给 UserController 类中的userService

构造方法注入,只需要在构造方法前加上 @Autowired 注解即可,如果当前类中只存在一个构造方法,那么 @Autowired 注解可以省略

2.3 Setter 注入

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

代码如下:

@Controller
public class UserController {private UserService userService;@Autowiredpublic void setUserService(UserService userService) {this.userService = userService;}public void sayHi() {userService.sayHi();}
}

setter 注入既可以使用 @Autowired 注解,也可以使用 @Resource注解

2.4 三种注入方式的区别

  1. 属性注入:特点写法简单。但是通用性不好,它只能运行在IoC 容器下,如果是非IoC容器就会出现问题
  2. Setter注入:早期Spring版本推荐的写法,Setter注入通用性比构造方法注入差
  3. 构造方法注入:通用性更好、它能确保在使用注入对象之前,此注入对象一定初始化过了。当构造方法注入参数过多时,此时开发者就要检查自己所写的代码是否符合单一设计原则的规范了,此注入方式也是spring 后期版本中推荐的注入方式

2.5 @Autowired 和 @Resource

  1. 出身不同:@Resource 来自JDK (Java亲儿子),@Autowired 是Spring框架提供的
  2. 用法不同:@Autowired支持属性注入、构造方法注入和Setter 注入,而@Resource 不支持构造方法注入
  3. 支持的参数不同:@Resource 支持更多的参数设置,比如name、type 设置,而@Autowired 只支持required参数设置

Spring更简单的读取和存储对象相关推荐

  1. javaEE进阶 - Spring 更简单的读取和存储对象 - 细节狂魔

    文章目录 前言 1.存储 Bean 对象 1.1.前置工作:配置扫描路径(重要) 1.2.简单的将 bean 存储到容器 1.使用 5 大类注解实现将 bean 存储到 容器 @Controller ...

  2. 【Java】Spring更简单的读取和存储

    文章目录 Spring更简单的读取和存储对象 1. 存储Bean对象 1.1 前置工作:配置扫描路径 1.2 添加注解存储Bean对象 1.2.1 @Controller(控制器存储) 1.2.2 @ ...

  3. Spring:更简单的存储与读取Bean对象

    前言: 上节课我们简单了解一些Spring非常基础的使用,但是在存储与读取Bean对象这个操作上来看还是有点麻烦滴~~ 我们有更方便的方法去实现存储与读取Bean对象. 1.存储Bean对象 我们要想 ...

  4. Spring更简单的存储对象------不使用XML而使用注解

    1.更简单进行存储: 1.先进行创建Spring的项目 先进行创建maven项目,在pom.xml里面引入对Spring所依赖的jar包(核心包:5.2.3) <!-- https://mvnr ...

  5. 使用spring最简单地读取properties文件中的内容

    相比传统的读取propertis文件内容,使用spring框架会更加简单快捷 1. 第一步,在spring的配置文件中,将propertis文件加载到spring容器 2. 加载了配置文件后,只需要在 ...

  6. Spring Security+Spring Data Jpa 强强联手,安全管理只有更简单!

    Spring Security+Spring Data Jpa 强强联手,安全管理没有简单,只有更简单! 这周忙着更新 OAuth2,Spring Security 也抽空来一篇. Spring Se ...

  7. 让CoreData更简单些

    从简书迁移到掘金 前言 本文并不是CoreData从入门到精通之类的教程, 并不会涉及到过多的原理概念描述, 而是介绍如何让CoreData的使用变得更加简单明了, 方便亲民. 全文约六千字, 预计花 ...

  8. 深入解析 Kubebuilder:让编写 CRD 变得更简单

    原文连接:https://developer.aliyun.com/article/719215 作者 | 刘洋(炎寻) 阿里云高级开发工程师 导读:自定义资源 CRD(Custom Resource ...

  9. mysql 利用触发器(Trigger)让代码更简单

    一,什么触发器 1,个人理解 触发器,从字面来理解,一触即发的一个器,简称触发器(哈哈,个人理解),举个例子吧,好比天黑了,你开灯了,你看到东西了.你放炮仗,点燃了,一会就炸了. 2,官方定义 触发器 ...

最新文章

  1. Python中常见字符串去除空格的方法总结
  2. 用WDM开发USB驱动程序
  3. redmine 贴图操作
  4. wordpress content.php,2020主题:content.php
  5. 20180307:python接口测试时json的传参与解析区分
  6. Git 分支管理-git stash 和git stash pop
  7. jq苹果手机全屏下点击无效果_苹果系统自带外挂?无需越狱也可录制动作脚本...
  8. 语音识别学习笔记(二)【基于矢量量化的识别技术】
  9. Android App优化之提升你的App启动速度之实例挑战
  10. 组织架构递归_映射架构和递归管理数据–第1部分
  11. C++ 中的指针、引用以及函数调用中的问题
  12. E-prime脑电实验设计
  13. Morketing Summit 2019“破·局”:有破有立,突破棋局 | MS2019灵眸·全球营销商业峰会全面启动!...
  14. 堡垒机阿里云安装包安装
  15. 计算任意2个日期内的工作日(没有考虑到国定假日
  16. Oracle 11g 修改表的所属表空间
  17. 【基础入门题026】佩尔数列Pell(n)
  18. 程序员转正述职报告_程序员转正的述职报告【五篇】
  19. redis实现简单的动态密码
  20. 有理函数多项式分解以及系数的留数法求解

热门文章

  1. RR级别下的GAP锁范围
  2. 用python定位他人手机_Python练习篇之3-利用tag name定位元素
  3. 修改CSS样式实现网页变灰色/黑白代码的几个方法整理
  4. 23 届校招技术岗薪资汇总
  5. 前端实现返回前一页面
  6. 电竞分析丨英雄联盟竞猜 TES挥师西安会WE豪强;iG、JDG“春决重演”一触即发
  7. 将手机上的小文件通过php脚本上传到linux服务器
  8. 物联网网络安全_物联网网络及其安全
  9. the import java.sql cannot be resolved_the import XXXX cannot be resolved 解决方法
  10. 今日头条十年,交出了一份怎样的答卷?