背景
有时我们需要在一些不属于Spring的类中,去调用Spring的Service类的方法。
比如,在Util类,或者main()方法中,去调用Service类的方法。
这时,可以使用 ApplicationContextAware接口 和 ApplicationContext接口 .
ApplicationContext 工具类:
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Component; @Component public class ApplicationContextUtil implements ApplicationContextAware { private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationContextUtil.class); private static ApplicationContext appContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { appContext = applicationContext; } public static <T> T getBean(Class<T> clazz) { if (appContext == null) { LOGGER.info("appContext is null"); return null; } return appContext.getBean(clazz); } }示例:
比如Service名是 UserServiceImpl ,那么初始化如下 :
UserServiceImpl userService = ApplicationContextUtil.getBean(UserServiceImpl.class);ApplicationContextAware接口的源码:
public interface ApplicationContextAware extends Aware { void setApplicationContext(ApplicationContext var1) throws BeansException; }ApplicationContextAware 接口中只有一个方法 setApplicationContext(),我们可以实现 ApplicationContextAware 接口,来重写这个方法,设置 ApplicationContext 。
ApplicationContext接口的源码:
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver { String getId(); String getApplicationName(); String getDisplayName(); long getStartupDate(); ApplicationContext getParent(); AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException; }ApplicationContext 接口,继承了 EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver。
BeanFactory
ApplicationContext里面这么多个类和接口,我们可以用Idea看一下相关的UML图:
前面的示例代码, applicationContext 使用了 getBean(Class var); 而在ApplicationContext 中是没有getBean这个方法的。
通过上面的UML图,可以留意到 ApplicationContext 继承 ListableBeanFactory, 而 ListableBeanFactory 继承 BeanFactory。
BeanFactory类里面,就有 getBean这个方法。getBean方法,就可以从Spring容器中返回特定名称的Bean对象。
也正因如此,ApplicationContext才能够实例化Bean。