今天,看了ApplicationContextAware,然后自己写了个例子,最后运行出了问题,报错:NullPointerException,再最后,发现自己这个问题真的很蠢,很白痴。好吧,我就当没发生这件事。。。
关于ApplicationContextAware,这是个接口,作用是实现了该接口的类,在Spring初始化的时候,会去执行该接口唯一的方法setApplicationContext(),这个方法你要自己去实现,一般是用来将web的上下文(ApplicationContext)填充到指定的static变量,方便你以后在其他地方使用(以后你要用这个上下文获得bean,可直接调用),所以,通常实现这个接口的类是个工具类,用来获取bean实例。说这么多,还是用例子说明好了。
我的ApplicationContextAware例子:
1.web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>spring-test</display-name>
<!-- spring config begin -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath*:config/spring/local/appcontext-*.xml
</param-value>
</context-param>
<!-- end -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
2.Spring配置文件appcontext-service.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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
">
<bean id="springTest" class="com.fcc.spring.test.SpringTest" lazy-init="false" />
<bean id="helloWorld" class="com.fcc.spring.test.HelloWorld">
<property name="message" value="Hello World!" />
</bean>
</beans>
3.SpringTest.java
package com.fcc.spring.test;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
public class SpringTest implements ApplicationContextAware{
private static ApplicationContext applicationContext;
public static void main(String[] args){
HelloWorld obj = (HelloWorld)SpringTest.getBean("helloWorld");
System.out.println("obj = " + obj);
System.out.println("The message value is " + obj.getMessage());
}
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("applicationContext before : " + applicationContext);
SpringTest.applicationContext = applicationContext;
}
public static ApplicationContext getApplicationContext(){
return applicationContext;
}
public static Object getBean(String name) throws BeansException{
System.out.println("applicationContext = " + applicationContext);
return applicationContext.getBean(name);
}
}
有大神看见上面代码先别喷,我这是错误范例。。。
HelloWorld的代码就不贴了,就是个简单的JavaBean
先说一下,我原先的思路:
启动tomcat容器,加载web.xml,建立整个容器(Servlet容器,这里是tomcat吧)的上下文,ServletContext,这时web.xml有个监听器,就是ContextLoaderListener,监听到这个事件,就会去扫描spring配置文件,默认是applicationContext.xml文件(classpath路径下,idea是Resource下),如果自定义,就应该如web.xml中的context-param标签那般配置,扫描这个指定的Spring配置文件,就会将文件中相应的bean加载,其中实现了ApplicationContextAware的bean类会去执行setApplicationContext()方法,将上下文自动初始化。
看到这个思路有没有反应出来什么?
是的,第一句就暴露出自己的煞笔了,main方法,这是个控制器程序,哪里来的tomcat。。。
好吧,还是说明一下,上面的配置。
这是个Web配置,也就是说是个应用程序的Spring配置,配置好了SpringTest相当于一个Web上下文提供工具(SpringTest命名可以更规范更有可读性,比如SpringContextUnits,当然,其实里面也可有更多静态方法,提供更多的功能,这里只是测试),以后想要获得容器中的bean,直接使用SpringTest.getBean(String)即可。
在web.xml中,前面说过,ContextLoaderListener是用来启动Spring容器,加载Spring上下文的,默认下,会将classpath下的applicationContext.xml文件作为Spring的配置文件,当然,你也可以像web.xml中context-param标签一样,指定路径,不过注意,这里的param-name这一行是不能变得,这是个指定属性值,说明上下文(context)配置(config)文件所在地方(Location)。
Spring配置文件appcontext-service.xml中,要注意,这里一定要将SpringTest这个实现了ApplicationContextAware的类声明为bean,这样,spring在扫描bean后,才回去看哪些bean实现了ApplicationContextAware,才回去将上下文传到这个类的静态对象(即执行setApplicationContext()方法),而且,这个bean声明必须放在其他bean之前(这里的其他bean是指通过该工具类去获得bean实例的bean,比如这里的HelloWorld)。
要想在main方法使用bean,貌似必须加载相应配置文件,具体方式可以查看Spring Bean获取方式。