美文网首页
静态方法获取spring的bean实例

静态方法获取spring的bean实例

作者: 水煮鱼又失败了 | 来源:发表于2020-07-05 16:04 被阅读0次

    1 场景

    spring命名空间中的bean,正常情况下可以使用@Autoware注解加在成员变量上注入,注入成功的前提是注入的对象必须已经是spring命名空间中的bean才可以。

    当前有一种需求:通过工具类的静态方法,获取spring中的bean

    2 思路

    (1)定义bean

    (2)bean实现ApplicationContextAware接口

    3 代码

    3.1 定义bean

    /**
     * spring上下文句柄
     */
    public class SpringContextHolder implements ApplicationContextAware {
        /**
         * spring上下文
         */
        private static ApplicationContext applicationContext;
        
        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            SpringContextHolder.applicationContext=applicationContext;
        }
        
        /**
         * 获取spring上下文
         * @return
         */
        public static ApplicationContext getApplicationContext(){
            return applicationContext;
        }
        
        /**
         * 获取bean
         * @param name  bean名称
         * @param <T>
         * @return
         */
        public static <T> T getBean(String name){
            if(applicationContext==null){
                return null;
            }
            return (T) applicationContext.getBean(name);
        }
        
        /**
         * 获取bean
         * @param requiredType bean类型
         * @param <T>
         * @return
         */
        public static <T> T getBean(Class<T> requiredType){
            if(applicationContext==null){
                return null;
            }
            return applicationContext.getBean(requiredType);
        }
        
        /**
         * 获取bean
         * @param name  bean名称
         * @param requiredType  bean类型
         * @param <T>
         * @return
         */
        public static <T> T getBean(String name, Class<T> requiredType){
            if(applicationContext==null){
                return null;
            }
            return applicationContext.getBean(name,requiredType);
        }
    }
    

    3.2 注册bean

    spring配置文件中,加载的xml最前面定义上述bean:

    <!-- spring上下文句柄 -->
    <bean id="springContextHolder" class="com.sa.demo.spring.context.SpringContextHolder"/>
    

    3.3 使用

    在java代码的任何一个地方执行下面代码,可以获取spring中的bean:

    SpringContextHolder.getBean("xxxxxx");
    SpringContextHolder.getBean("XXX.class")
    SpringContextHolder.getBean("xxxxxx","XXX.class")
    

    获取spring中的命名空间:

    ApplicationContext applicationContext=SpringContextHolder.getApplicationContext();
    

    4 扩展

    4.1 源码讲解

    加载原理:

    实现的接口ApplicationContextAware中的方法定义如下:

    /**
     * Set the ApplicationContext that this object runs in.
     * Normally this call will be used to initialize the object.
     * <p>Invoked after population of normal bean properties but before an init callback such
     * as {@link org.springframework.beans.factory.InitializingBean#afterPropertiesSet()}
     * or a custom init-method. Invoked after {@link ResourceLoaderAware#setResourceLoader},
     * {@link ApplicationEventPublisherAware#setApplicationEventPublisher} and
     * {@link MessageSourceAware}, if applicable.
     * @param applicationContext the ApplicationContext object to be used by this object
     * @throws ApplicationContextException in case of context initialization errors
     * @throws BeansException if thrown by application context methods
     * @see org.springframework.beans.factory.BeanInitializationException
     */
    void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
    

    翻译如下:

    设置运行该对象的ApplicationContext。
    通常这个调用将用于初始化对象。
    在填充普通bean属性之后,在init回调之前调用
    

    表示实现此接口的bean,将在填充bean属性之后bean的init回调方法之前,调用此方法。方法的参数为spring的命名空间ApplicationContext

    bean实现此接口后,会被调用相应方法,取决于以下源码:

    方法路径:

    org.springframework.context.support.ApplicationContextAwareProcessor#postProcessBeforeInitialization
    
    org.springframework.context.support.ApplicationContextAwareProcessor#invokeAwareInterfaces
    

    对应方法如下:

    private void invokeAwareInterfaces(Object bean) {
        if (bean instanceof EnvironmentAware) {
            ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
        }
        if (bean instanceof EmbeddedValueResolverAware) {
            ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
        }
        if (bean instanceof ResourceLoaderAware) {
            ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
        }
        if (bean instanceof ApplicationEventPublisherAware) {
            ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
        }
        if (bean instanceof MessageSourceAware) {
            ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
        }
        if (bean instanceof ApplicationContextAware) {
            ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
        }
    }
    

    相应扩展部分:

    当spring中注册的bean实现了如下接口:

    EnvironmentAware
    EmbeddedValueResolverAware
    ResourceLoaderAware
    ApplicationEventPublisherAware
    MessageSourceAware
    ApplicationContextAware
    

    均会执行上述代码中对应的实现方法。

    4.2 注意事项

    (1)此类bean的定义,需在spring最前面定义。

    (2)实现了接口ApplicationContextAware的bean,只能获取此bean所定义的spring命名空间。

    相关文章

      网友评论

          本文标题:静态方法获取spring的bean实例

          本文链接:https://www.haomeiwen.com/subject/wypvqktx.html