Spring 提供了两种类型的 IOC 容器实现.
- BeanFactory :是Spring实现IOC容器的顶级接口,主要供Spring内部使用,并非面向spring框架的开发者
- ApplicationContext : 是 BeanFactory 的子接口,提供了更多的高级特性。主要面向使用 Spring 框架的开发者,几乎所有的应用场合都直接使用 ApplicationContext 而非底层的 BeanFactory
在ApplicationContext接口中有三个常用的实现类分别是:
①、AnnotationConfigApplicationContext
②、FileSystemXmlApplicationContext
③、ClassPathXmlApplicationContext
1、ApplicationContextAware
Spring
定义的类实现ApplicationContextAware
接口会自动的将应用程序上下文加入。
代码示例如下:
@Slf4j
@Component
public class ApplicationConfig implements ApplicationContextAware {
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
log.info("{} 服务初始化完成!!!", this.applicationContext.getApplicationName());
}
}
spring
的入口方法就在 AbstractApplicationContext
的 refresh()
方法,我们先去看看refresh().prepareBeanFactory()
方法。
org.springframework.context.support.AbstractApplicationContext#prepareBeanFactory
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// Tell the internal bean factory to use the context's class loader etc.
beanFactory.setBeanClassLoader(getClassLoader());
if (!shouldIgnoreSpel) {
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(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
beanFactory.ignoreDependencyInterface(ApplicationStartupAware.class);
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
if (!NativeDetector.inNativeImage() && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// Set a temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
if (!beanFactory.containsLocalBean(APPLICATION_STARTUP_BEAN_NAME)) {
beanFactory.registerSingleton(APPLICATION_STARTUP_BEAN_NAME, getApplicationStartup());
}
}
spring在
启动的时候给我们添加了 ApplicationContextAwareProcessor
这样一个 processor
,看它的实现。
@Override
@Nullable
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware ||
bean instanceof ApplicationStartupAware)) {
return bean;
}
AccessControlContext acc = null;
if (System.getSecurityManager() != null) {
acc = this.applicationContext.getBeanFactory().getAccessControlContext();
}
if (acc != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareInterfaces(bean);
return null;
}, acc);
}
else {
invokeAwareInterfaces(bean);
}
return bean;
}
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 ApplicationStartupAware) {
((ApplicationStartupAware) bean).setApplicationStartup(this.applicationContext.getApplicationStartup());
}
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}
}
可清楚了解到ApplicationContextAware
实现类在应用启动的时候就自动初始化了
2、ApplicationListener
ApplicationContext
事件机制是属于设计模式中的观察者设计模式,通过ApplicationEvent
类和ApplicationListener
接口实现事件处理。
当容器中有一个ApplicationListener
对象, 当ApplicationContext
发布ApplicationEvent
事件时,ApplicationListener
对象会被自动触发, 需要由程序来控制。
spring内置事件
内置事件 | 说明 | 适用场景 |
---|---|---|
ContextRefreshedEvent | ApplicationContext 被初始化或刷新时,该事件被发布。也可在 ConfigurableApplicationContext 接口中使用 refresh() 方法来触发。初始化是指:所有的Bean被成功装载,容器已就绪可用 | 初始化缓存、预加载数据等 |
ContextStartedEvent | ConfigurableApplicationContext (ApplicationContext 子接口)接口中的 start() 方法启动 ApplicationContext 时,该事件被发布。 | 启动定时任务、启动异步消息处理 等 |
ContextStoppedEvent | ConfigurableApplicationContext 接口中的 stop() 停止 ApplicationContext 时,发布这个事件。可在接受到这个事件后做必要的清理工作 | 停止定时任务、关闭数据库等 |
ContextClosedEvent | ConfigurableApplicationContext 接口中的 close() 方法关闭 ApplicationContext 时,该事件被发布。适用于在应用程序关闭前执行最后的清理工作 | 释放资源、保存日志等 |
RequestHandledEvent | 是 web-specific 事件,告诉所有 bean HTTP 请求已经被服务处理。只能应用于使用DispatcherServlet 的Web 应用。在使用Spring 作为前端的MVC 控制器时,当Spring 处理用户请求结束后,系统会自动触发该事件 | 记录请求日志、处理统计数据等 |
代码示例
@Slf4j
@Component
public class ApplicationConfig implements ApplicationContextAware, ApplicationListener<ContextRefreshedEvent> {
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
log.info("{} 服务初始化完成!!!", this.applicationContext.getApplicationName());
}
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
if (event.getApplicationContext().getParent() == null) {
String contextName = event.getApplicationContext().getDisplayName();
String applicationName = event.getApplicationContext().getApplicationName();
log.info("ApplicationContext is success refreshed,contextName:{},applicationName:{}", contextName, applicationName);
}
}
}