package com.java.demo.service;
import com.java.demo.dao.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* Created with IntelliJ IDEA.
* Description:
* User: WJZ
* Date: 2023-10-16
* Time: 11:33
*/
@Service
public class UserService {
//1.属性注解
@Autowired //DI(依赖注入)
private UserRepository userRepository;//从spring当中取到UserRepository,并把它设值给当前变量
public int add() {
System.out.println("Do UserService add method");
//传统写法
//UserRepository userRepository = new UserRepository();
//return userRepository.add();
//spring V1.0
/*ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
UserRepository userRepository = context.getBean("userRepository",UserRepository.class);
return userRepository.add();*/
//spring V2.0
return userRepository.add();
}
}
UserRepository 类的实现代码如下:
java复制代码
@Repository
public class UserRepository {
public int add() {
System.out.println("Do UserRepository add method ");
return 1;
}
}
获取 UserService 中的 getUser ⽅法:
java复制代码
class UserServiceTest {
@Test
void add() {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
UserService userService = context.getBean("userService", UserService.class);
userService.add();
}
}
2️⃣获取多个对象:
User 类的实现代码如下:
java复制代码
public class User {
private String name;
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
将 User 对象存储到 Spring当中:
java复制代码
@Component
public class Users {
@Bean("user1")
public User user1() {
User user = new User();
user.setName("张三");
return user;
}
@Bean("user2")
public User user2() {
User user = new User();
user.setName("李四");
return user;
}
}
在 UserService2 中调用 User 对象(这个对象相同类型存储到 spring 中有两个,则根据 getName (根据名称)进行匹配)
java复制代码
@Service
public class UserService2 {
//属性注入
@Autowired
private User user;
public void sayHi() {
System.out.println(user.toString());
}
}
生成 UserService2Test 单元测试:
java复制代码
class UserService2Test {
@Test
void sayHi() {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
UserService2 userService2 = context.getBean("userService2", UserService2.class);
userService2.sayHi();
}
}
上述代码含义:在 @Autowired 中注入 User 对象:User对象放在 Users 当中,Users 存放在 demo 包下,会随着 spring 启动而启动,也就是说 spring 启动的时候,就会在 spring 框架中存 user1 = 张三 和use2 = 李四 (类型都是 User),通过单元测试拿到 UserService2,在UserService2 中注入 User 对象,打印信息
执行 测试类:
获取报错:获取唯一一个bean,但是找到了两个 bean
解决方案:
1️⃣将属性的名字和 Bean 的名字对应上
2️⃣使用 @Autowired 配合 @Qualifier 一起使用
3️⃣使用 @Resource
2.1.1 属性注入优点
属性注入最大的优点就是实现简单、使用简单,只需要给变量上添加一个注解(@Autowired),就可以在不 new 对象的情况下,直接获得注入的对象了(这就是 DI 的功能和魅力所在),所以它的优点就是使用简单。
2.1.2 属性注入缺点
1️⃣无法注入 final 修饰的变量
final 特征
被 final 修饰的变量需要直接赋值
在构造方法中进行赋值
2️⃣通用性问题:只适用于 IoC 容器
3️⃣更容易违背单一设计原则,因为使用起来比较简单
2.2 Setter 注入
java复制代码
//Setter 注入
@Service
public class UserService3 {
private UserRepository userRepository;
@Autowired
public void setUserRepository(UserRepository userRepository) {
this.userRepository = userRepository;
}
public void sayHi() {
System.out.println("Do UserService3 sayHi method");
userRepository.add();
}
}
2.2.1 优点
通常 Setter 只 Set 一个书属性,所以 Setter 注入更符合单一设计原则
2.2.2 缺点
1️⃣无法注入 final 修饰的变量
2️⃣setter 注入的对象可以被修改(setter 本来就是一个方法,有可能被多次调用和修改)
2.3 构造方法注入
造方法注入是 Spring 官方从 4.x 之后推荐的注入方式
java复制代码
@Service
public class UserService4 {
private UserRepository userRepository;
@Autowired
public UserService4(UserRepository userRepository) {
this.userRepository = userRepository;
}
public void sayHi() {
System.out.println("Do UserService4 sayHi");
userRepository.add();
}
}
在 Spring 项⽬中,通过 main ⽅法获取到 Controller 类,调⽤ Controller ⾥⾯通过注⼊的⽅式调⽤ Service 类,Service 再通过注⼊的⽅式获取到 Repository 类, 类⾥⾯有⼀个⽅法构建⼀个 User 对象,返回给 main ⽅法。Repository ⽆需连接数据库,使⽤伪代码即