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命名空间。
网友评论