前言:考虑到Spring的强大是尽人皆知的,所以能用就不必造轮子了,只需要改造即可。
1、web中如何控制ApplicationContext
在spring框架整合下,自己写的代码中要使用ApplicationContext是不方便的,但是在org.springframework.web.context.support.WebApplicationContextUtils 中有一方法 getWebApplicationContext
(
ServletContext sc)
可以得到ApplicationContext引用;但此方法有一参数ServletContext,它是Servlet容器提供的上下文,所以非Servlet环境下是得不到的。
我们可以定义一个servlet,该servlet配置为被容器第一个加载,它可以得到ServletContext,从而得到ApplicationContext的引用
import org.springframework.context.ApplicationContext;
public class SpringBeanProxy {
private static ApplicationContext applicationContext;
public synchronized static void setApplicationContext(ApplicationContext arg) {
applicationContext = arg;
}
public static Object getBean(String beanName){
return applicationContext.getBean(beanName);
}
}
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import org.springframework.web.context.support.WebApplicationContextUtils;
import SpringBeanProxy;
public class SpringBeanInitServlet extends HttpServlet {
public void init(ServletConfig arg) throws ServletException {
SpringBeanProxy.setApplicationContext(WebApplicationContextUtils.getWebApplicationContext(arg.getServletContext()));
}
}
在web.xml中配置如下,即可
<listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> <servlet> <servlet-name>SpringBeanInitServlet</servlet-name> <servlet-class> SpringBeanInitServlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet>
由于listener先于servlet加载,所以可以确保SpringBeanInitServlet加载时spring已经初始化好了,如果你使用的是servlet加载spring就要注意调整这两个servlet的启动顺序了。代码中使用 SpringBeanProxy.getBean("bean name")即可得到bean实例。
还有其他方式,如
从指定目录加载:
ApplicationContext context = new FileSystemXmlApplicationContext("applicationContext.xml");
从classpath路径加载:
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml")
2、web中如何控制基于ApplicationContext的配置文件读取信息值
关于程序中加载spring,自定义类实现spring 配置文件中通配符${jdbc.name}类似的正确解析;但是代码里如何使用读取到的配置文件呢?读源码 org.springframework.beans.factory.config.PropertyPlaceholderConfigurer 以及向上找父类和接口会发现,配置都定义好了,只是 protected Properties[] localProperties;
是继承使用,没法调用。
于是就只定义啦,配置如下:
<bean id="propertyConfigurer" class="com.jd.app.server.util.AutoPorpertiesConfigurer"> <property name="locations"> <list> <value>classpath:XXX.properties</value> </list> </property> <property name="propValueController" ref="genePropValueController"/> <property name="fileEncoding" value="GBK" /> </bean>
具体定制如下:
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
/**
* Created by on 2016/7/14.
*/
public class AutoPorpertiesConfigurer extends PropertyPlaceholderConfigurer {
private static Map<String,Object> ctxPropertiesMap;
private PropValueController propValueController;
private PropValueController defaultPropValueController = new DefaultPropValueController();
@Override
protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess, Properties props) throws BeansException {
super.processProperties(beanFactoryToProcess, props);
ctxPropertiesMap = new HashMap<String,Object>();
if (propValueController==null)
propValueController = defaultPropValueController;
long index=0;
for (Object key : props.keySet()) {
String keyStr = key.toString();
Object value = propValueController.transform(index,keyStr,props.getProperty(keyStr));
ctxPropertiesMap.put(keyStr, value);
index++;
}
}
public static Object getContextProperty(String name) {
return ctxPropertiesMap.get(name);
}
public void setPropValueController(PropValueController propValueController) {
this.propValueController = propValueController;
}
}
/**
* 配置值转化处理
*/
interface PropValueController{
public Object transform(long index, String key, String value) throws BeansException;
}
/**
* 配置默认返回原string
*/
class DefaultPropValueController implements PropValueController{
@Override
public Object transform(long index, String key, String value) throws BeansException {
return value;
}
此类即完成了PropertyPlaceholderConfigurer的任务,同时又提供了上下文properties访问的功能;于是在Spring配置文件中把PropertyPlaceholderConfigurer改成AutoPorpertiesConfigurer 。
PropValueController 接口可以为以后方便定制属性文件值转换灵活使用;
定义使用即可:
String gene = (String) propertyConfigurer.getContextProperty(cateid);
其实,通过
ServletContext servletContext = servlet.getServletContext();
WebApplicationContext wc = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);
也能获取上下文并取得配置,但是如上定义更直接明了,简单易使用。