Spring注解驱动之关于@Bean注解指定初始化和销毁的方法

目录
  • bean的生命周期
  • 如何定义初始化、销毁方法
  • 初始化、销毁方法的使用场景
  • 初始化、销毁方法在Spring中的调用时机
  • 多实例bean初始化、销毁

bean的生命周期

通常意义上讲的bean的生命周期,指的是bean从创建到初始化,经过一系列的流程,最终销毁的过程。

只不过,在Spring中,bean的生命周期是由Spring容器来管理的。

在Spring中,我们可以自己来指定bean的初始化和销毁的方法。

我们指定了bean的初始化和销毁方法之后,当容器在bean进行到当前生命周期的阶段时,会自动调用我们自定义的初始化和销毁方法。

如何定义初始化、销毁方法

可以通过@Bean注解指定初始化、销毁方法。

如果使用XML配置文件的方式配置bean的话,那么可以在标签中指定bean的初始化和销毁方法,如下所示:

<bean id="person" class="com.meimeixia.bean.Person" init-method="init" destroy-method="destroy">
    <property name="age" value="18"></property>
    <property name="name" value="liayun"></property>
</bean>

这里需要注意的是,我们自己写的Person类中,需要存在init()方法和destroy()方法。而且Spring中还规定,这里的init()方法和destroy()方法必须是无参的,但可以抛出异常。

如果我们使用注解的方式,那么该如何实现指定bean的初始化和销毁方法呢?

首先创建一个名称为Car的类,这个类的实现比较简单,如下所示:

package com.meimeixia.bean;

public class Car {

	public Car() {
		System.out.println("car constructor...");
	}

	public void init() {
		System.out.println("car ... init...");
	}

	public void destroy() {
		System.out.println("car ... destroy...");
	}
}

然后将Car类对象通过注解的方式注册到Spring容器中。

package com.meimeixia.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.meimeixia.bean.Car;

@Configuration
public class MainConfigOfLifeCycle {

	@Bean
	public Car car() {
		return new Car();
	}
}

接着来写一个测试类

package com.meimeixia.test;

import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import com.meimeixia.config.MainConfigOfLifeCycle;

public class IOCTest_LifeCycle {

	@Test
	public void test01() {
		// 1. 创建IOC容器
		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);
		System.out.println("容器创建完成");
	}
}

对于单实例bean对象来说,在Spring容器创建完成后,就会对单实例bean进行实例化。

可以看到,在Spring容器创建完成时,会自动调用单实例bean的构造方法,对单实例bean进行了实例化操作。

总之,对应单实例bean来说,会在Spring容器启动的时候创建对象;对于多实例bean来说,会在多次获取bean的时候创建对象。

@Bean注解的initMethod和destroyMethod树形来指定bean的初始化方法和销毁方法。

所以我们在配置类的@Bean注解中指定initMethod属性和destroyMethod属性。

package com.meimeixia.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.meimeixia.bean.Car;

@Configuration
public class MainConfigOfLifeCycle {

	@Bean(initMethod="init", destroyMethod="destroy")
	public Car car() {
		return new Car();
	}
}

再次执行测试方法。

在输出结果中可以看出,在Spring容器中,先是调用了Car类的构造方法来创建Car对象,接下来便是调用了Car对象的init方法来进行初始化。

这里有个问题,在运行测试方法的时候没有打印出bean的销毁方法中的信息,那么什么时候执行bean的销毁方法呢?bean的销毁方法时在容器关闭的时候被调用的。

所以,在测试方法中添加关闭容器的代码(注意关闭的容器的方法ApplicationContext没有)。

package com.meimeixia.test;

import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import com.meimeixia.config.MainConfigOfLifeCycle;

public class IOCTest_LifeCycle {

	@Test
	public void test01() {
		// 1. 创建IOC容器
		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);
		System.out.println("容器创建完成");
		// 关闭容器
		applicationContext.close();
	}
}

再次运行测试方法。

可以看出,此时输出了对象的销毁方法中的信息,说明执行了对象的销毁方法。

初始化、销毁方法的使用场景

一个典型的场景就是对于数据源的管理。例如,在配置数据源时,在初始化的时候,会对很多的数据源的属性进行赋值操作;在销毁的时候,我们需要对数据源的连接等信息进行关闭和清理。这个时候,我们就可以在自定义的初始化和销毁方法中自定义操作逻辑。

初始化、销毁方法在Spring中的调用时机

你有没有想过这样一个问题,初始化方法和销毁方法是在什么时候被调用的呢?

bean对象的初始化方法调用的时机

