Spring加载后初始化的9种方式

本文来聊一下在spring中,当spring 容器启动后,我们有几种初始化操作的方式。

目录

Spring加载后初始化的几种方式

@Component和@Service加构造方法

ContextRefreshedEvent事件

代码如下:

输出结果:

PostConstruct 注解

代码如下:

输出结果:

InitializingBean

代码如下:

输出结果:

init-method方法

代码如下:

输出结果:

实现 SmartInitializingSingleton 接口

代码如下:

输出结果:

重写 onRefresh()方法

CommandLineRunner(仅限Spring Boot)

代码如下:

输出结果:

SpringApplicationRunListener(仅限Spring boot)

代码如下:

输出结果:

总结:


Spring加载后初始化的几种方式

  1. @component和@service 加构造方法

  2. ContextRefreshedEvent事件

  3. PostConstruct 注解

  4. InitializingBean

  5. init-method方法

  6. 实现 SmartInitializingSingleton 接口

  7. 重写 onRefresh()方法

  8. CommandLineRunner(仅限Spring Boot)

  9. SpringApplicationRunListener(仅限Spring boot)

在spring 容器中有一个 Persion对象名字叫张三,需要在spring容器启动后调用它的run方法。代码如下


import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
​
@Configuration
public class PersonConfig {
​
    @Bean
    public Person person(){
        Person person = new Person();
        person.setName("张三");
        person.setAge(18);
        return person;
    }
}
​

@Component和@Service加构造方法

import org.springframework.stereotype.Component;
​
@Component
//@Service
public class PersonConfig {
​
    private Person person;
​
    public PersonConfig() {
        person = new Person();
        person.setName("张三");
        person.setAge(18);
    }
}

ContextRefreshedEvent事件

ContextRefreshedEvent:是Spring容器初始化完成后调用的事件。 ContextRefreshedEvent的父类是ApplicationContextEvent,是一个事件。所以我们通过ApplicationListener来实现。

代码如下:

import com.example.springbootdemo.bean.Person;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
​
@Component
public class PersonAfterListener implements ApplicationListener<ContextRefreshedEvent> {
    @Autowired
    private Person person;
​
    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        person.run("ContextRefreshedEvent");
    }
}
​

输出结果:

输出结果

PostConstruct 注解

PostConstruct注解修饰的方式,是在spring容器启动时运行的。优先级大于ContextRefreshedEvent事件。

代码如下:

import com.example.springbootdemo.bean.Person;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
​
import javax.annotation.PostConstruct;
​
@Component
public class PersonAfterPostConstruct {
    @Autowired
    private Person person;
​
    @PostConstruct
    public void postConstruct(){
        person.run("PostConstruct");
    }
}
​

输出结果:

输出结果 由此可见,PostConstruct优先级大于ContextRefreshedEvent事件。

InitializingBean

InitializingBean是spring容器在启动并初始化好内部示例后调用的,用来最终为总体bean添加最后属性和操作。 官方原话:This method allows the bean instance to perform validation of its overall configuration and final initialization when all bean properties have been set.

代码如下:

import com.example.springbootdemo.bean.Person;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
​
@Component
public class PersonAfterInitializingBean implements InitializingBean {
    @Autowired
    private Person person;
​
    @Override
    public void afterPropertiesSet() throws Exception {
        person.run("InitializingBean");
    }
}
​

输出结果:

输出结果

init-method方法

这种方法有一定的局限性,并且可能会覆盖曾经的init操作,需要慎用。

Bean在加载到Spring容器中时需要先将Bean的定义信息抽象为BeanDefinition,其中有一个属性init-method代表将来Bean初始化时要调用的方法。

我们通过BeanFactoryPostProcessor来注入init-method方法,并且该方法必须是没有参数的

代码如下:

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;
​
@Component
public class PersonAfterInit implements BeanFactoryPostProcessor {
​
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        BeanDefinition person = beanFactory.getBeanDefinition("person");
        person.setInitMethodName("run");
    }
}
​

输出结果:

输出结果

实现 SmartInitializingSingleton 接口

SmartInitializingSingleton是Bean容器在初始化所有非懒加载的单例Bean后调用的方法。

代码如下:

import com.example.springbootdemo.bean.Person;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
​
@Component
public class PersonAfterSmartInitializingSingleton implements SmartInitializingSingleton {
    @Autowired
    private Person person;
​
    @Override
    public void afterSingletonsInstantiated() {
        person.run("SmartInitializingSingleton");
    }
}
​

输出结果:

输出结果

重写 onRefresh()方法

这个我实在是不会,但我不藏着掖着,告诉你也能实现。

CommandLineRunner(仅限Spring Boot)

CommandLineRunner 是一个Spring boot 接口,在应用初始化后执行,且仅会执行一次。可以用来打印项目中配置文件的参数,方便排查问题。

