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 不可以没有 否则不会被加载到

总结:

所有实例化的类 都会进入到 ApplicationContextAwareProcessorpostProcessBeforeInitialization 方法中,此时当该实例化类为 Aware类型且是ApplicationContextAware 类型时会调用 setApplicationContext(this.applicationContext) ,也就完成了把spring上下文(applicationContext)的赋值过程上方的实例中 重写的set方法也就被执行 ,也就是说实现了 ApplicationContextAware 的类且有注解@component就会被在容器初始化时调。

@component 保证了该类进入了实例化流程,因此不能丢失该注解否则无效,将无法获取 applicationConext 对象。

sping Bean 初始化流程

  1. spring 检查注解注入的bean 并实例化对应bean
  2. spring 初始化bean 顺序按照配置文件顺序加载
  3. 当某个类 实现了 ApplicationContextAware 那么初始化完成后调用改类重写的 setApplicationContext 方法
  4. 当某个类实现了 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;
    }
}

你可能感兴趣的:(#,Spring,全家,Java,spring)