⭐️前言⭐️
在上一篇文章【Spring的创建与使用】中,我们已经了解了Spring中bean对象的基本的创建和使用方法,这篇文章通过注解的方法,使得存储和读取对象更加简单。
博客主页: 【如风暖阳】
精品Java专栏【JavaSE】、【备战蓝桥】、【JavaEE初阶】、【MySQL】、【数据结构】
欢迎点赞 收藏 ⭐留言评论 私信必回哟本文由 【如风暖阳】 原创,首发于 CSDN
博主将持续更新学习记录收获,友友们有任何问题可以在评论区留言
博客中涉及源码及博主日常练习代码均已上传码云(gitee)、GitHub
简单的将Bean存储到容器,有以下几种方法:
a)使用5大类注解实现
b)通过@Bean方法注解
下标我们一起来看具体的实现方式。
在使用更简单的方法存储和读取bean对象之前,先完成前置工作——在Spring配置文件中设置bean的扫描根路径:
<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="">content:component-scan>
beans>
使⽤ @Controller 存储 bean 的代码如下所示:
@Controller
public class UserController {
public void sayHi() {
System.out.println("你好,Contorller");
}
}
我们先使⽤之前读取对象的⽅式来读取上⾯的 UserController 对象,如下代码所示:
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",UserController.class);
//3.使用bean
userController.sayHi();
}
}
此处我们的beanName依旧是类名的小驼峰命名法,在后边我们会具体讲述Spring使用五大类注解生成beanName的问题。
使⽤ @Service 存储 bean 的代码如下所示:
@Service
public class UserService {
public void sayHi() {
System.out.println("你好,Service");
}
}
读取bean的代码:
public class App {
public static void main(String[] args) {
//1.得到Spring上下文
ApplicationContext context=
new ClassPathXmlApplicationContext("spring-config.xml");
//2.得到bean
UserService userService=context.getBean("userService",UserService.class);
//3.使用bean
userService.sayHi();
}
}
使⽤ @Repository 存储 bean 的代码如下所示:
@Repository
public class UserRepository {
public void sayHi() {
System.out.println("你好,Repository");
}
}
读取 bean 的代码:
public class App {
public static void main(String[] args) {
//1.得到Spring上下文
ApplicationContext context=
new ClassPathXmlApplicationContext("spring-config.xml");
//2.得到bean
UserRepository userRepository=context.getBean("userRepository",UserRepository.class);
//3.使用bean
userRepository.sayHi();
}
}
使⽤ @Component 存储 bean 的代码如下所示:
@Component
public class UserComponent {
public void sayHi() {
System.out.println("你好,Component");
}
}
读取 bean 的代码:
public class App {
public static void main(String[] args) {
//1.得到Spring上下文
ApplicationContext context=
new ClassPathXmlApplicationContext("spring-config.xml");
//2.得到bean
UserComponent userComponent=context.getBean("userComponent",UserComponent.class);
//3.使用bean
userComponent.sayHi();
}
}
使⽤ @Configuration 存储 bean 的代码如下所示:
@Configuration
public class UserConfiguration {
public void sayHi() {
System.out.println("你好,Configuration");
}
}
读取 bean 的代码:
public class App {
public static void main(String[] args) {
//1.得到Spring上下文
ApplicationContext context=
new ClassPathXmlApplicationContext("spring-config.xml");
//2.得到bean
UserConfiguration userConfiguration=context.getBean("userConfiguration",UserConfiguration.class);
//3.使用bean
userConfiguration.sayHi();
}
}
既然上述的五大类注解都能够完成将Bean对象存储到Spring中的功能,那为什么需要这么多的注解呢?
这是因为不同的注解有不同的用途,在程序猿看到类注解后,就能直接了解当前类的用途,增加了代码的可读性。
查看 @Controller / @Service / @Repository / @Configuration 等注解的源码发现:
这些注解里都有一个注解@Component,说明它们本身就是属于@Component的“子类”。
在1.2所有的获取bean对象的方法中,使用到的beanName都是小驼峰命名,但如果出现以下bean,还能通过小驼峰获取到吗?
@Controller
public class APIController {
public void sayHi() {
System.out.println("你好,APIController");
}
}
在我们去还以小驼峰命名法去获取bean对象时,发现报错,说明并不是所有的beanName都是以小驼峰命名法来命名的。
我们来查看beanName的命名规则源码:
(关于注解beanName的生成器)
我们来看bean对象的命名规则的方法:
它使⽤的是 JDK Introspector 中的 decapitalize ⽅法,源码如下:
public static String decapitalize(String name) {
if (name == null || name.length() == 0) {
return name;
}
// 如果第⼀个字⺟和第⼆个字⺟都为⼤写的情况,是把 bean 的⾸字⺟也⼤写存储了
if (name.length() > 1 && Character.isUpperCase(name.charAt(1)) &&
Character.isUpperCase(name.charAt(0))){
return name;
}
// 否则就将⾸字⺟⼩写
char chars[] = name.toCharArray();
chars[0] = Character.toLowerCase(chars[0]);
return new String(chars);
}
如果第⼀个字母和第⼆个字母都为⼤写的情况,是把 bean 的⾸字母也⼤写存储了,否则就将⾸字母⼩写
所以对于上⾯报错的代码,我们只要改为以下代码就可以正常运⾏了:
类注解是添加到某个类上的,而方法注解是放到某个方法上的,但仅依靠方法注解是仍然获取不到bean的,还需要搭配类注解:
先完成类代码:
public class User {
private int id;
private String name;
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + 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;
}
}
@Component
public class UserBeans {
@Bean
public User getUser() {
User user=new User();
user.setId(1);
user.setName("张三");
return user;
}
}
使用User类:
我们发现这样也可以获得User
对象,但是beanName
很别扭(也可以只通过bean type
来获取该类,但如果出现多次存储的情况就会报错),因为是方法名,而不是类名的小驼峰,所以我们可以通过设置name
属性给Bean
对象,进行重命名操作,下边看具体演示:
可以通过设置name属性给Bean对象进行重命名操作,如下代码所示:
@Component
public class UserBeans {
@Bean(name="u1")
public User getUser() {
User user=new User();
user.setId(1);
user.setName("张三");
return user;
}
}
获取bean对象也叫做对象装配,是把对象取出来放到某个类中,有时候也叫对象注入。
对象装配(对象注入)的实现方法有以下三种:
下边我们按照实际开发中的模式,将Service类注入到Controller类中。
属性注入是使用@Autowired
实现的,将Service
类注入到Controller
类中。
Service
类的实现代码如下:
@Service
public class UserService {
public void sayHi() {
System.out.println("你好,Service");
}
}
Controller
类的实现代码如下:
@Controller
public class UserController2 {
//属性注入
@Autowired
private UserService userService;
public void sayHi() {
userService.sayHi();
}
}
获取 Controller
中的 sayHi
⽅法:
构造方法注入是在类的构造方法上,使用@Autowired
实现注入,如下代码所示:
@Controller
public class UserController3 {
private UserService userService;
//构造方法注入
@Autowired
public UserController3(UserService userService) {
this.userService = userService;
}
public void sayHi() {
userService.sayHi();
}
}
注意:
如果只有一个构造方法,那么@Autowired
注释可以省略,但如果类中有多个构造方法,就必须加上注解来明确指定到底使用哪个构造方法,否则会报错。
Setter
注入和属性的Setter方法实现类似,只不过在设置set
方法的时候需要加上@Autowired
注解,如下代码所示:
@Controller
public class UserController4 {
private UserService userService;
//Setter注入
@Autowired
public void setUserService(UserService userService) {
this.userService=userService;
}
public void sayHi() {
userService.sayHi();
}
}
@Resourse
该注入注解与@Autowired
功能几乎相同,但也有差别,下边看两者的具体差别:
1、出身不同:@Resourse
来自于JDK,而@Autowired
是Spring框架提供的。
2、用法不同:@Autowired
支持属性注入、构造方法注入和Setter注入,而@Resourse
比前者少一个,它不支持构造方法注入。
3、支持的参数不同:@Resourse
支持更多的参数设置,比如name
、type
设置,而@Autowired
只支持required
参数设置。
当出现以下多个Bean,返回同一对象类型时程序会报错,如下代码所示:
@Component
public class UserBeans {
@Bean(name="u1")
public User getUser1() {
User user=new User();
user.setId(1);
user.setName("张三");
return user;
}
@Bean(name="u2")
public User getUser2() {
User user=new User();
user.setId(2);
user.setName("李四");
return user;
}
}
在另一个类中获取User对象,如下代码所示:
@Controller
public class UserController {
@Resource
private User user;
public void sayHi() {
System.out.println("user->"+user);
}
}
同一个类型多个Bean的报错处理有以下三种方式:
1、精确地描述bean
的名称(将注入的名称写对)
2、使用@Resourse
设置name的方式来重命名注入对象
3、使用@Autowired
+@Qualifier
来筛选bean对象
1、将对象存储到Spring
中:
@Controller
、@Service
、@Repository
、@Configuration
、@Component
【了解它们之间的关系与区别】@Bean
【注意搭配类注解一起使用】2、Bean的命名规则:
首字母和第二个字母都是大写,那么直接使用原Bean名来获取Bean,否则就让首字母小写(小驼峰)来获取Bean。
3、从Spring中获取对象:
4、注入的关键字:
@Autowired
@Resourse
5、 @Autowired
和 @Resourse
的区别:
@Resourse
不支持构造方法注入@Resourse
支持更多的参数6、解决同一类型多个Bean
的报错:
@Resourse(name="")
@Autowired @Qulifier("value =")
⭐️最后的话⭐️
总结不易,希望uu们不要吝啬你们的哟(^U^)ノ~YO!!如有问题,欢迎评论区批评指正