@Autowired和@Resource注解之间的关系区别,Bean的作用域和生命周期,Spring的执行流程

这篇具有很好参考价值的文章主要介绍了@Autowired和@Resource注解之间的关系区别,Bean的作用域和生命周期,Spring的执行流程。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

一. @Autowired 和 @Resource 注解

二. Bean的作用域 

1. singleton(单例模式)

2. prototype(原型模式)(多例模式)

3. 请求作用域:request

4. 会话作用域:session

三. Spring 的执行流程

四. Bean 的生命周期 

 1. 实例化

 2. 设置属性 

3. Bean 初始化  

   3.1 执行各种各种 Aware 通知; 

   3.2 执行初始化前置方法;

   3.3 执行初始化方法;

   3.4 执行初始化后置方法; 

4. 使用 Bean 对象

5. 销毁 Bean 对象 

6. 代码演示 


一. @Autowired 和 @Resource 注解

在前面的文章中,我们介绍了通过 @Autowired 注解的方式来获取到Spring容器中的Bean对象,实际上,还有另一个注解:@Resource,它的功能也是差不多的,也可以从 Spring容器中获取到Bean对象,但也是存在一定的差别的。 

  1. @Resource 来自于 jdk,而 @Autowired 来自于 Spring;
  2. 使⽤时设置的参数不同:相⽐于 @Autowired 来说,@Resource ⽀持更多的参数设置,例如
    name 设置,根据名称获取 Bean;
  3. @Autowired 可⽤于 Setter 注⼊、构造函数注⼊和属性注⼊,⽽ @Resource 只能⽤于 Setter 注⼊和属性注⼊,不能⽤于构造函数注⼊;
  4. @Autowired在获取Bean对象的时候,先根据类型查找,之后再根据名称查找;而@Resource先根据名称查找,之后再根据类型查找;

问题分析:当在 Spring 中存放多个同一类型 Bean 对象的时候,使用 @Autowired 去获取 Bean对象会出错。

@Component
public class UserBeans {
    @Bean
    public User user1(){
        User user = new User();
        user.setAge(20);
        user.setId(1);
        user.setName("张三");
        return user;
    }

    @Bean
    public User user2(){
        User user = new User();
        user.setAge(22);
        user.setId(11);
        user.setName("李四");
        return user;
    }
}
@Controller
public class UserController2 {
    @Autowired
    private User user;

    public void sayHi(){
        System.out.println("do UserController2");
        System.out.println(user.getName());
    }
}

public class App {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
    UserController2 userController2 = context.getBean("userController2",UserController2.class);
        userController2.sayHi();
    }
}

