spring动态获取bean

在实际的项目中,在使用spring注解的方式管理bean时,只能通过注解或者配置文件注入的方式获取相应的bean。但是在某些特殊情况下,我们需要在一个普通的JAVA类中获取由spring所管理的bean,一下是解决方法,实现接口ApplicationContextAware。

package com.example.demo.service;

import com.baomidou.mybatisplus.core.toolkit.ArrayUtils;
import org.apache.commons.lang3.Validate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

/**
 * 以静态变量保存Spring ApplicationContext, 可在任何代码任何地方任何时候取出ApplicaitonContext.
 *
 * @author lst
 * @date 2019-12-21 16:52
 */
@Service
@Lazy(false)
public class SpringContextHolder implements ApplicationContextAware, DisposableBean {

    private static ApplicationContext applicationContext = null;

    private static Logger logger = LoggerFactory.getLogger(SpringContextHolder.class);

    /**
     * 取得存储在静态变量中的ApplicationContext.
     */
    public static ApplicationContext getApplicationContext() {
        assertContextInjected();
        return applicationContext;
    }

    /**
     * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
     */
    @SuppressWarnings("unchecked")
    public static <T> T getBean(String name) {
        assertContextInjected();
        return (T) applicationContext.getBean(name);
    }

    /**
     * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
     */
    public static <T> T getBean(Class<T> requiredType) {
        assertContextInjected();
        return applicationContext.getBean(requiredType);
    }

    /**
     * 清除SpringContextHolder中的ApplicationContext为Null.
     */
    public static void clearHolder() {
        if (logger.isDebugEnabled()) {
            logger.debug("清除SpringContextHolder中的ApplicationContext:" + applicationContext);
        }
        applicationContext = null;
    }

    /**
     * 实现ApplicationContextAware接口, 注入Context到静态变量中.
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) {
        SpringContextHolder.applicationContext = applicationContext;
    }

    /**
     * 实现DisposableBean接口, 在Context关闭时清理静态变量.
     */
    @Override
    public void destroy() throws Exception {
        SpringContextHolder.clearHolder();
    }

    /**
     * 检查ApplicationContext不为空.
     */
    private static void assertContextInjected() {
        Validate.validState(applicationContext != null, "applicaitonContext属性未注入, 请在applicationContext.xml中定义SpringContextHolder.");
    }

    /**
     * // 获取当前环境参数  exp: dev,prod,test
     * @return
     */
    public static String getActiveProfile() {
        String[] profiles = SpringContextHolder.getApplicationContext().getEnvironment().getActiveProfiles();
        if (!ArrayUtils.isEmpty(profiles)) {
            return profiles[0];
        }
        return "";
    }
}

以上的工具可以通过一下方式去获取。

private static DictMapper dictMapper = SpringContextHolder.getBean(DictMapper.class);

其实我们获取的Bean是从Spring容器中获取的,所以肯定要获取Spring上下文,即ApplicationContext。当然,首先我们编写的SpringContextHolder首先自身要被Spring管理,实现ApplicationContextAware、DisposableBean接口。这样在Spring加载的时候,会执行setApplicationContext方法将ApplicabletionContext注入到当前的SpringContextHolder的成员变量ApplicationContext ctx。这样就获取到了Spring上下文,后面动态获取Bean就方便了。

要注意的是,如果你获取的这个Bean是singleton的话(Spring默认的作用域),那该工具类获取的也是singleton,如果是prototype的话,Spring每次会跟你new一个出来。

发布了13 篇原创文章 · 获赞 7 · 访问量 588

猜你喜欢

转载自blog.csdn.net/qq_33612228/article/details/103958006
今日推荐