前言:考虑到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);
也能获取上下文并取得配置,但是如上定义更直接明了,简单易使用。