此时执行是会报错的,因为 @Autowired 注解先通过类型去查找,得到了 user1 和 user2 两个 Bean对象,但是根据 user 名称来去查找的话,是没有找到对应的 Bean 对象的,因此会报错。(查找 Bean 对象的默认名称为 添加 @Autowired 注解的对应属性名称,也就是上述第二段代码的private User user

@Autowired和@Resource注解之间的关系区别,Bean的作用域和生命周期,Spring的执行流程

 解决办法1:修改 @Autowired 注解的对应属性名称

@Controller
public class UserController2 {
    @Autowired
    private User user1;

    public void sayHi(){
        System.out.println("do UserController2");
        System.out.println(user1.getName());
    }
}

此时运行代码就会获取到对应的 Bean对象,也就是存储的 user1 对象。

@Autowired和@Resource注解之间的关系区别,Bean的作用域和生命周期,Spring的执行流程 

解决办法2:配合使⽤ @Qualifier 注解定义名称

@Qualifier(value = "Bean对象的名称") 

@Controller
public class UserController2 {
    @Autowired
    @Qualifier(value="user1")
    private User user;

    public void sayHi(){
        System.out.println("do UserController2");
        System.out.println(user.getName());
    }
}

也可以得到预期的结果。 

 @Autowired和@Resource注解之间的关系区别,Bean的作用域和生命周期,Spring的执行流程

解决办法3:使⽤ @Resource(name="Bean对象名称") 定义

@Controller
public class UserController2 {
    
    @Resource(name="user1")
    private User user;

    public void sayHi(){
        System.out.println("do UserController2");
        System.out.println(user.getName());
    }
}

 同样是可以得到预期结果的。

@Autowired和@Resource注解之间的关系区别,Bean的作用域和生命周期,Spring的执行流程 

二. Bean的作用域 

限定程序中变量的可⽤范围叫做作用域,或者说在源代码中定义变量的某个区域就叫做作用域。而 Bean 的作⽤域是指 Bean 在 Spring 整个框架中的某种行为模式。

1. singleton(单例模式)

singleton 表示的是单例作用域,类似于之前讲过的单例模式。这也是默认情况下的行为模式。在该作用域下的 Bean 在 IoC容器中只存在一个实例,获取到的 Bean 以及对 Bean 进行修改,都是针对同一个 Bean 对象。

代码演示: 

1. 往 Spring 容器中注入一个 User 对象 

@Component
public class UserBeans {
    @Bean
    public User user(){
        User user = new User();
        user.setId(1);
        user.setName("张三");
        return user;
    }
}

2.  通过@Autowired获取到Bean对象,并对其进行修改

@Controller
public class UserController {
    @Autowired
    private User user;

    public void printUser(){
        System.out.println(user);
        // 修改 User
        User myUser = user;     // 给引用对象赋值,其实就是共享对象!!!这两个变量指向了同一个地址
        myUser.setName("李四");
        System.out.println("myUser -> " + myUser);
        System.out.println("User -> " + user);  
    }
}

3. 再新建一个类,通过 @Autowired 获取到Bean对象 


@Controller
public class UserController2 {

    @Resource
    private User user;

    public void printUser2(){
        System.out.println("user -> " + user);  
        // Bean 作用域 -> 默认是单例模式 = 此 Bean 在整个框架(Spring 容器)中只有一份
    }
}

 4. 最后输出观察结果


public class App {
    public static void main(String[] args) {
        ApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");

        UserController userController = context.getBean("userController",UserController.class);
        userController.printUser();

        UserController2 userController2 = context.getBean("userController2",UserController2.class);
        userController2.printUser2();

    }
}

@Autowired和@Resource注解之间的关系区别,Bean的作用域和生命周期,Spring的执行流程

因此也可以得出结论:singleton 单例作用域,他们使用的 Bean 都是 Spring 容器中的同一个对象。这个 Bean 在整个 Spring 中只有一份,是全局共享的,当其他人修改了这个值之后,那么另一个人读到的就是被修改后的值了。

2. prototype(原型模式)(多例模式)

 在原型模式下,每次对该作用域下的 Bean 的请求都会创建新的实例,也就是说每次获取 Bean 对象和修改 Bean 对象都是针对新的 Bean 对象实例而言的。

需要添加注解 @Scope("prototype") 或者@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)

代码演示: 

@Component
public class UserBeans {
    @Bean
    @Scope("prototype")
    //@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public User user(){
        User user = new User();
        user.setId(1);
        user.setName("张三");
        return user;
    }
}

 再次运行得到结果:

@Autowired和@Resource注解之间的关系区别,Bean的作用域和生命周期,Spring的执行流程

可以看出,在第二次通过 @Autowired 获取到 Bean 对象的时候,得到的是一个新的实例对象了。

3. 请求作用域:request

 每次 http 请求会创建新的 Bean 实例。适用于⼀次 http 的请求和响应的共享 Bean 的情况。

 限定SpringMVC中使⽤。

4. 会话作用域:session

在⼀个http session中,定义⼀个 Bean 实例。每次 Session 会话共享一个 Bean 对象。限定SpringMVC中使⽤。

 文章来源地址https://www.toymoban.com/news/detail-439344.html

三. Spring 的执行流程

 @Autowired和@Resource注解之间的关系区别,Bean的作用域和生命周期,Spring的执行流程

@Autowired和@Resource注解之间的关系区别,Bean的作用域和生命周期,Spring的执行流程 

