目录
一、存储Bean对象
在 Spring 中想要更简单的存储和读取对象的核心是使用注解
1.1 配置扫描路径
想要将Bean对象存储到Spring中,需要配置存储对象的扫描包路径,只有被配置的包下所有类,添加了注解才能被正确识别并保存到Spring中
在spring.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 htt
p://www.springframework.org/schema/beans/spring-beans.xsd http://www.spring
framework.org/schema/context https://www.springframework.org/schema/contex
t/spring-context.xsd">
<content:component-scan base-package="com.bit"></content:component-scan>
</beans>
【为什么要在spring的配置文件中,配置扫描路径?】
1.2 使用注解存储Bean对象
想要将对象存储在 Spring 中,有两种注解类型可以实现:
- 类注解:
- 方法注解:@Bean
【程序的工程分层,调用流程】
下面使用的是Controller注解,其他注解都是类似的
package com.bit;
import org.springframework.stereotype.Controller;
@Controller
public class User {
public void method(){
System.out.println("hello User");
}
}
1.3 通过上下文读取Bean对象
import com.bit.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import javax.jws.soap.SOAPBinding;
public class App {
public static void main(String[] args) {
//参数中传的是spring的配置文件名称
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring.xml");
User user=applicationContext.getBean("user",User.class);//默认的id名为小驼峰(并不绝对,后面详细说)
user.method();
}
}
1.4 Bean命名规则
我们先看下面这两个示例
(1)
(2)当要注册的类名的前两个首字母都是大写字母时,如果在获取时依然使用首字母小写作为id来获取就会报错
【观察默认bean命名规则的源代码】
1.5 方法注解 @Bean
类注解是添加到某个类上的,而方法注解是放到某个方法上的,如以下代码的实现
当我们写完以上代码,尝试获取 bean 对象中的 user1 时却发现,根本获取不到:
这是因为在Spring框架中,方法注解Bean要配合类注解才能将对象正常的存储到Spring容器中
修改代码:
通过Bean注解注册对象的默认beanName是方法名,因此我们通过方法名来获取注册到Spring当中的User对象
1.5 重命名Bean
重命名Bean主要用来解决:在两个不同类中有两个同名的方法且返回的对象类型相同且这两个方法都被Bean注解修饰,此时我们在根据方法名取对象时只能取到其中的一个
对Bean重命名:
StudentBeans
package com.bit;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
@Component
public class StudentBeans {
@Bean(name = "studentbeans_user")
//@Bean("studentbeans_user") 效果一样
//@Bean(name = {"studentbeans_user","user1","user2"})起多个名字
public User user(){
User user=new User();
user.setName("lisi");
user.setId(100);
return user;
}
}
UserBeans
package com.bit;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Controller;
@Controller
public class UserBeans {
@Bean(name = "userbeans_user")
public User user(){
User user=new User();
user.setName("zhangsan");
user.setId(100);
return user;
}
}
按照重命名后的名字取Bean
【注意】
二、获取Bean对象
获取Bean对象也叫做对象装配,是把对象取出来放到某个类中,有时候也叫对象注入。
对象装配的实现方法有以下三种:
- 属性注入
- 构造方法注入
- Setter注入
2.1 属性注入
属性注入是使用@Autowired实现的
下面演示在UserController中注入UserService对象
UserService:
package com.bit;
import org.springframework.stereotype.Service;
@Service
public class UserService {
/**
* 根据 ID 获取⽤户数据
*
* @param id
* @return
*/
public User getUser(Integer id) {
// 伪代码,不连接数据库
User user = new User();
user.setId(id);
user.setName("Java-" + id);
return user;
}
}
UserController:
package com.bit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@Controller
public class UserController {
@Autowired
private UserService userService;
public User getUser(Integer id){
return userService.getUser(id);
}
}
App:
public class App {
@Autowired
private UserController userController;
public static void main(String[] args) {
//参数中传的是spring的配置文件名称
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring.xml");
UserController userController=applicationContext.getBean("userController",UserController.class);
System.out.println(userController.getUser(1));
}
}
【注意】
【优缺点分析】
2.2 Setter注入
UserController类:
@Controller
public class UserController {
private UserService userService;
@Autowired //Setter注入的方式
public void setUserService(UserService userService) {
this.userService = userService;
}
public User getUser(Integer id){
return userService.getUser(id);
}
}
UserService的写法同上
【优缺点分析】
2.3 构造方法注入
UserController类
@Controller
public class UserController {
private UserService userService;
@Autowired
public UserController(UserService userService){
this.userService= userService;
}
public User getUser(Integer id){
return userService.getUser(id);
}
}
【注意】
【优点】
2.4 Resource注解
在进行依赖注入时,除了可以使用Autowired注解,JDK也提供了一个Resource注解,可以达到同样的效果
属性注入的方式:
@Controller
public class UserController {
@Resource
private UserService userService;
public void doUserController(){
userService.doUserService();
}
}
Setter注入的方式:
@Controller
public class UserController {
private UserService userService;
@Resource
public void setUserService(UserService userService){
this.userService=userService;
}
public void doUserController(){
userService.doUserService();
}
}
Resource注解不支持构造方法注入
【@Autowired和@Resource的区别】
2.5 Resource注解中name参数的作用
当在一个类中有两个方法,返回的对象类型相同且这两个方法都被Bean修饰,在另一个类中获取该对象时就会报错,具体看下面示例
UserBeans类中,有user1和user2方法,都返回User对象且被Bean注解修饰
@Controller
public class UserBeans {
@Bean
public User user1(){
User user=new User();
user.setName("zhangsan");
user.setId(100);
return user;
}
@Bean
public User user2(){
User user=new User();
user.setName("lisi");
user.setId(200);
return user;
}
}
在UserController类中通过Autowired属性注入的方式注入User对象
@Controller
public class UserController {
@Autowired
private User user;
public User getUser(){
return user;
}
}
App类启动时程序报错(使用Resource注解也会报同样的错误)
【发生上述错误的原因和注解的匹配方式有关】
【解决方式】
- 在使用注解注入时将变量名user改为user1或user2,这样就可以通过name筛选得到唯一对象
- 在不改变user的情况下,可以使用Resource中的name注解指定要获取的对象name
- 使用Autowired+Qualifier,在Qualifier注解的value参数中指定name,根据这个name进行筛选
【补充】