0


一文带你了解Spring中存入Bean和获取Bean的方式

0. Spring中的五大注解

在这里插入图片描述
上图中就是五大类注解对应的层,通过源码可以看到其他四个注解都基于@Conponent

1. 存入 Bean

Spring既然是一个包含众多工具方法的IoC容器,它是一个控制反转的容器,所以就需要将Bean对象存入到容器中,需要用的时候从容器中获取Bean对象,下面我们来介绍下存入Bean对象。

1.1 在 xml 中存入 Bean 对象

<?xml version="1.0" encoding="UTF-8"?><beansxmlns="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">

   // 这句代码中, id 就是给 这个要注入的对象取个名字, class就是 要存入的 Bean 的类型是哪一个
    <bean id = "user" class="com.java.demo.User"></bean></beans>

在这里插入图片描述

1.2 通过配置 Bean 扫描路径 + 类注解 实现 Bean 的存储

<?xml version="1.0" encoding="UTF-8"?><beansxmlns="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-scanbase-package="com.java.demo"></content:component-scan></beans>

配置了 Bean 的扫描路径,只有当前目录下的类才会被扫描是否加了类注解,如果加了类注解后,就会将 所有加了类注解的类 存入到 IoC 容器中。

@ComponentpublicclassUser{publicvoidsay(){
        System.out.println("Hello User...");}}

类注解存Bean需要注意几点

  • 如果类名为大驼峰命名规则,那么获取 Bean 的默认名称,就是 类名首字母小写
  • 如果不满足首字母大写,第二个字母小写,那么 Bean 的名称,就是原类名,这点可以看源码知道在这里插入图片描述

1.3 通过配置 Bean 扫描路径 + 方法注解 实现 Bean 的存储

<?xml version="1.0" encoding="UTF-8"?><beansxmlns="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-scanbase-package="com.java.demo"></content:component-scan></beans>
publicclassStudent{private String name;private Integer age;public String getName(){return name;}publicvoidsetName(String name){this.name = name;}public Integer getAge(){return age;}publicvoidsetAge(Integer age){this.age = age;}@Overridepublic String toString(){return"Student{"+"name='"+ name +'\''+", age="+ age +'}';}}
@ComponentpublicclassUser{@Beanpublic Student getStudent(){
        Student student =newStudent();
        student.setName("张三");
        student.setAge(18);return student;}publicvoidsay(){
        System.out.println("Hello User...");}}

在上述代码中,我们可以通过 在方法上 加上 @Bean 注解 将该方法存入到 IoC 容器中,并且可以直接获取到该对象。
在这里插入图片描述


在使用 @Bean 注解的时候,需要注意几点

  • @Bean 注解必须配合 五大类注解一块使用
  • @Bean 注解的默认命名 = 方法名称
  • 如果使用 @Bean(“xxxx”)方式,那么名称就是 xxxx, 并且 @Bean({“xxx”,“xxxxx”,“xxxxxx”}),里面可以类似和数组一样多个名称
  • 如果@Bean重命名后,那么默认的方法名就没用,获取Bean的时候就不能写默认方法名
  • 如果多个 Bean 使用相同的名称,则不会报错,只会存储第一个 Bean对象,之后相同名称的不会存入,会自动忽略

2. 获取 Bean

2.1 依赖查找(DF)

依赖查找(依赖Bean的名称),有两种方式,一种是 ApplicationContext, 一种是 BeanFactory。这两种都是容器管理对象,都可以获取到 Bean对象

2.11 ApplicationContext

publicclassApp{publicstaticvoidmain(String[] args){// 1. 获取 Spring 上下文对象
        ApplicationContext context =newClassPathXmlApplicationContext("spring-config.xml");// 2。获取 Bean 对象
        Student student =(Student) context.getBean("student");
        System.out.println(student);}}

2.12 BeanFactory

publicstaticvoidmain(String[] args){// 1. 得到 spring 上下文对象
        BeanFactory context =newXmlBeanFactory(newClassPathResource("spring-config.xml"));// 2. 获取 Bean 对象//Student student = (Student)context.getBean("user");

        Student student =(Student)context.getBean("student");
        System.out.println(student.toString());}

2.13 Application VS BeanFactory

ApplicationContextBeanFactoryApplicationContext是BeanFactory的子类,其拥有更多功能(国际化支持、资源访问支持、事件传播)BeanFactory是ApplicationContext的父类ApplicationContext加载Bean:一次性加载所有Bean对象BeanFactory加载Bean:懒加载,按需加载(使用一个加载一个)
在这里插入图片描述

