Spring ApplicationContextAware,InitializingBean 作用以及使用学习总结 spring bean初始化流程总结
ApplicationContextAware
sping 框架提供的用于获取应用环境启动后获取(ApplicationContext)环境上下文 和容器中的bean
ApplicationContextAware 直译过来即 “应用程序上下文感知”
常见用法即工具类
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@Component
public final class SpringContextAwareTool implements ApplicationContextAware {
private static ApplicationContext applicationContext;
/**
* 获取
* @return
*/
public static ApplicationContext getApplicationContext(){
return applicationContext;
}
/**
* 通过bean 名获取
* @param beanName
* @return
*/
public static Object getBean(String beanName){
return getApplicationContext().getBean(beanName);
}
/**
* 通过 类的 .class 获取
* @param clazz
* @return
*/
public static <T> T getBean(Class<T> clazz){
return getApplicationContext().getBean(clazz);
}
/**
* 该方法在容器初始化入口处时被执行
* @param applicationContext
* @throws BeansException
*/
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if (SpringContextAwareTool.applicationContext == null){
SpringContextAwareTool.applicationContext = applicationContext;
}
}
}
上方执行的大概流程
简单来说当容器初始化的时候 实现了 ApplicationContextAware 的类的 setApplicationContext 方法会被调用执行 applicatonContext 对象会被框架给与,此时上方的方法中 静态属性 applicationContext 也就被赋值了,之后就可以使用静态的applicatonContext 的 getBean时就顺利成章可以使用了,从而获取到 容器中bean。
注意 @component 不可以没有 否则不会被加载到
总结:
所有实例化的类 都会进入到 ApplicationContextAwareProcessor 的 postProcessBeforeInitialization 方法中,此时当该实例化类为 Aware类型且是ApplicationContextAware 类型时会调用 setApplicationContext(this.applicationContext) ,也就完成了把spring上下文(applicationContext)的赋值过程上方的实例中 重写的set方法也就被执行 ,也就是说实现了 ApplicationContextAware 的类且有注解@component就会被在容器初始化时调。
@component 保证了该类进入了实例化流程,因此不能丢失该注解否则无效,将无法获取 applicationConext 对象。
sping Bean 初始化流程
- spring 检查注解注入的bean 并实例化对应bean
- spring 初始化bean 顺序按照配置文件顺序加载
- 当某个类 实现了 ApplicationContextAware 那么初始化完成后调用改类重写的 setApplicationContext 方法
- 当某个类实现了 InitializingBean 那么会在初始化完成后,且当 setApplicationContext 被调用执行完成后继续调用 afterPropertiesSet 方法。
同时实现 InitializingBean
实现 InitializingBean后 若重写 afterPropertiesSet,则会在 初始化完成,即容器中的Bean 完成填装后,继续执行 afterPropertiesSet 中的方法,类似如下:
import com.dtdream.dthink.dtalent.dmall.exception.DXPException;
import com.dtdream.dthink.dtalent.dmall.exception.ExceptionType;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
@Component
public class Xxxxxxxxxxxxxx implements ApplicationContextAware, InitializingBean {
private static final Map<String, XXXXXX> MY_MAP = new HashMap<>();
private ApplicationContext applicationContext;
// 将容器中部分已经注入的Bean 放到某一个Map 中
@Override
public void afterPropertiesSet() throws Exception {
applicationContext.getBeansOfType(XXXXXX.class).values()
.forEach(processor -> MY_MAP.put(Xxxxxxxx, processor));
}
// 初始化环境上下文 已获取容器中已注册的Bean
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
// 提供外部调用 可以从当前方法获得放到Map 中的Bean
public Xxxxxxxxx getExchangeProcessor(String type) throws MyException{
XXXXXXXXXX processor = MY_MAP.get(type);
if (processor == null) {
throw new MyException(.............);
}
return processor;
}
}