S2SH中都是层层注入,action交给Spring托管。即,往Struts的Action中注入Service,往Service中又注入DAO,这个都是通过配置完成的。
经过对Spring原理和源码的研究,发现,可以写一个SpringBeanFactory.java,自己实现获取bean实例的功能。下面分两种情况进行说明。
情况1:在web.xml中已经配置Spring的applicationContext文件
一般我们是这么配置Spring的:
<!-- spring上下文 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:/service.xml</param-value> </context-param> <!-- 启动监听 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
此时,可以通过
org.springframework.web.context.ContextLoaderListener来获取bean。关键代码如下:
public SpringBeanFactory{ private static ApplicationContext ctx; /** 通过ContextLoaderListener取得ctx */ public static void initApplicationContext(){ ctx=ContextLoaderListener.getCurrentWebApplicationContext(); } /** 通过泛型方法取得bean实例 */ public static <T> T getBean(String name){ if(ctx==null){ initApplicationContext(); } return (T) ctx.getBean(name); } }
这样,无论在Servlet,还是在普通Java类中,都可以调用getBean()方法获取Spring托管的Bean对象了。
情况2:在web.xml中未配置Spring
此时,我们可以自己写程序去加载xml文件,生成ctx,关键代码如下:
public class SpringBeanFactory { private static ApplicationContext ctx = null; public static void initApplicationContext(){ if (ctx == null) { ctx = new ClassPathXmlApplicationContext( new String[] { "classpath:applicationContext-Comm.xml", "classpath:applicationContext-B2BPL.xml" }); } } }
其本质和第一种情况是一样的,如果自己再建一个StartListener.java,如下:其本质和第一种情况是一样的,如果自己再建一个StartListener.java,如下:
public class StartListener implements ServletContextListener { @Override public void contextInitialized(ServletContextEvent event) { event.getServletContext().log("Start initing ApplicationContext..."); SpringBeanFactory.initApplicationContext(); } }
并把StartListener.java配置在web.xml中,这样就可以在服务器启动的时候得到ctx了。并把StartListener.java配置在web.xml中,这样就可以在服务器启动的时候得到ctx了。