spring ApplicationContextInitializer接口

看源码

package org.springframework.context;

/**
 * Callback interface for initializing a Spring {@link ConfigurableApplicationContext}
 * prior to being {@linkplain ConfigurableApplicationContext#refresh() refreshed}.
 *
 * <p>Typically used within web applications that require some programmatic initialization
 * of the application context. For example, registering property sources or activating
 * profiles against the {@linkplain ConfigurableApplicationContext#getEnvironment()
 * context's environment}. See {@code ContextLoader} and {@code FrameworkServlet} support
 * for declaring a "contextInitializerClasses" context-param and init-param, respectively.
 *
 * <p>{@code ApplicationContextInitializer} processors are encouraged to detect
 * whether Spring's {@link org.springframework.core.Ordered Ordered} interface has been
 * implemented or if the @{@link org.springframework.core.annotation.Order Order}
 * annotation is present and to sort instances accordingly if so prior to invocation.
 *
 * @author Chris Beams
 * @since 3.1
 * @see org.springframework.web.context.ContextLoader#customizeContext
 * @see org.springframework.web.context.ContextLoader#CONTEXT_INITIALIZER_CLASSES_PARAM
 * @see org.springframework.web.servlet.FrameworkServlet#setContextInitializerClasses
 * @see org.springframework.web.servlet.FrameworkServlet#applyInitializers
 */

public interface ApplicationContextInitializer<C extends ConfigurableApplicationContext> {

	void initialize(C applicationContext);

}

上面的英文注释大概意思:在ConfigurableApplicationContext的refresh()方法之前被调用。通常在web应用中做初始化操作,比如根据ConfigurableApplicationContext#getEnvironment()注册属性源或配置文件。支持@Order()

写个小例子(springboot 项目):

MyApplicationContextInitializer 实现ApplicationContextInitializer

import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;

public class MyApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext>{

	@Override
	public void initialize(ConfigurableApplicationContext applicationContext) {
	    System.out.println("bean count:" + applicationContext.getBeanDefinitionCount());
	    System.out.println("BeanName列表:");
	    String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
	    for (String beanName : beanDefinitionNames) {
	        System.out.println(beanName);
	    }
	}

}

需要注册一下

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

import com.xiaofeng.shiro.config.MyApplicationContextInitializer;

@SpringBootApplication
public class Application {

	public static void main(String[] args) {
	SpringApplication springApplication = new SpringApplication(Application.class);
        //关键一步:将一个或多个initializer加入至spring容器中
        springApplication.addInitializers(new MyApplicationContextInitializer());
        ConfigurableApplicationContext context = springApplication.run(args);
        context.close();
		
	}
}

运行结果:

这个MyApplicationContextInitializer 是什么时候调用的?看下图,在springboot 启动的时候,会调用下面的方法

 

现在再把这个实现类的逻辑改一下,改成获取某个bean,看是什么结果

import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;

public class MyApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext>{

	@Override
	public void initialize(ConfigurableApplicationContext applicationContext) {
		System.out.println("初始化MyApplicationContextInitializer...");
		System.out.println(applicationContext.containsBean("conversionService"));
		Object con = applicationContext.getBean("conversionService");
		System.out.println(con.getClass());
	}

}

结果报错:

java.lang.IllegalStateException: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@71244ee8 has not been refreshed yet

这个错误是下面这段代码抛出的

protected void assertBeanFactoryActive() {
		if (!this.active.get()) {
			if (this.closed.get()) {
				throw new IllegalStateException(getDisplayName() + " has been closed already");
			}
			else {
				throw new IllegalStateException(getDisplayName() + " has not been refreshed yet");
			}
		}
	}

这里先判断active 这个变量的值,如果是未激活,并且容器未关闭,则抛出这个异常。

/** Flag that indicates whether this context is currently active */
    private final AtomicBoolean active = new AtomicBoolean();

也就是在从beanFactory获取bean的时候,会先判断是否为激活状态

@Override
    public Object getBean(String name) throws BeansException {
        assertBeanFactoryActive();
        return getBeanFactory().getBean(name);
    }

那这个方法在什么时候被赋值为true?

也就是说,这个MyApplicationContextInitializer在prepareRefresh()之前执行了,故报错

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值