对象创建完成,如果对象中存在一些属性,并且这些属性也都已经赋值了,那么就会调用bean的初始化方法。对于单实例bean来说,在Spring容器创建完成后,Spring容器会自动调用bean的初始化方法;对应多实例bean来说,在每次获取bean对象的时候,调用bean的初始化方法。

bean对象的销毁方法调用的时机:对于单实例bean来说,在容器关闭的时候,会调用bean的销毁方法;对于多实例bean来说,Spring容器只负责创建bean不会管理这些bean,也就不会自动调用这个bean的销毁方法了。小伙伴只能手动调用多实例bean的销毁方法了。

多实例bean初始化、销毁

在配置类上通过@Scope注解将Car对象设置成多实例bean。

package com.meimeixia.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;

import com.meimeixia.bean.Car;

@Configuration
public class MainConfigOfLifeCycle {

	@Scope("prototype")
	@Bean(initMethod="init", destroyMethod="destroy")
	public Car car() {
		return new Car();
	}
}

修改一下测试方法。

@Test
public void test01() {
	// 1. 创建IOC容器
	AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);
	System.out.println("容器创建完成");
}

运行测试方法。

可以看到,将Car对象设置成多实例bean,并且没有获取bean实例对象时,Spring容器并没有执行bean的构造方法、初始化方法和销毁方法。

如果我们在测试方法获取一下Car实例结果是什么样呢?

可以看到,结果信息中输出了构造方法和初始化方法中的信息。

当我们在获取多实例bean对象的时候,会创建对象并进行初始化,但是销毁方法时在什么时候被调用呢?是在容器关闭的时候么?我们现在来验证一下。

@Test
public void test01() {
	// 1. 创建IOC容器
	AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);
	System.out.println("容器创建完成");
	applicationContext.getBean("car"); // 多实例bean在获取的时候才创建对象
	// 关闭容器
	applicationContext.close();
}