代码如下:

import com.example.springbootdemo.bean.Person;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
​
@Component
public class PersonAfterCommandLineRunner implements CommandLineRunner {
    @Autowired
    private Person person;
​
    @Override
    public void run(String... args) throws Exception {
        person.run("CommandLineRunner");
    }
}
​

输出结果:

输出结果

SpringApplicationRunListener(仅限Spring boot)

SpringBoot的生命周期事件监听方法,需要搭配resource/META-INF/spring.factories 文件使用。

代码如下:

JAVA代码:

import com.example.springbootdemo.bean.Person;
import org.springframework.boot.ConfigurableBootstrapContext;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringApplicationRunListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
​
import java.time.Duration;
​
​
public class PersonAfterSpringApplicationRunListener implements SpringApplicationRunListener {
    private final SpringApplication application;
    private final String[] args;
​
    public PersonAfterSpringApplicationRunListener(SpringApplication application, String[] args) {
        this.application = application;
        this.args = args;
    }
​
    @Override
    public void starting(ConfigurableBootstrapContext bootstrapContext) {
        /*
         * Person has not been registered
         */
//        Person person = bootstrapContext.get(Person.class);
//        person.run("SpringApplicationRunListener:starting");
    }
​
    @Override
    public void environmentPrepared(ConfigurableBootstrapContext bootstrapContext, ConfigurableEnvironment environment) {
        /*
         * Person has not been registered
         */
//        Person person = bootstrapContext.get(Person.class);
//        person.run("SpringApplicationRunListener:environmentPrepared");
    }
​
    @Override
    public void contextPrepared(ConfigurableApplicationContext context) {
        /*
         * Person has not been registered
         */
//        Person person = context.getBean(Person.class);
//        person.run("SpringApplicationRunListener:contextPrepared");
    }
​
    @Override
    public void contextLoaded(ConfigurableApplicationContext context) {
        /*
         * Person has not been registered
         */
//        Person person = context.getBean(Person.class);
//        person.run("SpringApplicationRunListener:contextLoaded");
    }
​
    @Override
    public void started(ConfigurableApplicationContext context, Duration timeTaken) {
        Person person = context.getBean(Person.class);
        person.run("SpringApplicationRunListener:started");
    }
​
    @Override
    public void ready(ConfigurableApplicationContext context, Duration timeTaken) {
        Person person = context.getBean(Person.class);
        person.run("SpringApplicationRunListener:ready");
    }
​
    @Override
    public void failed(ConfigurableApplicationContext context, Throwable exception) {
        Person person = context.getBean(Person.class);
        person.run("SpringApplicationRunListener:failed");
    }
}
​

spring.factories

    org.springframework.boot.SpringApplicationRunListener=com.example.springbootdemo.impl.PersonAfterSpringApplicationRunListener

输出结果:

输出结果

总结:

执行优先级:init-Method >> InitializingBean >> PostConstruct >> SmartInitializingSingleton >> ContextRefreshedEvent >> SpringApplicationRunListener:started >> CommandLineRunner >> SpringApplicationRunListener:ready

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring框架中,Spring上下文(ApplicationContext)是一个负责管理Bean生命周期和提供依赖注入的容器。Spring上下文初始化指的是Spring容器在启动时进行的一系列操作,包括加载配置文件、解析Bean定义、创建和初始化Bean等。 Spring上下文的初始化过程主要包括以下几个步骤: 1. 加载配置文件:Spring容器会读取配置文件,可以是XML格式的配置文件(如applicationContext.xml)或基于注解的配置类(如@Configuration注解的类)。 2. 解析Bean定义:在加载配置文件后,Spring容器会解析配置文件或配置类中定义的Bean信息。它会识别和解析Bean的定义、依赖关系、作用域等元数据,并将其存储在内部数据结构中。 3. 创建和初始化Bean:在解析完Bean定义后,Spring容器会根据定义的信息创建和初始化Bean。这包括实例化Bean对象、设置属性值、调用初始化方法等。 4. 注册Bean到容器:创建和初始化的Bean会被注册到Spring容器中,以便其他部分可以通过依赖注入或其他方式获取并使用这些Bean。 5. 执行其他初始化逻辑:除了创建和初始化Bean外,Spring容器还可能执行其他初始化逻辑,如加载资源文件、注册事件监听器、处理AOP代理等。 6. 完成初始化:当所有的Bean都被创建和初始化后,Spring上下文初始化过程完成,容器处于可用状态,可以提供Bean的依赖注入和其他功能。 Spring上下文的初始化过程由Spring框架自动完成,开发者无需显式调用。通常,当应用程序启动时,会通过启动类或配置文件指定要使用的Spring上下文,并由框架负责初始化和管理容器。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值