四. Bean 的生命周期 

 1. 实例化

给 Bean 对象分配内存空间。 

此处要注意:初始化不等于实例化!!!

类的初始化是完成程序前的准备工作,在这个阶段,静态的会被执行,同时会开辟一块存储空间用来存放静态的数据,初始化只在类加载的时候执行一次,也可以理解为给对象赋值的过程。

类的实例化,是指创建一个对象的过程,这个过程会在堆中开辟内存,将一些非静态的方法,变量存放在里面,在程序执行的过程中,可以创建多个对象,即多次实例化,每次实例化都会开辟一块新的内存。 

 2. 设置属性 

看需求,有的 Bean 对象需要被注入属性,这个属性也会是已经在 Spring 容器中的 Bean,如果该属性还不存在于 Spring 中,那么会先去将该属性 Bean 存储到 Spring 中。 

3. Bean 初始化  

   3.1 执行各种各种 Aware 通知; 

实现了各种 Aware 通知的⽅法,如 BeanNameAware、BeanFactoryAware、
ApplicationContextAware 的接⼝⽅法;

   3.2 执行初始化前置方法;

   3.3 执行初始化方法;

有两种方式,第一种是通过注解 @PostConstruct ,依赖注⼊操作之后执行注解修饰的方法;第二种是通过 xml 的方式,执行自己指定的 init-method ⽅法。如果两者都存在,那么先执行注解的初始化方法。

@Autowired和@Resource注解之间的关系区别,Bean的作用域和生命周期,Spring的执行流程

@Autowired和@Resource注解之间的关系区别,Bean的作用域和生命周期,Spring的执行流程

@Autowired和@Resource注解之间的关系区别,Bean的作用域和生命周期,Spring的执行流程 

   3.4 执行初始化后置方法; 

 

4. 使用 Bean 对象

通过 getBean() 方法来获取容器中的 Bean 对象并使用。 

5. 销毁 Bean 对象 

销毁容器的各种⽅法,如 @PreDestroy、DisposableBean 接⼝⽅法、destroy-method(XML的方式)。  

6. 代码演示 

public class App {
    public static void main(String[] args) {
// 此时要使用 ApplicationContext 的子类,因为它本身是没有销毁方法的
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        BeanComponent beanComponent = context.getBean("beanComponent",BeanComponent.class);
        beanComponent.sayHi();
        context.close();
    }
}

public class BeanComponent implements BeanNameAware {
    @Override
    public void setBeanName(String s) {
        System.out.println("执行了通知 BeanName -> " + s);
    }

    /**
     * xml 方式的初始化方法
     */
    public void myInit(){
        System.out.println("XML 方式初始化");
    }


    @PostConstruct
    public void doPostConstruct(){
        System.out.println("注解的初始化方法");
    }

    public void sayHi(){
        System.out.println("执行 sayHi()");
    }

    // 销毁的方法,销毁的时候执行的一个方法
    @PreDestroy
    public void doPreDestroy(){
        System.out.println("do PreDestroy");
    }
}

@Autowired和@Resource注解之间的关系区别,Bean的作用域和生命周期,Spring的执行流程

 @Autowired和@Resource注解之间的关系区别,Bean的作用域和生命周期,Spring的执行流程

 

