spring IOC及Bean作用域和生命周期

  • Post author:
  • Post category:其他



目录


1.什么是spring IOC?


2.IOC/DI的理解


3.Bean作用域


4.Bean生命周期


5.上篇文章遗漏总结



1.什么是spring IOC?

spring容器主要是对IOC设计模式的实现。主要是使用容器来

统一管理

Bean对象,及管理对象之间的

依赖关系。

在Spring中,我们基本不需要 new 一个类,这些都是让 Spring 去做的。Spring 启动时会把所需的类实例化成对象,如果需要依赖,则先实例化依赖,然后实例化当前类。因为依赖必须通过构建函数传入,所以实例化时,当前类就会接收并保存所有依赖的对象。

这一步也就是所谓的


依赖注入


在 Spring 中,类的实例化、依赖的实例化、依赖的传入都交由 Spring Bean 容器控制,而不是用new方式实例化对象、通过非构造函数方法传入依赖等常规方式。实质的控制权已经交由程序管理,而不是程序员管理,所以叫做


控制反转




Spring提供了一个容器,称为IOC容器,用来充当IOC思想中的


外部



IOC容器负责对象的创建、初始化等一系列工作,被创建或被管理的对象在IOC容器中统称为


Bean



2.IOC/DI的理解

IoC 是 Inversion of Control 的缩写,翻译成中文是“控制反转”的意思,

它不是一个具体的技术,而是一个实现对象解耦的思想。

要解释什么是解耦?就要了解什么是耦合,所谓的**耦合是指:两个或两个以上对象存在依赖,当一方修改之后会影响另一方,那么就说这些对象间存在耦合。**而解耦就是解除两个或两个以上对象,修改之后影响另一方的问题。

DI 是 Dependency Injection 的缩写,翻译成中文是“依赖注入”的意思。

依赖注入不是一种设计实现,而是一种具体的技术

,它是

在 IoC 容器运行期间,动态地将某个依赖对象注入到当前对象的技术就叫做 DI(依赖注入)

举个例子:A 类在使用 B 类时,就是通过构造方法将依赖对象 B 引入的,这种实现方法就可以看作是

通过构造方法

实现依赖注入的手段,具体代码如下

class A {
    // 先定义一个需要依赖的 B 对象
    private B b;
    // 通过构造方法实现赋值
    public A(B b) {
        this.b = b;
    }
    public void init() {
        // 调用 B 类中的 init 方法
        b.init();
    }
}

从上面的内容中我们可以看出,IoC 和 DI 虽然定义不同,但它们所做的事情都是一样的,都是用来实现对象解耦的,而二者又有所不同:

IoC 是一种设计思想,而 DI 是一种具体的实现技术

给大家举个例子很快就可以更清晰:比如博主今天心情比较好,下午想出去吃一顿大餐,那么“想吃一顿大餐”就是一种思想,就是

IOC

但什么样的大餐才是好吃的呢?羊肉火锅还是烧烤啤酒?具体吃什么是

DI


因此“博主今天心情比较好,想出去吃大餐”是一种思想、是 IOC,而吃一顿火锅而非烧烤就是具体的实现、是 DI。


3.Bean作用域


Bean 的作用域是指 Bean 在 Spring 整个框架中的某种行为模式。比如 singleton 单例作用域,就表示 Bean 在整个 Spring 中只有一份,它是全局共享的,当有人修改了这个值之后,那么另一个人读取到的就是被修改后的值

。 举个例子,比如我们在 Spring 中定义了一个单例的 Bean 对象 user(默认作用域为单例),具体实现代码如下:

@Component
public class UserBean {
    @Bean
    public User user() {
        User user = new User();
        user.setId(1);
        user.setName("Java"); // 此行为重点:用户名称为 Java
        return user;
    }
}

然后,在 A 类中使用并修改了 user 对象,具体实现代码如下:

@Controller
public class AController {
    @Autowired
    private User user;
    public User getUser() {
        User user = user;
        user.setName("MySQL"); // 此行为重点:将 user 名称修改了
        return user;
    }
}

最后,在 B 类中也使用了 user 对象,具体实现代码如下:

@Controller
public class BController {
    @Autowired
    private User user;
    public User getUser() {
        User user = user;
        return user;
    }
}

此时我们访问 B 对象中的 getUser 方法,就会发现此时的用户名为 A 类中修改的“MySQL”,而非原来的“Java”,这就说明 Bean 对象 user 默认就是单例的作用域。如果有任何地方修改了这个单例对象,那么其他类再调用就会得到一个修改后的值。

—————–作用域分类————————————————————-

在 Spring 中,Bean 的常见作用域有以下 5 种:

  1. singleton:单例作用域;
  2. prototype:原型作用域(多例作用域);
  3. request:请求作用域;
  4. session:会话作用域;
  5. application:全局作用域。


注意:后 3 种作用域,只适用于 Spring MVC 框架。

singleton:该作用域下的 Bean 在 IoC 容器中只存在一个实例:获取 Bean(即通过 applicationContext.getBean等方法获取)及装配 Bean(即通过 @Autowired 注入)都是同一个对象。

prototype:每次对该作用域下的 Bean 的请求都会创建新的实例:获取 Bean(即通过 applicationContext.getBean 等方法获取)及装配 Bean(即通过 @Autowired 注入)都是新的对象实例。

request:每次 Http 请求会创建新的 Bean 实例,类似于 prototype。

session:在一个 Http Session 中,定义一个 Bean 实例。

application:在一个 Http Servlet Context 中,定义一个 Bean 实例。


4.Bean生命周期


Spring 中 Bean 的生命周期是指:Bean 在 Spring(IoC)中从创建到销毁的整个过程。

Spring 中 Bean 的生命周期主要包含以下 5 部分:

  1. 实例化:为 Bean 分配内存空间;
  2. 设置属性:将当前类依赖的 Bean 属性,进行注入和装配;
  3. 初始化:

    1. 执行初始化的前置方法;
    2. 执行初始化方法;
    3. 执行初始化的后置方法。
  4. 使用 Bean:在程序中使用 Bean 对象;
  5. 销毁 Bean:将 Bean 对象进行销毁操作。

以上生命周期中,需要注意的是:

“实例化”和“初始化”是两个完全不同的过程,实例化只是给 Bean 分配了内存空间,而初始化则是将程序的执行权,从系统级别转换到用户级别,并开始执行用户添加的业务代码


5.上篇文章遗漏总结

1.@Autowired 和 @Resource 注解的区别

(1)@Autowired是spring框架提供的注解,而@Resource是JDK提供的注解

(2)@Autowired必须在spring框架中使用,否则会报错。而@Resource可以不在spring框架中使用

(3)显示指定引用某个Bean,使用方式不同:@Resource(name=“xxx”),@Autowired 结合@Qualifier

2.同一个类型的Bean,如何正确的注入到某个属性



版权声明:本文为qq_53679373原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。