1207 2017-12-12 2024-08-09
前面都是基于Spring的bean模块的BeanFactory接口及其默认实现类DefaultListableBeanFactory为例进行分析的,这次我们看下context模块的另一个重要的接口ApplicationContext。
一、类结构
ApplicationContext和BeanFactory两者都是用于加载bean的,但是相比之下,ApplicationContext提供了更多的扩展功能,简单一点说:ApplicationContext包含BeanFactory的所有功能。通常建议比BeanFactory优先使用。
我们先从类结构出发,如图
代码如下
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
// 唯一标识id
String getId();
String getApplicationName();
String getDisplayName();
long getStartupDate();
// ApplicationContext天生具有继承关系
ApplicationContext getParent();
// 天生兼容BeanFactory,且是可以支持注入的BeanFactory
AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException;
}
下面对其父级进行说明。
二、父接口
1、MessageSource
实现信息资源国际化的接口。
// 天然支持多语言、国际化
public interface MessageSource {
String getMessage(String code, Object[] args, String defaultMessage, Locale locale);
String getMessage(String code, Object[] args, Locale locale) throws NoSuchMessageException;
String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException;
}
2、ApplicationEventPublisher
事件发布的接口。
// 支持事件发布,可以在spring启动中,触发响应的事件监听
public interface ApplicationEventPublisher {
void publishEvent(ApplicationEvent event);
}
3、ResourcePatternResolver
资源模式解析器的接口,继承自ResourceLoader接口。
// 加载类及类资源文件接口
public interface ResourcePatternResolver extends ResourceLoader {
String CLASSPATH_ALL_URL_PREFIX = "classpath*:";
Resource[] getResources(String locationPattern) throws IOException;
}
public interface ResourceLoader {
/** Pseudo URL prefix for loading from the class path: "classpath:" */
String CLASSPATH_URL_PREFIX = ResourceUtils.CLASSPATH_URL_PREFIX;
Resource getResource(String location);
ClassLoader getClassLoader();
}
4、EnvironmentCapable
Spring环境获取的接口。
// 支持spring环境变量、配置获取
public interface EnvironmentCapable {
/**
* Return the {@link Environment} associated with this component.
*/
Environment getEnvironment();
}
5、继承自BeanFactory的接口
还有两个接口分别是
- ListableBeanFactory:可列举的bean工厂接口,定义了大量获取bean的方法。
- HierarchicalBeanFactory:分层的bean工厂接口。
三、子接口
ApplicationContext只有三个子接口,而两个子接口下面有众多的子孙接口及实现类(Ctrl + h 可以查看类自上而下继承结构)。
1、ConfigurableApplicationContext
可配置的ApplicationContext接口。
// 主要是服务于ApplicationContext的全生命周期,加载配置、环境变量、应用BeanFactoryPostProcessor
// 发布spring事件、刷新ApplicationContext、销毁ApplicationContext
public interface ConfigurableApplicationContext extends ApplicationContext, Lifecycle, Closeable {
String CONFIG_LOCATION_DELIMITERS = ",; \t\n";
String CONVERSION_SERVICE_BEAN_NAME = "conversionService";
String LOAD_TIME_WEAVER_BEAN_NAME = "loadTimeWeaver";
String ENVIRONMENT_BEAN_NAME = "environment";
String SYSTEM_PROPERTIES_BEAN_NAME = "systemProperties";
String SYSTEM_ENVIRONMENT_BEAN_NAME = "systemEnvironment";
void setId(String id);
void setParent(ApplicationContext parent);
ConfigurableEnvironment getEnvironment();
void setEnvironment(ConfigurableEnvironment environment);
void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor);
void addApplicationListener(ApplicationListener<?> listener);
void refresh() throws BeansException, IllegalStateException;
void registerShutdownHook();
void close();
boolean isActive();
ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;
}
2、WebApplicationContext
适用于Web环境的ApplicationContext接口,常见于比较原始Spring MVC场景。
// 与web环境相结合,适配web协议 javax.servlet.ServletContext
public interface WebApplicationContext extends ApplicationContext {
String ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class.getName() + ".ROOT";
// 各种web作用域
String SCOPE_REQUEST = "request";
String SCOPE_SESSION = "session";
String SCOPE_GLOBAL_SESSION = "globalSession";
String SCOPE_APPLICATION = "application";
String SERVLET_CONTEXT_BEAN_NAME = "servletContext";
String CONTEXT_PARAMETERS_BEAN_NAME = "contextParameters";
String CONTEXT_ATTRIBUTES_BEAN_NAME = "contextAttributes";
// 想起servlet了吗?
// 想起xml了吗?
ServletContext getServletContext();
}
3、WebServerApplicationContext
WebServerApplicationContext是Spring Boot专用ApplicationContext。
// 支持内嵌tomcat
// 这是一条广告,欢迎关注公众号:好看的HK
public interface WebServerApplicationContext extends ApplicationContext {
WebServer getWebServer();
// 支持多服务多端口部署
String getServerNamespace();
}
// 服务器接口
public interface WebServer {
void start() throws WebServerException;
void stop() throws WebServerException;
int getPort();
}
4、ApplicationContextAware
@Component
public class Test implements ApplicationContextAware {
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
// 真正干活的是 AnnotationConfigServletWebServerApplicationContext
System.out.println(applicationContext.getClass());
// true
System.out.println(applicationContext instanceof WebServerApplicationContext);
// true
System.out.println(applicationContext instanceof WebApplicationContext);
}
}
四、重要实现类
ApplicationContext接口功能远比BeanFactory接口强大,因此如果我们想要一个精简版的Spring环境(比如只想要IoC、不想要AOP或Web环境等特殊情况下),可以使用这些开箱即用的ApplicationContext。
先回忆一下远古的xml配置方式(这个配置文件后面还会出现)。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<aop:aspectj-autoproxy/>
<bean id="testBean" class="xiaokui1.TestBean"/>
<bean class="xiaokui1.AspectJTest"/>
</beans>
啊,这该死的回忆又涌上了心头!
1、ClassPathXmlApplicationContext
public static void main(String[] args) {
// 使用相对类路径 ClassPathXmlApplicationContext
// 固定文件路径的话,可以用 FileSystemXmlApplicationContext
// 区别在 Resource 接口实现的不同
ClassPathXmlApplicationContext application = new ClassPathXmlApplicationContext("xiaokui1/xiaokui.xml");
TestBean testBean = (TestBean)application.getBean("testBean");
testBean.test();
}
2、AnnotationConfigApplicationContext
@SpringBootApplication
public class TestApp {
public static void main(String[] args) {
// web环境可以考虑用AnnotationConfigWebApplicationContext,但单独使用会有环境配置问题,不能建议直接使用
// AnnotationConfigApplicationContext相对来说轻量级一点
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
// 扫描特定包下面类
context.scan("site.xiaokui.app");
// 刷新,触发bean的加载
context.refresh();
Object bean1 = context.getBean(TestController.class);
// 正常输出 class site.xiaokui.app.controller.TestController
System.out.println(bean1.getClass());
Object bean2 = context.getBean(InitPrometheusData.class);
// 正常输出 class site.xiaokui.app.task.InitPrometheusData$$EnhancerBySpringCGLIB$$ae07d98f
System.out.println(bean2.getClass());
// SpringApplication.run(TestApp.class, args);
// log.info("========== web服务已成功启动!!! ==========");
}
}
总访问次数: 174次, 一般般帅 创建于 2017-12-12, 最后更新于 2024-08-09
欢迎关注微信公众号,第一时间掌握最新动态!