到了这里,关于@Autowired和@Resource注解之间的关系区别,Bean的作用域和生命周期,Spring的执行流程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Bean作用域和生命周期

    hi,今天为大家带啦Bean的作用域和生命周期的相关知识 Bean的作用域和我们之前学过的不一样,我们之前学的作用域是一个范围,而现在指的是 Bean在Spring框架中的某种行为模式,也就是一个动作. 这样干巴巴的说看我可能无法理解,我们来举个例子 创建一个公共类的一个公共对象

    2024年02月15日
    浏览(47)
  • @Resource和@Autowired的区别

    @Resource和@Autowired这两个注解的作用都是在Spring生态里面去实现Bean的依赖注入 首先,@Autowired是Spring里面提供的一个注解,默认是根据类型来实现Bean的依赖注入。 @Autowired注解里面有一个required属性默认值是true,表示强制要求bean实例的注入,在应用启动的时候,如果IOC容器里

    2024年02月08日
    浏览(36)
  • Bean的作用域和生命周期

    目录 1.作⽤域定义 1.1Bean的6个作用域 1.singleton:单例作用域 2.prototype:多例作用域 3.request:请求作用域 4.session:会话作用域 5.application:全局作用域 6.websocket:HTTP WebSocket作用域 单例作⽤域(singleton) VS 全局作⽤域(application) 1.2设置作用域 1.直接设置值@Scope(\\\"potptype\\\") 2.用枚举设置:@Scop

    2024年02月02日
    浏览(81)
  • Spring(Bean 作用域和生命周期)

    目录 1. 案例1: Bean作用域的问题 2. 作用域 3. 设置 Bean 的作用域 4. Spring 的执行流程 5. Bean 的生命周期 现在有一个公共的 Bean,通过给 A 用户 和 B 用户使用, 然后在使用的过程中 A 偷偷的修改了公共 Bean 的数据, 导致 B 在使用时发生了预期之外的逻辑错误 (1) 公共 Bean:   [名称是

    2024年02月19日
    浏览(92)
  • Spring | Bean 作用域和生命周期

    Spring 是用来读取和存储 Bean,因此在 Spring 中 Bean 是最核心的操作资源,所以接下来我们深入学习⼀下 Bean 对象 假设现在有⼀个公共的 Bean,提供给 A 用户和 B 用户使用,然而在使用的途中 A 用户却 “悄悄” 地修改了公共 Bean 的数据,导致 B 用户在使用时发生了预期之外的逻

    2024年02月14日
    浏览(37)
  • @Autowired 和 @Resource 的区别是什么?

    Java面试题目录 @Autowired 和 @Resource 的区别是什么? @Autowired 是 Spring 提供的注解。默认的注入方式为byType(根据类型进行匹配)。 @Resource 是 JDK 提供的注解。默认注入方式为 byName(根据名称进行匹配)。 当一个接口存在多个实现类的情况下,@Autowired 和@Resource都需要通过名称

    2024年01月19日
    浏览(37)
  • 【Spring】Bean的作用域和生命周期

    目录 一、引入案例来探讨Bean的作用域 二、Bean的作用域 2.1、Bean的6种作用域 2.2、设置Bean的作用域 三、Spring的执行流程  四、Bean的声明周期 1、生命周期演示 首先我们创建一个User类,定义一个用户信息,在定义一个Users类,使用方法注解将user存入Spring中,然后两个用户A对这

    2024年02月14日
    浏览(38)
  • Spring Bean的作用域和生命周期

    Bean 的作用域指的是 Bean 在 Spring 容器中的行为(Bean 实例创建及生命周期),它的行为是由 Spring 来管理的,可以根据具体情况选择不同的作用域来达到性能优化、资源利用最大化和可维护性等目的。 Bean 作用域(Scope)类型主要有如下几种: 其中前两种是 Spring 核心作用域,

    2024年02月12日
    浏览(51)
  • 【JavaEE进阶】Bean 作用域和生命周期

    注意在此例子中需要用到lombok lombok是什么? Lombok 是一个 Java 库,它通过注解的方式来简化 Java 代码的编写。它提供了一组注解,让我们可以通过在代码中添加这些注解来自动生成样板式的代码,如 getter、setter、构造函数、toString 等。 使用 Lombok 可以有效地减少冗余的样板代

    2024年02月12日
    浏览(40)
  • 简述@Autowired和@Resource的区别(通俗易懂)

    前言:在日常的开发项目当中,这两个注解是经常会用到的,但是在实际使用当中好像使用起来并没有多大区别,这里我就对这两个注解进行一个详细的区别总结,通过一个完整的典型例子进行论证,思路清晰明了。 目录 一、结论 二、典型案例 2.1、准备代码 2.2、使用@A

    2024年02月03日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包