IOC详解Bean的声明以及DI详解,存在多个Bean解决方法

[复制链接]
admin 发表于 8 小时前 | 显示全部楼层 |阅读模式
IOC详解Bean的声明

注解

说明

位置

@Component

声明bean的基础注解

不属于以下三类时,用此注解
@Controller

@Component的衍生注解

标注在控制层类上
@Service

@Component的衍生注解

标注在业务层类上
@Repository


@Component的衍生注解

标注在数据访问层类上(由于与mybatis整合,用的少)

那么此时,我们就可以使用 @Service 注解声明Service层的bean。 使用 @Repository 注解声明Dao层的bean。 代码实现如下:
Service层:
  1. @Service
  2. public class UserServiceImpl implements UserService {

  3.     private UserDao userDao;

  4.     @Override
  5.     public List<User> findAll() {
  6.         List<String> lines = userDao.findAll();
  7.         List<User> userList = lines.stream().map(line -> {
  8.             String[] parts = line.split(",");
  9.             Integer id = Integer.parseInt(parts[0]);
  10.             String username = parts[1];
  11.             String password = parts[2];
  12.             String name = parts[3];
  13.             Integer age = Integer.parseInt(parts[4]);
  14.             LocalDateTime updateTime = LocalDateTime.parse(parts[5], DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
  15.             return new User(id, username, password, name, age, updateTime);
  16.         }).collect(Collectors.toList());
  17.         return userList;
  18.     }
  19. }
复制代码
Dao层:
  1. @Repository
  2. public class UserDaoImpl implements UserDao {
  3.     @Override
  4.     public List<String> findAll() {
  5.         InputStream in = this.getClass().getClassLoader().getResourceAsStream("user.txt");
  6.         ArrayList<String> lines = IoUtil.readLines(in, StandardCharsets.UTF_8, new ArrayList<>());
  7.         return lines;
  8.     }
  9. }
复制代码
  • 前面声明bean的四大注解,要想生效,还需要被组件扫描注解 @ComponentScan 扫描。
  • 该注解虽然没有显式配置,但是实际上已经包含在了启动类声明注解 @SpringBootApplication 中,默认扫描的范围是启动类所在包及其子包。
1
  • @Autowired用法

@Autowired 进行依赖注入,常见的方式,有如下三种:
1). 属性注入
  1. @RestController
  2. public class UserController {

  3.     //方式一: 属性注入
  4.     @Autowired
  5.     private UserService userService;
  6.    
  7.   }
复制代码
  • 优点:代码简洁、方便快速开发。
  • 缺点:隐藏了类之间的依赖关系、可能会破坏类的封装性。

2). 构造函数注入
  1. @RestController
  2. public class UserController {

  3.     //方式二: 构造器注入
  4.     private final UserService userService;
  5.    
  6.     @Autowired //如果当前类中只存在一个构造函数, @Autowired可以省略
  7.     public UserController(UserService userService) {
  8.         this.userService = userService;
  9.     }
  10.    
  11. }   
复制代码
  • 优点:能清晰地看到类的依赖关系、提高了代码的安全性。
  • 缺点:代码繁琐、如果构造参数过多,可能会导致构造函数臃肿。
  • 注意:如果只有一个构造函数,@Autowired注解可以省略。(通常来说,也只有一个构造函数)

3). setter注入
  1. /**
  2. * 用户信息Controller
  3. */
  4. @RestController
  5. public class UserController {
  6.    
  7.     //方式三: setter注入
  8.     private UserService userService;
  9.    
  10.     @Autowired
  11.     public void setUserService(UserService userService) {
  12.         this.userService = userService;
  13.     }
  14.    
  15. }   
复制代码

  • 优点:保持了类的封装性,依赖关系更清晰。
  • 缺点:需要额外编写setter方法,增加了代码量。

在项目开发中,基于@Autowired进行依赖注入时,基本都是第一种和第二种方式。(官方推荐第二种方式,因为会更加规范)但是在企业项目开发中,很多的项目中,也会选择第一种方式因为更加简洁、高效(在规范性方面进行了妥协)。

  • 注意事项
那如果在IOC容器中,存在多个相同类型的bean对象,会出现什么情况呢?
在下面的例子中,我们准备了两个UserService的实现类,并且都交给了IOC容器管理。 代码如下:
1.jpg

网站建设,公众号小程序开发,多商户单商户小程序制作,高端系统定制开发,App软件开发联系我们【手机/微信:17817817816
微信扫码

网站建设,公众号小程序开发,商城小程序,系统定制开发,App软件开发等

粤ICP备2024252464号

在本版发帖
微信扫码
QQ客服返回顶部
快速回复 返回顶部 返回列表