SpringBoot_生命周期_三种初始化方式

Bean的初始化和销毁

  • 测试三种方式初始化bean
    • 实现InitializingBean接口
    • @Bean(initMethod = “init”, destroyMethod = “destroy”) 指定方法
    • 成员方法使用 @PostConstruct @PreDestroy 注解实现

Java配置方式

package com.myron.springboot.study.beanlife.service;

public class BeanWayService {

    public BeanWayService() {
        System.out.println("BeanWayService--new BeanWayService()");
    }

    public void init() {
        System.out.println("BeanWayService--init--@Bean(initMethod=)");
    }

    public void destroy() {
        System.out.println("BeanWayService--destroy--@Bean(destroyMethod=)");
    }
}

注解方式

package com.myron.springboot.study.beanlife.service;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

public class AnnotationWayService {

    public AnnotationWayService() {
        System.out.println("AnnotationWayService--new AnnotationWayService()");
    }

    @PostConstruct
    public void init() {
        System.out.println("AnnotationWayService--init--init() use @PostConstruct");
    }

    @PreDestroy
    public void destroy() {
        System.out.println("AnnotationWayService--destroy--destroy() use @PreDestroy");
    }
}

InitializingBean接口方式

package com.myron.springboot.study.beanlife.service;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;

public class InterfaceWayService implements InitializingBean, DisposableBean {

    public InterfaceWayService() {
        System.out.println("InterfaceWayService--new InterfaceWayService()");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("InterfaceWayService--InitializingBean");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("InterfaceWayService--DisposableBean");
    }
}

配置三种方式Config

package com.myron.springboot.study.beanlife.config;

import com.myron.springboot.study.beanlife.service.AnnotationWayService;
import com.myron.springboot.study.beanlife.service.BeanWayService;
import com.myron.springboot.study.beanlife.service.InterfaceWayService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class BeanLifeConfig {

    // 实现InitializingBean接口
    @Bean
    public InterfaceWayService interfaceWayService() {
        return new InterfaceWayService();
    }

    // java @bean配置 指定方法实现(等效于xml配置的init-method和destroy-method)
    @Bean(initMethod = "init", destroyMethod = "destroy")
    public BeanWayService beanWayService() {
        return new BeanWayService();
    }

    // 方法使用 @PostConstruct @PreDestroy 注解实现
    @Bean
    public AnnotationWayService annotationWayService() {
        return new AnnotationWayService();
    }
}

运行测试

package com.myron.springboot.study.beanlife;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class BeanLifeApplication {
    public static void main(String[] args) {
        System.out.println("-----------容器启动----------------------");
        SpringApplication.run(BeanLifeApplication.class, args);
        System.out.println("bean初始化顺序: 实例化对象[构造方法] --> 属性分配[依赖注入] --> 初始化[@PostConstruct/InitializingBean/@Bean(initMethod)]");
        System.out.println("-----------容器关闭----------------------");
    }
}

效果

在这里插入图片描述

搞个事情, 如果一个bean同时使用三种方式初始化bean,会怎么样呢
在这里插入图片描述

测试结果: 执行顺序@PostConstruct注解 -> InitializingBean接口 -> @Bean(initMethod)指定配置

补充

三种初始化和销毁方式,实际开发中怎么选呢

平常业务开发时候,不推荐InitializingBean和 DisposableBean接口。最好用另外两种

Spring 官方文档是这样说的

We recommend that you do not use the InitializingBean interface, because it unnecessarily couples the code to Spring. Alternatively, we suggest using the @PostConstruct annotation or specifying a POJO initialization method. (我们建议您不要使用 InitializingBean回调接口,因为它不必要地将代码耦合到 Spring。另外,我们建议使用@PostConstruct注解或指定bean定义支持的通用方法。)

InitializingBean 使用场景示例

发生时机,实例化对象[构造方法],属性分配[依赖注入] ,之后再到初始化,可以做一些定制化操作

场景1: RedisTeplate可选插件的默认初始化设置

如果没有配置自定义的序列化器, 使用默认的序列化器。

public class RedisTemplate<K, V> extends RedisAccessor implements RedisOperations<K, V>, BeanClassLoaderAware {
    private boolean enableTransactionSupport = false;
    private boolean exposeConnection = false;
    private boolean initialized = false;
    private boolean enableDefaultSerializer = true;
    @Nullable
    private RedisSerializer<?> defaultSerializer;
    @Nullable
    private ClassLoader classLoader;
    @Nullable
    private RedisSerializer keySerializer = null;
    @Nullable
    private RedisSerializer valueSerializer = null;
    @Nullable
    private RedisSerializer hashKeySerializer = null;
    @Nullable
    private RedisSerializer hashValueSerializer = null;
    private RedisSerializer<String> stringSerializer = RedisSerializer.string();
    @Nullable
    private ScriptExecutor<K> scriptExecutor;
    private final ValueOperations<K, V> valueOps = new DefaultValueOperations(this);
    private final ListOperations<K, V> listOps = new DefaultListOperations(this);
    private final SetOperations<K, V> setOps = new DefaultSetOperations(this);
    private final ZSetOperations<K, V> zSetOps = new DefaultZSetOperations(this);
    private final GeoOperations<K, V> geoOps = new DefaultGeoOperations(this);
    private final HyperLogLogOperations<K, V> hllOps = new DefaultHyperLogLogOperations(this);
    private final ClusterOperations<K, V> clusterOps = new DefaultClusterOperations(this);

    public RedisTemplate() {
    }

    public void afterPropertiesSet() {
        super.afterPropertiesSet();
        boolean defaultUsed = false;
        if (this.defaultSerializer == null) {
            this.defaultSerializer = new JdkSerializationRedisSerializer(this.classLoader != null ? this.classLoader : this.getClass().getClassLoader());
        }

        if (this.enableDefaultSerializer) {
            if (this.keySerializer == null) {
                this.keySerializer = this.defaultSerializer;
                defaultUsed = true;
            }

            if (this.valueSerializer == null) {
                this.valueSerializer = this.defaultSerializer;
                defaultUsed = true;
            }

            if (this.hashKeySerializer == null) {
                this.hashKeySerializer = this.defaultSerializer;
                defaultUsed = true;
            }

            if (this.hashValueSerializer == null) {
                this.hashValueSerializer = this.defaultSerializer;
                defaultUsed = true;
            }
        }

        if (this.enableDefaultSerializer && defaultUsed) {
            Assert.notNull(this.defaultSerializer, "default serializer null and not all serializers initialized");
        }

        if (this.scriptExecutor == null) {
            this.scriptExecutor = new DefaultScriptExecutor(this);
        }

        this.initialized = true;
    }
}
  • 为什么不直接在构造方法或在属性定义时候直接初始化?(个人理解)
    • 好处: 不仅可以让本类,指定自定义序列化方式, 同时子类可以很方便的修改选择默认的自定义序列化方式。比直接在构造方法中写,直观一些,也可以补充校验逻辑, 保证template类良好的扩展性。

参考阅读

  1. @PostConstruct
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值