可以看到,多实例的bean在容器关闭的时候是不会进行销毁的,也就是说你每次获取时,IOC容器帮你创建出对象交还给你,至于要什么时候销毁是你自己的事,Spring容器只负责创建多实例不再负责管理多实例bean了。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • SpringBoot @Configuration与@Bean注解使用介绍

    目录 demo示例 特点和特性 之前我们都是通过xml的方式定义bean,里面会写很多bean元素,然后spring启动的时候,就会读取bean xml配置文件,然后解析这些配置,然后会将这些bean注册到spring容器中,供使用者使用. Spring3.0开始,@Configuration用于定义配置类,定义的配置类可以替换xml文件,一般和@Bean注解联合使用. @Configuration注解可以加在类上,让这个类的功能等同于一个bean xml配置文件. @Bean注解类似于bean

  • Spring @Bean注解的使用场景与案例实现

    目录 一.简单介绍 二.注解说明 1. 注解源码 2. 注解使用场景 三.使用案例 1. 案例描述 2. 案例实现 新建注入到IOC容器中的User类 创建Spring的配置类BeanConfig 创建案例测试类BeanTest 3. 案例测试 一.简单介绍 翻看Spring的源码时,发现@Bean注解的源码上标注了Since: 3.0,也就是说,@Bean注解是Spring从3.0版本开始提供的源码.@Bean注解可以标注在方法上,将当前方法的返回值注入到IOC容器中,也可以标注到注解上,作为

  • Spring @Bean注解配置及使用方法解析

    使用说明 这个注解主要用在方法上,声明当前方法体中包含了最终产生 bean 实例的逻辑,方法的返回值是一个 Bean.这个 bean 会被 Spring 加入到容器中进行管理,默认情况下 bean 的命名就是使用了 bean 注解的方法名.@Bean 一般和 @Component 或者 @Configuration 一起使用. @Bean 显式声明了类与 bean 之间的对应关系,并且允许用户按照实际需要创建和配置 bean 实例. 该注解相当于: <bean id="useService

  • Spring注解@Configuration与@Bean注册组件的使用详解

    目录 原始Spring开发 Person.java pom.xml bean.xml PersonTest.java 注解Spring开发 原始Spring开发 Person.java 准备Person.java类: package com.jektong.spring; public class Person { private String name; private int age; public Person() { super(); } public Person(String nam

  • Spring @Bean vs @Service注解区别

    今天跟同事讨论了一下在Spring Boot中,是使用@Configuration和@Bean的组合来创建Bean还是直接使用 @Service等注解放在类上的方式.笔者倾向于使用第一种,即@Configuration和@Bean的组合. 先来看一个例子,目标是创建SearchService的一个Bean. 直接使用@Service的方式: // SearchService.java package li.koly.search; import java.util.List; public in

  • Spring注解开发@Bean和@ComponentScan使用案例

    组件注册 用@Bean来注册 搭建好maven web工程 pom加入spring-context,spring-core等核心依赖 创建实例类com.hjj.bean.Person, 生成getter,setter方法 public class Person { private String name; private int age; } 创建com.hjj.config.MainConfig @Configuration //告诉spring是一个配置类 public class Main

  • Springboot @Configuration @bean注解作用解析

    这篇文章主要介绍了springboot @Configuration @bean注解作用解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 @Configuration注解可以达到在Spring中使用xml配置文件的作用 @Bean就等同于xml配置文件中的<bean> 在spring项目中我们集成第三方的框架如shiro会在spring.xml配置文件中进行配置,例如: <!-- 配置shiro框架提供过滤器工厂 --> <

  • SpringBoot配置@Configuration注解和@bean注解

    目录 1.@Configuration注解 2.@bean注解 3.单实例 4.配置类也是容器的组件 5.直接调用配置类里面的person1()方法 6.proxyBeanMethods——代理bean的方法 1.@Configuration注解 用法:作用在类上面 作用:告诉SpringBoot这是一个配置类,相当于Spring中的xml配置文件. @Configuration //告诉SpringBoot这是一个配置类 == 配置文件 public class Config { } 2.@b

  • Spring初始化和销毁的实现方法

    这篇文章主要介绍了Spring初始化和销毁的实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一 指定初始化和销毁方法 通过@Bean指定init-method和destroy-method: @Bean(initMethod="init",destroyMethod="detory") public Car car(){ return new Car(); } 二 通过让Bean实现Initializing

  • 详解Spring注解驱动开发之属性赋值

    一.@Value注解 在Person的属性上使用@Value注解指定注入值 public class Person { @Value("#{20-2}") //SpEL表达式 #{} private Integer id; @Value("张三") //基本数据类型 private String name; } 配置类 @Configuration public class MainConfigOfPropertyValues { @Bean public Pers

  • Spring IOC容器Bean注解创建对象组件扫描

    目录 Spring IOC Bean注解对象组件扫描 一.spring 针对 bean 管理中创建对象提供注解 1. 引入依赖 2. 开启组件扫描 3. 创建类,并添加注解来创建对象 4. 测试一下 二.组件扫描的其他过滤条件 1. include-filter 2. exclude-filter Spring IOC Bean注解对象组件扫描 什么是注解? 注解是代码里的特殊标记,格式: @注解名称(属性名称=属性值, 属性名称2=属性值...) 可以作用在:类.方法.属性上面. 使用注解的目

  • Spring注解驱动之ApplicationListener异步处理事件说明

    目录 概述 示例 自定义事件多波器 测试用例 ApplicationListener异步执行源码分析 概述 之前我们讲过简单使用ApplicationListener发布事件,处理事件,但是发现是同一个线程发送事件并自己处理事件的. 下面我们就来说下如何使用自定义的线程池来异步处理接收的事件. 示例 实现一个ApplicationListener用于处理事件 package com.atguigu.ext; import org.springframework.context.Applicati

  • Spring如何使用注解的方式创建bean

    这篇文章主要介绍了Spring如何使用注解的方式创建bean,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 第一种使用配置类的方式 1.创建一个bean package com.springbean; public class Person { private String name; private Integer age ; public Person(String name, Integer age) { this.name = name

  • Java Spring详解如何配置数据源注解开发以及整合Junit

    目录 Spring数据源的配置 数据源(连接池)的作用 数据源的开发步骤 手动创建数据源 Spring注解开发 Spring原始注解 Spring新注解 Spring整合Junit Spring集成Junit步骤 Spring数据源的配置 数据源(连接池)的作用 数据源(连接池)是提高程序性能如出现的 事先实例化数据源,初始化部分连接资源 使用连接资源时从数据源中获取 使用完毕后将连接资源归还给数据源 常见的数据源(连接池):DBCP.C3PO.BoneCP.Druid等 数据源的开发步骤 1.

  • Spring框架中 @Autowired 和 @Resource 注解的区别

    Spring框架中 @Autowired 和 @Resource 注解的区别 在 spring 框架中,除了使用其特有的注解外,使用基于 JSR-250 的注解,它包括 @PostConstruct, @PreDestroy 和 @Resource 注释. 首先,咱们简单了解 @PostConstruct 和 @PreDestroy 注释: 为了定义一个 bean 的安装和卸载,我们可以使用 init-method 和 destroy-method 参数简单的声明一下 ,其中 init-meth

  • spring整合redis缓存并以注解(@Cacheable、@CachePut、@CacheEvict)形式使用

    maven项目中在pom.xml中依赖2个jar包,其他的spring的jar包省略: <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.8.1</version> </dependency> <dependency> <groupId>org.springfra

随机推荐