欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

spring:普通Java类中获取由Spring所管理的Bean

程序员文章站 2022-05-23 10:05:30
...

一般情况下,在使用SPRING注解的方式管理bean时,只能通过注解或者配置文件注入的方式获取相应的bean。

但是在某些特殊情况下,我们需要在一个普通的JAVA类中获取由spring所管理的bean,下面是解决办法之一:

  

实例演示

 

第一步:创建一个类并让其实现org.springframework.context.ApplicationContextAware接口,使Spring在启动时注入ApplicationContext对象:

package com.hsoft.mss.common.utils;
  
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
  
public class ApplicationContextUtil implements ApplicationContextAware { 
      
  private static ApplicationContext context;
     
  public void setApplicationContext(ApplicationContext contex) throws BeansException { 
        ApplicationContextUtil.context=contex; 
  } 

  public static ApplicationContext getContext(){ 
    return context; 
  }
}

严格上来说,方法类ApplicationContextUtil 是一个bean,而且从第一步中我们不难发现,之所以方法ApplicationContextUtil能够灵活自如地获取ApplicationContext就是因为spring能够为我们自动地执行了setApplicationContext。但是,spring不会无缘无故地为某个类执行它的方法的,所以,就很有必要通过注册方法类ApplicationContextUtil的方式告知spring有这样子一个类的存在。其实,方法很简单,就是将方法类ApplicationContextUtil作为一个普通的bean在spring的配置文件中进行注册:

第二步:在spring配置文件中注册上述bean,令服务器启动时加载并将contex对象注入其中:

<bean class="com.XXX.common.utils.ApplicationContextUtil"></bean> 

 

第三步:通过上述方法获取重写的contex对象,并通过spring所管理的bean名称得到相应的对象,之后即可使用对象中的各种方法:

MyService myService = (MyService ) ApplicationContextUtil.getContext().getBean("myService"); 
//调用其中的方法
int count = myService .getCountById("18");

 

原理分析

 

在AbstractApplicationContext的refresh方法中的prepareBeanFactory(beanFactory);方法。添加了ApplicationContextAwareProcessor处理器,ApplicationContextAwareProcessor是继承了BeanPostProcessor接口。在bean实例化的时候,也就是Spring**bean的init-method方法的前后,会调用BeanPostProcessor的postProcessBeforeInitialization方法和postProcessAfterInitialization。


在ApplicationContextAwareProcessor我们同样关心这两个方法。在postProcessBeforeInitialization方法中,可以看到会调用invokeAwareInterfaces方法,其中判断了当前初始化bean时候继承了对应的Aware,如果是则调用对应的set方法,传入对应的资源。

所有的BeanPostProcessor都将在AbstractAutowireCapableBeanFactory类的initializeBean方法中,通过调用applyBeanPostProcessorsBeforeInitialization方法完成所有实现BeanPostProcessor接口的postProcessBeforeInitialization的调用。

AbstractApplicationContext.prepareBeanFactory
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
     // Tell the internal bean factory to use the context's class loader etc.
     beanFactory.setBeanClassLoader(getClassLoader());
     beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
     beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

     // Configure the bean factory with context callbacks.
     beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
     beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
     beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
     beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
     beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
     beanFactory.ignoreDependencyInterface(EnvironmentAware.class);

     // BeanFactory interface not registered as resolvable type in a plain factory.
     // MessageSource registered (and found for autowiring) as a bean.
     beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
     beanFactory.registerResolvableDependency(ResourceLoader.class, this);
     beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
     beanFactory.registerResolvableDependency(ApplicationContext.class, this);

     .....
     ...
     ..
}

 

ApplicationContextAwareProcessor.postProcessBeforeInitialization
@Override
public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
     AccessControlContext acc = null;

     if (System.getSecurityManager() != null &&
                (bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
                           bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
                           bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
           acc = this.applicationContext.getBeanFactory().getAccessControlContext();
     }

     if (acc != null) {
           AccessController.doPrivileged(new PrivilegedAction<Object>() {
                @Override
                public Object run() {
                     invokeAwareInterfaces(bean);
                     return null;
                }
           }, acc);
     }else {
           invokeAwareInterfaces(bean);
     }

     return bean;
}

private void invokeAwareInterfaces(Object bean) {
     if (bean instanceof Aware) {
           if (bean instanceof EnvironmentAware) {
                ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
           }
           if (bean instanceof EmbeddedValueResolverAware) {
                ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(
                           new EmbeddedValueResolver(this.applicationContext.getBeanFactory()));
           }
           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);
           }

     }
}

@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
     return bean;
}
 

相关标签: spring bean