浩泽学编程:个人主页

  推荐专栏:《深入浅出SpringBoot》《java项目分享》              《RabbitMQ》《Spring》《SpringMVC》

学无止境,不骄不躁,知行合一

文章目录

前言一、@Bean注解指定初始化和销毁方法二、实现InitializingBean接口和DisposableBean接口三、@PostConstruct(初始化逻辑)和@PreDestroy(销毁逻辑)注解四、BeanPostProcessor接口总结

前言

上篇文章详细讲诉了Bean的生命周期和作用域,在生命周期中提到了如何自定义初始化Bean,可能很多人不知道如何自定义初始化,这里详细补充讲解一下:使用@Bean注解指定初始化和销毁方法、实现InitializingBean接口和DisposableBean接口自定义初始化和销毁、@PostConstruct(初始化逻辑)和@PreDestroy(销毁逻辑)注解、使用BeanPostProcessor接口。

一、@Bean注解指定初始化和销毁方法

创建BeanTest类,自定义初始化方法和销毁方法。在@Bean注解的参数中指定BeanTest自定义的初始化和销毁方法:销毁方法只有在IOC容器关闭的时候才调用。

代码如下:

/**

* @Version: 1.0.0

* @Author: Dragon_王

* @ClassName: dog

* @Description: TODO描述

* @Date: 2024/1/21 22:55

*/

public class BeanTest {

public BeanTest(){

System.out.println("BeanTest被创建");

}

public void init(){

System.out.println("BeanTest被初始化");

}

public void destory(){

System.out.println("BeanTest被销毁");

}

}

/**

* @Version: 1.0.0

* @Author: Dragon_王

* @ClassName: MyConfig

* @Description: TODO描述

* @Date: 2024/1/21 22:59

*/

@Configuration

@ComponentScan(("com.dragon.restart1"))

public class MyConfig {

@Bean(initMethod = "init",destroyMethod = "destory")

public BeanTest beanTest(){

return new BeanTest();

}

}

//测试代码

AnnotationConfigApplicationContext ct = new AnnotationConfigApplicationContext(MyConfig.class);

System.out.println("IoC容器创建完成");

可以看到调用的是自定义的方法,这里解释一下,测试时,运行完代码块程序就结束了,所哟IoC容器就被关闭,所以调用了IoC销毁方法。同时可以看到初始化方法在对象创建完成后调用。当组件的作用域为单例时在容器启动时即创建对象,而当作用域为原型(PROTOTYPE)时在每次获取对象的时候才创建对象。并且当作用域为原型(PROTOTYPE)时,IOC容器只负责创建Bean但不会管理Bean,所以IOC容器不会调用销毁方法。

二、实现InitializingBean接口和DisposableBean接口

看一下两接口的方法:

public interface InitializingBean {

/**

* Invoked by the containing {@code BeanFactory} after it has set all bean properties

* and satisfied {@link BeanFactoryAware}, {@code ApplicationContextAware} etc.

*

This method allows the bean instance to perform validation of its overall

* configuration and final initialization when all bean properties have been set.

* @throws Exception in the event of misconfiguration (such as failure to set an

* essential property) or if initialization fails for any other reason

* Bean都装配完成后执行初始化

*/

void afterPropertiesSet() throws Exception;

}

====================================================================

public interface DisposableBean {

/**

* Invoked by the containing {@code BeanFactory} on destruction of a bean.

* @throws Exception in case of shutdown errors. Exceptions will get logged

* but not rethrown to allow other beans to release their resources as well.

*/

void destroy() throws Exception;

}

代码如下:

/**

* @Version: 1.0.0

* @Author: Dragon_王

* @ClassName: BeanTest1

* @Description: TODO描述

* @Date: 2024/1/21 23:25

*/

public class BeanTest1 implements InitializingBean, DisposableBean {

@Override

public void destroy() throws Exception {

System.out.println("BeanTest1销毁");

}

@Override

public void afterPropertiesSet() throws Exception {

System.out.println("BeanTest1初始化");

}

public BeanTest1() {

System.out.println("BeanTest1被创建");

}

}

=========================

@Configuration

@ComponentScan(("com.dragon.restart1"))

public class MyConfig {

@Bean

public BeanTest1 beanTest1(){

return new BeanTest1();

}

}

三、@PostConstruct(初始化逻辑)和@PreDestroy(销毁逻辑)注解

被@PostConstruct修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器调用一次,类似于Serclet的inti()方法。被@PostConstruct修饰的方法会在构造函数之后,init()方法之前运行。被@PreDestroy修饰的方法会在服务器卸载Servlet的时候运行,并且只会被服务器调用一次,类似于Servlet的destroy()方法。被@PreDestroy修饰的方法会在destroy()方法之后运行,在Servlet被彻底卸载之前。