2.2 依赖注入(DI)

在 spring 中实现依赖注入的常见方式有3种:

  • 1.属性注入
  • 2.setter注入
  • 3.构造方法注入

2.21 属性注入

@ControllerpublicclassUserController{/**
     * 属性注入
     */@Autowiredprivate UserService userService;// 此处 main方法里面,必须使用依赖查找的方式,先获取到UserControllerpublicstaticvoidmain(String[] args){
        ApplicationContext context =newClassPathXmlApplicationContext("spring-config.xml");
        UserController userController =(UserController) context.getBean("userController");
        userController.userService.say();}}

属性注入:

优点: 实现简单、使用简单,只需要在属性上加一个注解@Autowired,就不需要自己new一个对象,直接获得注入的对象。

缺点:

  1. 无法注入一个用 final 修饰的对象在这里插入图片描述 因为在Java语法中,final修饰的对象(不可变),要么一开始就赋值,要么在构造方法里面赋值。而上述使用属性注入,注入final修饰的对象,就不符合规范,所以不行。

  1. 只能适用于 IoC 容器:如果将这些代码放到其他非IoC容器中,那么代码就会失效
  2. 设计原则:更容易违背单一原则,因为属性注入比较简单,那么可能就会在一个类中注入多个对象,这就可能不符合程序的单一职责问题。

2.22 Setter注入

@ControllerpublicclassUserController2{private UserService userService;/**
     * setter注入
     */@AutowiredpublicvoidsetUserService(UserService userService){this.userService = userService;}publicstaticvoidmain(String[] args){
        ApplicationContext context =newClassPathXmlApplicationContext("spring-config.xml");
        UserController2 userController2 =(UserController2) context.getBean("userController2");
        userController2.userService.say();}}

优点:似乎没什么优点,而且比属性注入更加麻烦,要说唯一可能有用的就是,完全符合单一职责设计原则,每个 setter 只针对一个对象。Setter注入 也适用于非IoC容器
缺点:

  1. 不能注入 final 对象在这里插入图片描述
  2. 由于是 Setter 注入,提供了 set 方法,那么注入的对象可以随时被更改

2.23 构造方法注入(Spring4.x之后推荐的)

@ControllerpublicclassUserController3{privatefinal UserService userService;/**
     * 构造方法注入
     */// @Autowired 此处如果构造方法参数只有一个的时候,该注解可有可无publicUserController3(UserService userService){this.userService = userService;}publicstaticvoidmain(String[] args){
        ApplicationContext context =newClassPathXmlApplicationContext("spring-config.xml");
        UserController3 userController3 =(UserController3) context.getBean("userController3");
        userController3.userService.say();}}

优点:

  1. 可以注入 被final 修饰的对象在这里插入图片描述
  2. 注入对象不会被更改,因为是在构造方法注入的,构造方法在对象创建的时候只会创建一次
  3. 注入的对象会被完全初始化
  4. 通用性会更好,无论在 IoC容器 还是 非 IoC容器中都能用

缺点:

  1. 写法更加复杂
  2. 使用构造方法,无法解决循环依赖的问题

Spring官方推荐的是构造方法的注入,可以注入不可变对象,通用性更好;如果想要注入可变对象,那么可以使用 Setter 注入。

3. 解决同一类型多个 Bean 的报错问题

在这里插入图片描述
上述代码,可以看到报错,出现了多个同一类型的多个Bean报错,需要1个,找到了2个。如何解决呢

  • 1.@Autowired 配合 @Qualifier(value = “xxx”)一起使用,里面参数加方法名字在这里插入图片描述
  • 2.使用@Resource(name = “xxxx”)在这里插入图片描述

3. @Resource 和 @Autowired

  • 出身不同:@Resource来自于JDK,@Resource来自于Spring
  • 支持参数不同:@Resource支持更多的参数在这里插入图片描述 @Autowired只支持一个参数设置
  • 使用上的区别:@Resource不支持构造方法的注入在这里插入图片描述
  • 兼容性问题:@Autowired在社区版 IDEA可能会误报;

标签: spring java

本文转载自: https://blog.csdn.net/hero_jy/article/details/131794428
版权归原作者 一个想打拳的程序员 所有, 如有侵权,请联系我们删除。

“一文带你了解Spring中存入Bean和获取Bean的方式”的评论:

还没有评论