• Spring(存储Bean对象五大类注解,获取Bean对象三种注入方式)


    目录

    1. 先进行配置扫描路径

    2. 存储 Bean 对象 ( 添加注解存储 Bean 对象)

    2.1 @Controller [控制器存储]

    2.2 @Service [服务存储]

    2.3 @Repository [仓库存储]

    2.4 @Configuration [配置存储]

    2.5 @Component [组件存储]

    2.6 五大类注解的作用和关系

    2.7 Bean的命名规则

    2.8 使用方法注解 @Bean

    2.8.1 重命名 Bean

    3. 获取 Bean 对象 (对象装配) 

    3.1 属性注入

    3.2 构造方法注入

    3.3 Setter注入

    3.4 面试题: 三种注入优缺点分析

    3.5 @Resource:另一种注入关键字

    面试题: @Autowired 和 @Resource 的区别

    3.6 @Bean 将一个类型的对象注入多次的问题:


    在上一篇中,可以看到,创建Spring需要三步,存 bean 需要三步, 取 bean 需要三步,感觉这个读取和存储对象的步骤并没有想象的那么 "简单" 啊

    所以本篇将学习通过 "使用注解" 来更简单的存储和读取对象


    前面在存储 Bean 时,需要在 spring-config 中添加一行 bean 注册内容,这个XML文件有一点不好的是调试,而且XML文件报错了是不影响项目运行的,即使报错了,也可能发现不了.

    1. 先进行配置扫描路径

    1. "1.0" encoding="UTF-8"?>
    2. "http://www.springframework.org/schema/beans"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xmlns:content="http://www.springframework.org/schema/context"
    5. 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">
    6. package="com.bit.service">

    在 spring 配置文件中设置 bean 的扫描根路径


    2. 存储 Bean 对象 ( 添加注解存储 Bean 对象)

    使用 5 大类注解实现,就不用在spring-config 中添加一行 bean 注册内容了

    2.1 @Controller [控制器存储]

    1. package com.beans;
    2. import org.springframework.stereotype.Controller;
    3. @Controller
    4. public class UserController {
    5. public void sayHi() {
    6. System.out.println("你好,UserController!");
    7. }
    8. }
    1. import com.beans.UserController;
    2. import org.springframework.context.ApplicationContext;
    3. import org.springframework.context.support.ClassPathXmlApplicationContext;
    4. public class app {
    5. public static void main(String[] args) {
    6. //1. 先得到上下文对象
    7. ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
    8. //2. 得到 bean
    9. UserController controller = context.getBean("userController",UserController.class);
    10. //3. 使用 bean
    11. controller.sayHi();
    12. }
    13. }

    2.2 @Service [服务存储]

    1. import com.beans.UserController;
    2. import com.beans.UserService;
    3. import org.springframework.context.ApplicationContext;
    4. import org.springframework.context.support.ClassPathXmlApplicationContext;
    5. public class app {
    6. public static void main(String[] args) {
    7. ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
    8. UserService service = context.getBean("userService",UserService.class);
    9. service.sayHi();
    10. }
    11. }
    1. package com.beans;
    2. import org.springframework.stereotype.Service;
    3. @Service
    4. public class UserService {
    5. public void sayHi() {
    6. System.out.println("你好,Service!");
    7. }
    8. }

    2.3 @Repository [仓库存储]

    1. import com.beans.UserRepository;
    2. import org.springframework.context.ApplicationContext;
    3. import org.springframework.context.support.ClassPathXmlApplicationContext;
    4. public class app {
    5. public static void main(String[] args) {
    6. ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
    7. UserRepository repository = context.getBean("userRepository",UserRepository.class);
    8. repository.sayHi();
    9. }
    10. }
    1. package com.beans;
    2. import org.springframework.stereotype.Repository;
    3. @Repository
    4. public class UserRepository {
    5. public void sayHi() {
    6. System.out.println("你好,Repository!");
    7. }
    8. }

    2.4 @Configuration [配置存储]

    1. package com.beans;
    2. import org.springframework.context.annotation.Configuration;
    3. @Configuration
    4. public class UserConfiguration {
    5. public void sayHi() {
    6. System.out.println("你好,Configuration!");
    7. }
    8. }
    1. import com.beans.UserConfiguration;
    2. import org.springframework.context.ApplicationContext;
    3. import org.springframework.context.support.ClassPathXmlApplicationContext;
    4. public class app {
    5. public static void main(String[] args) {
    6. //1. 先得到上下文对象
    7. ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml"); UserConfiguration configuration = context.getBean("userConfiguration",UserConfiguration.class);
    8. configuration.sayHi();
    9. }
    10. }

    2.5 @Component [组件存储]

    1. package com.beans;
    2. import org.springframework.stereotype.Component;
    3. @Component
    4. public class UserComponent {
    5. public void sayHi() {
    6. System.out.println("你好,Component!");
    7. }
    8. }
    1. import com.beans.*;
    2. import org.springframework.context.ApplicationContext;
    3. import org.springframework.context.support.ClassPathXmlApplicationContext;
    4. public class app {
    5. public static void main(String[] args) {
    6. ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
    7. UserComponent component = context.getBean("userComponent",UserComponent.class);
    8. component.sayHi();
    9. }
    10. }

    2.6 五大类注解的作用和关系

    (1) 作用:

    这么多注解的作用是,如果一个项目特别大的情况下,文件会非常杂乱的,所以就是通过注解,来让程序员看到注解后就知道了,当前类的作用

    程序的最基础⼯程分层,调⽤流程如下

     (2) 关系:

    在五大注解类中 Component 可以当做其他注解的父类

    其他类之间的关系可以当做是兄弟

    下面看一下源码

    2.7 Bean的命名规则

    在前按照规范"大驼峰"取类名,然后getBean按照规范"小驼峰"是可以运行成功的

     而写如果写一个这样的类

     但是如果,这样写就可以运行成功

     那么 Bean 的命名规则到底应该是什么样的

    所以根据这个规则,正常下命名,如果类的前两个字符都为大写字母,就写原名字

    如果只有第一个字母为大写,那就按"小驼峰" 来命名


    2.8 使用方法注解 @Bean

    @Bean 是加在方法上的,并且只使用一个 @Bean 是无法将对象存储到容器中的,所以还要给类加个注解

    Bean 就是类注解的基础上缩小范围

    1. package com.beans;
    2. import org.springframework.context.annotation.Bean;
    3. import org.springframework.stereotype.Component;
    4. @Component
    5. public class UserBeans {
    6. @Bean //[只使用一个 @Bean 是无法将对象存储到容器中]
    7. public User user1() {
    8. User user = new User();
    9. user.setId(1);
    10. user.setName("张三");
    11. return user;
    12. }
    13. }
    1. import com.beans.*;
    2. import org.springframework.context.ApplicationContext;
    3. import org.springframework.context.support.ClassPathXmlApplicationContext;
    4. public class app {
    5. public static void main(String[] args) {
    6. //1. 先得到上下文对象
    7. ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
    8. User user = context.getBean("user1",User.class);
    9. // User user = context.getBean(User.class);
    10. System.out.println(user);
    11. }
    12. }
    1. package com.beans;
    2. public class User {
    3. private int id;
    4. private String name;
    5. @Override
    6. public String toString() {
    7. return "User{" +
    8. "id=" + id +
    9. ", name='" + name + '\'' +
    10. '}';
    11. }
    12. public int getId() {
    13. return id;
    14. }
    15. public void setId(int id) {
    16. this.id = id;
    17. }
    18. public String getName() {
    19. return name;
    20. }
    21. public void setName(String name) {
    22. this.name = name;
    23. }
    24. }

    2.8.1 重命名 Bean

    可以通过设置 name 属性给 Bean 对象进⾏重命名操作

    1. package com.beans;
    2. import org.springframework.context.annotation.Bean;
    3. import org.springframework.stereotype.Component;
    4. @Component
    5. public class UserBeans {
    6. @Bean(name = "userinfo") //[只使用一个 @Bean 是无法将对象存储到容器中]
    7. public User user1() {
    8. User user = new User();
    9. user.setId(1);
    10. user.setName("张三");
    11. return user;
    12. }
    13. }

    @Bean 命名规则,当没有设置name属性时,那么 bean 默认的名称就是方法名,

    当设置name属性后,只能通过重命名的name属性对应的值来获取,也就是说再使用方法就获取不到 bean 对象了,

    并且也可以 一个bean 有多个名字,像数组一样在{}中写上多个名字,就可以了 


    3. 获取 Bean 对象 (对象装配) 

    获取 Bean 对象也叫做对象装配,是把对象取出来放到某个类中,有时候也叫对象注入

    3.1 属性注入

    通过 @Autowired 就可以属性注入

    1. package com.beans;
    2. import org.springframework.beans.factory.annotation.Autowired;
    3. import org.springframework.stereotype.Controller;
    4. @Controller
    5. public class UserController2 {
    6. // 对象注入1: 属性注入
    7. @Autowired
    8. private UserService userService;
    9. public void sayHi() {
    10. userService.sayHi();
    11. }
    12. }
    1. import com.beans.*;
    2. import org.springframework.context.ApplicationContext;
    3. import org.springframework.context.support.ClassPathXmlApplicationContext;
    4. public class app {
    5. public static void main(String[] args) {
    6. //1. 先得到上下文对象
    7. ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
    8. UserController2 controller2 = context.getBean(UserController2.class);
    9. controller2.sayHi();
    10. }
    11. }

    3.2 构造方法注入

    写构造方法,参数传入要注入的对象,然后写上注解 @AutoWired (如果当前类中只有一个构造方法,那就可以省略注解)

    1. package com.beans;
    2. import org.springframework.beans.factory.annotation.Autowired;
    3. import org.springframework.stereotype.Controller;
    4. @Controller
    5. public class UserController2 {
    6. //使用构造方法实现 bean 注入(官方推荐写法)
    7. private UserService userService;
    8. @Autowired
    9. public UserController2(UserService userService) {
    10. // userService = new UserService(); //传统的写法
    11. this.userService = userService;
    12. }
    13. public void saHi() {
    14. userService.sayHi();
    15. }
    16. }

    3.3 Setter注入

    Setter 注入,写要注入的属性的 setter方法,然后加上注解 @Autowired

    1. package com.beans;
    2. import org.springframework.beans.factory.annotation.Autowired;
    3. import org.springframework.stereotype.Controller;
    4. @Controller
    5. public class UserController2 {
    6. //3. 使用 Setter 注入
    7. private UserService userService;
    8. @Autowired
    9. public void setUserService(UserService userService) {
    10. this.userService = userService;
    11. }
    12. public void sayHi() {
    13. userService.sayHi();
    14. }
    15. }

    3.4 面试题: 三种注入优缺点分析

    属性注入 / 构造方法注入 / Setter注入

    1. 属性注入特点: 写法简单,只适用于 IoC容器,通用性不好
    2. 构造方法注入: 这种写法从 spring 3.4后就成推荐写法了,通用性更好,能确保在使用注入对象之前,此注入对象一定是初始化过的.当构造方法注入参数过多时,开发者就要检查自己所写的代码是否符合单一设计原则的规范了.
    3. Setter 注入特点:这种写法是早期 Spring 版本的推荐写法(大概是3.4前),Setter 注入通用性没有构造方法注入通用

    3.5 @Resource:另一种注入关键字

    @Resource: 支持 属性注入 和 Setter 注入,但不支持构造方法注入

    面试题: @Autowired 和 @Resource 的区别

    相同点: 都可以实现将一个对象注入到类中
    不同点:
    1. 出身不同: @Resource 来自 JDK ;    @Autowired 是 Spring 框架提供的
    2. 用法不同: @Resource 用于 属性注入/Setter 注入 ;  @ Autowired 用于 属性注入/构造方法注入/Setter注入
    3. 支持的参数不同: @Resource 支持更多的参数设置,name/type....  ;  而 @Autowired 只支持 required 参数设置

    3.6 @Bean 将一个类型的对象注入多次的问题:

      解决方法

    (1) 精确的描述 bean 的名称 (将注入的名称写对)

    (2) 使用 @Resource 设置 name 的方式来重命名注入对象

    (3) 如果限定不能删除 @Autowired ,那就可以再加上使用 @Qualifier,来删选 bean 对象

     

     解决方法

    (1) 精确的描述 bean 的名称 (将注入的名称写对)

    1. package com.beans;
    2. import org.springframework.beans.factory.annotation.Autowired;
    3. import org.springframework.beans.factory.annotation.Qualifier;
    4. import org.springframework.stereotype.Controller;
    5. @Controller
    6. public class UserController {
    7. @Autowired //[属性注入/字段注入]
    8. private User user2;
    9. public void sayHi() {
    10. System.out.println("User -> " + user2);
    11. }
    12. }
    1. import com.beans.*;
    2. import org.springframework.context.ApplicationContext;
    3. import org.springframework.context.support.ClassPathXmlApplicationContext;
    4. public class app {
    5. public static void main(String[] args) {
    6. //1. 先得到上下文对象
    7. ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
    8. UserController controller = context.getBean(UserController.class);
    9. controller.sayHi();
    10. }
    11. }
    1. package com.beans;
    2. import org.springframework.context.annotation.Bean;
    3. import org.springframework.stereotype.Component;
    4. @Component
    5. public class UserBeans {
    6. @Bean(name = "userinfo") //[只使用一个 @Bean 是无法将对象存储到容器中]
    7. public User user1() {
    8. User user = new User();
    9. user.setId(1);
    10. user.setName("张三");
    11. return user;
    12. }
    13. @Bean
    14. public User user2() {
    15. User user = new User();
    16. user.setId(2);
    17. user.setName("李四");
    18. return user;
    19. }
    20. }

    (2) 使用 @Resource 设置 name 的方式来重命名注入对象

    (3) 如果限定不能删除 @Autowired ,那就可以再加上使用 @Qualifier,来删选 bean 对象

     


  • 相关阅读:
    【代码随想录算法训练营】第56天 | 第九章 动态规划(十六)+ 复习第28天 第六章 回溯(四)
    自动挂载磁盘
    tf.metrics
    前端项目负责人(虚拟岗)
    Nginx 使用自签名证书实现 https 反代 Spring Boot 中碰到的页面跳转问题
    ☆☆如何学习MATLAB☆☆
    gabse8a 认证培训课后题(二)
    EaselJS 源码分析系列--第三篇
    1024程序员节 | 电脑软件:SmartSystemMenu(窗口置顶工具)介绍
    macOS 下玩原生MAME 模拟器
  • 原文地址:https://blog.csdn.net/m0_58761900/article/details/128053256