代码如下:

/**

* @Version: 1.0.0

* @Author: Dragon_王

* @ClassName: BeanTest2

* @Description: TODO描述

* @Date: 2024/1/21 23:32

*/

public class BeanTest2 {

public BeanTest2(){

System.out.println("BeanTest2被创建");

}

@PostConstruct

public void init(){

System.out.println("BeanTest2被初始化");

}

@PreDestroy

public void destory(){

System.out.println("BeanTest2被销毁");

}

}

========================

//

@Configuration

@ComponentScan(("com.dragon.restart1"))

public class MyConfig {

@Bean

public BeanTest2 beanTest2(){

return new BeanTest2();

}

}

四、BeanPostProcessor接口

BeanPostProcessor又叫Bean的后置处理器,是Spring框架中IOC容器提供的一个扩展接口,在Bean初始化的前后进行一些处理工作。

BeanPostProcessor的源码如下:

public interface BeanPostProcessor {

/**

* Apply this BeanPostProcessor to the given new bean instance before any bean

* initialization callbacks (like InitializingBean's {@code afterPropertiesSet}

* or a custom init-method). The bean will already be populated with property values.

* The returned bean instance may be a wrapper around the original.

*

The default implementation returns the given {@code bean} as-is.

* @param bean the new bean instance

* @param beanName the name of the bean

* @return the bean instance to use, either the original or a wrapped one;

* if {@code null}, no subsequent BeanPostProcessors will be invoked

* @throws org.springframework.beans.BeansException in case of errors

* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet

*/

@Nullable

//bean初始化方法调用前被调用

default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {

return bean;

}

/**

* Apply this BeanPostProcessor to the given new bean instance after any bean

* initialization callbacks (like InitializingBean's {@code afterPropertiesSet}

* or a custom init-method). The bean will already be populated with property values.

* The returned bean instance may be a wrapper around the original.

*

In case of a FactoryBean, this callback will be invoked for both the FactoryBean

* instance and the objects created by the FactoryBean (as of Spring 2.0). The

* post-processor can decide whether to apply to either the FactoryBean or created

* objects or both through corresponding {@code bean instanceof FactoryBean} checks.

*

This callback will also be invoked after a short-circuiting triggered by a

* {@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation} method,

* in contrast to all other BeanPostProcessor callbacks.

*

The default implementation returns the given {@code bean} as-is.

* @param bean the new bean instance

* @param beanName the name of the bean

* @return the bean instance to use, either the original or a wrapped one;

* if {@code null}, no subsequent BeanPostProcessors will be invoked

* @throws org.springframework.beans.BeansException in case of errors

* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet

* @see org.springframework.beans.factory.FactoryBean

*/

@Nullable

//bean初始化方法调用后被调用

default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

return bean;

}

代码如下:

/**

* @Version: 1.0.0

* @Author: Dragon_王

* @ClassName: MyBeanPostProcess

* @Description: TODO描述

* @Date: 2024/1/21 23:40

*/

@Component

public class MyBeanPostProcess implements BeanPostProcessor {

@Override

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {

System.out.println("postProcessBeforeInitialization..."+beanName+"=>"+bean);

return bean;

}

@Override

public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

System.out.println("postProcessAfterInitialization..."+beanName+"=>"+bean);

return bean;

}

}

============================

@Configuration

@ComponentScan(("com.dragon.restart1"))

public class MyConfig {

@Bean

public BeanTest1 beanTest1(){

return new BeanTest1();

}

@Bean

public BeanTest2 beanTest2(){

return new BeanTest2();

}

}

运行结果如下:

BeanTest1被创建

postProcessBeforeInitialization...beanTest1=>com.dragon.restart1.BeanTest1@111d5c97

BeanTest1初始化

postProcessAfterInitialization...beanTest1=>com.dragon.restart1.BeanTest1@111d5c97

BeanTest2被创建

postProcessBeforeInitialization...beanTest2=>com.dragon.restart1.BeanTest2@29c17c3d

BeanTest2被初始化

postProcessAfterInitialization...beanTest2=>com.dragon.restart1.BeanTest2@29c17c3d

IoC容器创建完成

BeanTest2被销毁

BeanTest1销毁

通过上述运行结果可以发现使用BeanPostProcessor的运行顺序为: IOC容器实例化Bean---->调用BeanPostProcessor的postProcessBeforeInitialization方法---->调用bean实例的初始化方法---->调用BeanPostProcessor的postProcessAfterInitialization方法。

总结

以上就是Bean生命周期自定义初始化和销毁的讲解。

精彩文章

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: