spring:普通Java类中获取由Spring所管理的Bean
一般情况下,在使用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;
}
上一篇: 普通java类获取spring管理的bean的几种方法
下一篇: spring的IOC容器
推荐阅读
-
FastJson序列化自定义返回字段,普通类从spring容器中获取bean
-
SpringBoot实现其他普通类调用Spring管理的Service,dao等bean
-
Spring 注解中,普通类获取@Service标记的方法 或者bean对象的两种方法
-
spring通用获取ioc容器中配置的bean的工具类
-
普通类获取Spring容器中的Bean
-
Spring:普通的Java类获取由Spring所管理的Bean
-
JAVA普通类获取spring的bean对象
-
普通java类获取 spring中的bean方法
-
Spring普通Java类获取bean
-
Spring如何管理Java普通类(Java类获取Spring容器的bean)