SpringContextHelper或者SpringContextHolder之类命名的类,主要是通过Spring上下文根据bean名称获取注入spring的对象。代码相对简单,本文不对代码做详细赘述。主要mark使用过程中可能遇到的坑。


  • 在项目启动时,可能会偶现SpringContextHelper抛出的NPE异常。那么什么情况会出现NPE呢?如bean A中有一个被@PostConstruct注解的方法m,当A被容器实例化之后会调用m,此时如果SpringContextHelper还未实例化就会导致NPE。最后虽然项目成功启动了,并且后续SpringContextHelper可以正常使用,但是这种NPE会导致m方法里面处理的数据出现丢失的情况。这种偶现的异常可能给项目带来失之毫厘差之千里的影响。
  • 解决方案
    知道报错原因我们很容易找到解决方法,只需要保证SpringContextHelper优先示例话即可。比如:
  1. 使用@DependsOn("springContextHelper"),在A上添加次注解,让A在SpringContextHelper之后实例化;
  2. 在spring包扫描时调整SpringContextHelper优先被扫描到。 (SpringContextHelper.java在com.bingo包路径下)
    	@ComponentScan(basePackages = {
    			"com.bingo", "com.demo"
    	})
    

  • SpringContextHelper.java
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
 * <Description> 获取容器中的ApplicationContext<br>
 *
 * @author <br>
 * @version 1.0<br>
 * @taskId <br>
 * @CreateDate 2016年10月10日 <br>
 */

@Component
public class SpringContextHelper implements ApplicationContextAware {
    /**
     * appCtx
     */
    private static ApplicationContext appCtx;

    /**
     * Description: 此方法可以把ApplicationContext对象inject到当前类中作为一个静态成员变量。<br>
     *
     * @param applicationContext ApplicationContext 对象. <br>
     * @author <br>
     * @taskId <br>
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) {
        SpringContextHelper.setAppCtx(applicationContext);
    }

    /**
     * Description: 此方法可以把ApplicationContext对象inject到当前类中作为一个静态成员变量。<br>
     *
     * @param applicationContext ApplicationContext 对象. <br>
     * @author <br>
     * @taskId <br>
     */
    private static void setAppCtx(ApplicationContext applicationContext) {
        appCtx = applicationContext;
    }

    /**
     * Description: 获取ApplicationContext<br>
     *
     * @return <br>
     * @author <br>
     * @taskId <br>
     */
    public static ApplicationContext getApplicationContext() {
        return appCtx;
    }

    /**
     * Description:这是一个便利的方法,帮助我们快速得到一个BEAN  <br>
     *
     * @param beanName beanName
     * @return <br>
     * @author <br>
     * @taskId <br>
     */
    public static Object getBean(String beanName) {
        return appCtx.getBean(beanName);
    }

    /**
     * Description: 快速获取Spring容器中的bean<br>
     *
     * @param <T>   <br>
     * @param clazz <br>
     * @return <br>
     * @author <br>
     * @taskId <br>
     */
    public static <T> T getBean(Class<T> clazz) {
        return appCtx.getBean(clazz);
    }

    /**
     * 打印所有的bean name <br>
     */
    public static void printAllBeans() {
        System.out.println(Arrays.asList(appCtx.getBeanDefinitionNames()));
    }
}
12-26 19:08