Spring更简单的读取和存储对象
1.存储 Bean 对象
之前我们存储 Bean 时, 需要在 Spring-config 中添加 一行 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
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.test">
</content:component-scan>
</beans>
如果不是在配置的扫描包下的类对象,即使添加了注解,也不能被存储到Spring中的.
② 添加注解存储 Bean 对象
想要将对象存储到Spring 中,有两种注解类型可实现:
1.类注解:
@Controller – 控制器
使用@Controller 存储 bean 的代码如下:
@Controller
public class UserController {
public void sayHi(String name){
System.out.println("Hi, " + name);
}
}
使用之前的ApplicationContext来读取上面的 UserController 对象
public static void main(String[] args) {
//1.得到上下文
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
//2.得到Bean对象
UserController userController = context.getBean("userController", UserController.class);
//调用bean 方法
userController.sayHi("张一");
}
@Service – 服务
使用@Service 存储 bean的代码如下所示
@Service
public class UserService {
public void sayHi(String name){
System.out.println("Hi, " + name);
}
}
调取 bean 的代码
public static void main(String[] args) {
//1.得到上下文
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
//2. 得到Bean对象
UserService userService = context.getBean("userService",UserService.class);
//3.调用Bean
userService.sayHi("张二");
}
@Repoistory – 仓库
使用Repoistory 存储bean 的代码如下所示
@Repository
public class UserRepository {
public void sayHi(String name){
System.out.println("Hi, " + name);
}
}
读取 bean 的代码
public static void main(String[] args) {
//1.得到上下文
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
// 2.得到Bean
UserRepository userRepository = context.getBean("userRepository",UserRepository.class);
//3.调用Bean
userRepository.sayHi("张三");
}
@Configuration – 配置
使用@Configuration 存储bean 的代码如下所示
@Configuration
public class UserConfiguration {
public void sayHi(String name){
System.out.println("Hi, " + name);
}
}
读取 bean 的代码
public static void main(String[] args) {
//1.得到上下文
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
//2.得到bean
UserConfiguration userConfiguration = context.getBean("userConfiguration",UserConfiguration.class);
//3.调用Bean
userConfiguration.sayHi("张四");
}
@Component – 组件
使用 @Component 存储 bean 的代码如下
@Component
public class UserComponent {
public void sayHi(String name){
System.out.println("Hi, " + name);
}
读取 bean
public static void main(String[] args) {
//1.得到上下文
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
UserComponent userComponent = context.getBean("userComponent",UserComponent.class);
userComponent.sayHi("张五");
}
③ 为什么要这么多类注解
④ 类注解之间的关系
@Controller, @Service, @Repository, @Configuration 都是基于 @Component 实现的,所以@Component 可以认为是其它4个注解的父类
⑤方法注解**@Bean方法**
@Component
public class Users {
@Bean(name = {"u1"})
public User user1(){
User user = new User();
user.setId(1);
user.setName("java");
return user;
}
取对象
public static void main(String[] args) {
//1.得到 spring
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
//2.得到某个 bean
User user = (User) context.getBean("u1");
System.out.println(user);
}
@Bean命名规则,当没有设置 name属性时,那么 bean 默认的名称就是方法名,当设置了 name 属性 之后,只能通过重命名的 name 属性对应的值来获取,也就是说重命名之后,在使用方法名就获取不到 bean 对象
2.获取 Bean 对象(对象装配)
获取 bean 对象也叫做对象装配,是把对象取出来放到某个类中,有时候也叫对象注入
对象装配(对象注入)的实现方法有以下3种
- 属性注入
- 构造方法注入
- Setter 注入
1. 属性注入
属性注入是使用@Autowired 实现的,将service 类注入到Controller类中.
Service 类的实现代码如下
@Service
public class UserService {
public User getUser(Integer id){
User user = new User();
user.setId(id);
user.setName("Java-"+id);
return user;
}
}
Controller类的实现代码如下:
@Controller
public class UserController {
//注入方法1: 属性注入
@Autowired
private UserService userService;
public User getUser(Integer id){
return userService.getUser(id);
}
}
获取Controller 中的getUser方法:
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
UserController userController = context.getBean(UserController.class);
System.out.println(userController.getUser(1).toString());
}
结果:
2.构造方法注入
构造方法注入是在类的构造方法中实现注入,如下代码所示
@Controller
public class UserController2 {
//注入方法2 : 构造方法注入
private UserService userService;
@Autowired
public UserController2(UserService userService){
this.userService = userService;
}
public User getUser(Integer id){
return userService.getUser(id);
}
}
3.Setter 注入
Setter 注入和属性的 Setter 方法实现类似,只不过在设置set 方法的时候需要加上,@Autowired注解,如下代码所示:
@Controller
public class UserController3 {
//注入方法3 : Setter
private UserService userService;
@Autowired
public void setUserService(UserService userService){
this.userService = userService;
}
public User getUser(Integer id){
return userService.getUser(id);
}
4.三种注入优缺点分析
- 属性注⼊的优点是简洁,使⽤⽅便;缺点是只能⽤于 IoC 容器,如果是⾮ IoC 容器不可⽤,并且只有在使⽤的时候才会出现 NPE(空指针异常)
- 构造方法注入是Spring 推荐的注入方式,它的缺点是如果有多个注⼊会显得⽐较臃肿,但出现这种情况你应该考虑⼀下当前类是否符合程序的单⼀职责的设计模式了,它的优点是通⽤性,在使⽤之
前⼀定能把保证注⼊的类不为空 - Setter ⽅式是 Spring 前期版本推荐的注⼊⽅式,但通⽤性不如构造⽅法,所有 Spring 现版本已经推荐使⽤构造⽅法注⼊的⽅式来进⾏类注⼊了
5.@Resource:另一种注入关键字
在进⾏类注⼊时,除了可以使⽤ @Autowired 关键字之外,我们还可以使⽤ @Resource 进⾏注⼊,如下代码所示
@Controller
public class UserController {
//注入方法1: 属性注入
@Resource
private UserService userService;
public User getUser(Integer id){
return userService.getUser(id);
}
}
@Autowired 和 @Resource 的区别
- 出身不同:@Autowired 来⾃于 Spring,⽽ @Resource 来⾃于 JDK 的注解
- 使⽤时设置的参数不同:相⽐于 @Autowired 来说,@Resource ⽀持更多的参数设置,例如 name设置,根据名称获取 Bean
6.同一类型多个@Bean 报错
当出现以下多个 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("C++");
return user;
}
}
在另⼀个类中获取 User 对象,如下代码如下:
@Controller
public class UserController4 {
@Resource
private User user;
public User getUser(){
return user;
}
}
以上程序的执⾏结果如下:
报错的原因,非唯一的Bean对象
同一类型多个Bean 报错处理
解决同⼀个类型,多个 bean 的解决⽅案有以下两个
- 使⽤ @Resource(name=“user1”) 定义
- 使⽤ @Qualifier 注解定义名称
使⽤ @Resource(name=“XXX”)
@Controller
public class UserController4 {
@Resource(name = "user1")
private User user;
public User getUser(){
return user;
}
}
使用@Qualifier
@Controller
public class UserController5 {
// 注⼊
@Autowired
@Qualifier(value = "user2")
private User user;
public User getUser() {
return user;
}
}