本文参考 https://www.cnblogs.com/wangcp-2014/p/8126187.html
ServletContextAware
ApplicationContext 是spring ioc容器,在这个容器中存储了bean对象实例(通过Map(ConcurrentHashMap)结构进行存储) 。 一般情况我们不会刻意去取ApplicationContext、WebApplicationContext这个对象,只是有时为了测试,需要从ioc容器中获取某个指定的Bean对象
一. 通过 xml文件方式、注解方式加载spring配置文件,启动spring ioc容器
xml方式: ClassPathXmlApplicationContext、FileSystemXmlApplicationContext —— 一个是从classpath路径下加载spring配置文件,另外一个是从指定的绝对路径下加载spring配置文件
注解方式: AnnotationConfigApplicationContext、AnnotationConfigWebApplicationContext —— 两者都是通过注解方式加载spring配置文件
示例如下:
public class ProductWebApplication {
private static ApplicationContext ac = null;
public static void main(String[] args) {
SpringApplication.run(ProductWebApplication.class, args);
// 1.
ApplicationContext ac1 = new ClassPathXmlApplicationContext("classpath:spring.xml");
ProductComponentService bean1 = ac1.getBean("productComponentService", ProductComponentService.class);
// 2.
ApplicationContext ac2 = new FileSystemXmlApplicationContext("f:\\spring\\spring.xml");
ProductComponentService bean2 = ac2.getBean("productComponentService", ProductComponentService.class);
// 3.
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(WebConfig.class);
// AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
// ctx.register(WebConfig.class);
// ctx.refresh();
ProductComponentService bean3 = ctx.getBean("productComponentService", ProductComponentService.class);
System.out.println(bean3.toString());
// 4.
AnnotationConfigWebApplicationContext acwc = new AnnotationConfigWebApplicationContext();
acwc.register(WebConfig.class);
acwc.refresh();
ProductComponentService bean4 = acwc.getBean("productComponentService", ProductComponentService.class);
System.out.println(bean4.toString());
}
}
@Configuration
@EnableWebMvc
@ComponentScan(value= {"com.xxx.product.web"})
public class WebConfig extends WebMvcConfigurerAdapter {
}
二、 通过工具类WebApplicationContextUtils 来获取
/**
* 通过WebApplicationContextUtils工具类来获取 ApplicationContext对象
*/
class Demo {
public static void main(String[] args) {
ServletContext sc = null;
// getRequiredWebApplicationContext 如果未获取到ac对象,会抛出异常
ApplicationContext ac1 = WebApplicationContextUtils.getRequiredWebApplicationContext(sc);
ProductComponentService productComponentService1 = ac1.getBean("productComponentService", ProductComponentService.class);
// getWebApplicationContext 如果未获取到ac对象,返回null
ApplicationContext ac2 = WebApplicationContextUtils.getWebApplicationContext(sc);
ProductComponentService productComponentService2 = ac2.getBean("productComponentService", ProductComponentService.class);
}
}
/**
* Find the root {@code WebApplicationContext} for this web app, typically
* loaded via {@link org.springframework.web.context.ContextLoaderListener}.
* Will rethrow an exception that happened on root context startup,
* to differentiate between a failed context startup and no context at all.
* @param sc ServletContext to find the web application context for
* @return the root WebApplicationContext for this web app, or {@code null} if none
* @see org.springframework.web.context.WebApplicationContext#ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE
*/
但是通过WebApplicationContextUtils 工具类获取 ioc容器的时候,不能在容器启动的时候 ( root context startup),否则会抛出异常,看WebApplicationContextUtils的 方法注释就知道了
/**
* Find the root {@code WebApplicationContext} for this web app, typically
* loaded via {@link org.springframework.web.context.ContextLoaderListener}.
*
Will rethrow an exception that happened on root context startup,
* to differentiate between a failed context startup and no context at all.
* @param sc ServletContext to find the web application context for
* @return the root WebApplicationContext for this web app, or {@code null} if none
* @see org.springframework.web.context.WebApplicationContext#ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE
*/
三、继承方式:
3.1 继承 ApplicationObjectSupport ( abstract class )
它实现了 ApplicationContextAware 接口
public abstract class ApplicationObjectSupport implements ApplicationContextAware {}
说明:抽象类ApplicationObjectSupport提供getApplicationContext()方法,可以方便的获取到ApplicationContext
Spring初始化时,会通过该抽象类的setApplicationContext(ApplicationContext context)方法将ApplicationContext 对象注入。
spring mvn 4.3.12 AbstractDetectingUrlHandlerMapping.java 类就有获取 ioc容器的应用,并且是通过继承ApplicationObjectSupport 的方式
AbstractDetectingUrlHandlerMapping中的 detectHandlers()方法
ApplicationObjectSupport类图关系
3.2 继承WebApplicationObjectSupport (abstract class)
它继承自上面的ApplicationObjectSupport类
public abstract class WebApplicationObjectSupport extends ApplicationObjectSupport implements ServletContextAware {
说明:类似上面方法,调用getWebApplicationContext()获取WebApplicationContext
WebApplicationObjectSupport类图关系, 他还实现了 ServletContextAware接口,也就是可以获取到 ServletContext信息
四、 实现 ApplicationContextAware 接口
和这个 ApplicationContextAware接口 类似的有 ServletContextAware
ServletContextAware 中可以获取到Servlet容器信息
这种 XxxAware接口是spring的一种特性,扩展,在spring容器启动的时候,只要实现了这种Aware接口[有一个Aware接口],都是被spring容器进行回调,类似的还有:
BeanFactoryAware
BeanNameAware
... ...
@SpringBootApplication
@MapperScan("com.xxx.mapper") // 扫描mybatis mapper文件
public class Application implements ApplicationContextAware {
private static ApplicationContext ac = null;
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
// ac 成员变量在spring 容器启动的时候,进行了初始化赋值,可以直接使用该成员变量了,从spring ioc容器中获取bean对象
ProductComponentService productComponentService = ac.getBean("xxx", ProductComponentService.class);
productComponentService.doXXX();
}
// 因为实现了ApplicationContextAware接口,所以本方法在spring容器启动的时候会调用,并注入 applicationContext
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
ac = applicationContext;
}
}
实现Aware接口的还有很多:
五、 据说还有一种方式,通过获取当前线程对应的 WebApplicationContext对象, 没试过 这种方式。
public static void main(String[] args) {
// 获取当前线程,对应的WebApplicationContext对象
WebApplicationContext wac = ContextLoader.getCurrentWebApplicationContext();
ProductComponentService productComponentService3 = wac.getBean("productComponentService", ProductComponentService.class);
}