卡进度,卡进度,卡进度了就要多复习,这次我研究了spring-web封装好的监听器源代码,然后就模拟一下对自己的监听器代码进行优化,虽然目前springMVC的进度卡了,这几天也在做一个小项目,希望能在跟着大佬做项目的时候自己能加深对框架的理解。
前几次发了spring集成web以及自定义scl监听器的代码,但是有些地方注释没有标清楚,有些地方的代码没有优化,还是耦合着的。我们从代码上来吧!
1、优化applicationContext.xml文件的读取方式
还记不记得上一次我是怎么在这个监听器类里读取applicationContext.xml文件并创建app容器的?
其实上一次我是直接 ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");这样直接读取它的文件名去创建的,这样的话就耦合住了,如果改动xml配置文件名,相应的就得下到.java文件里改动,这里我是在web.xml文件里利用<context-param>标签创建了一个全局参数并指向“applicationContext.xml”,代码如下:
<!-- 全局初始化参数,使用在自定义监听器类中,注意在使用applicationContext.xml文件名时可以直接在servletContext域里拿到这个contextConfigLocation参量使用就可以了,
当然如果我们要使用人家spring-web框架提供好的监听器的话就必须取这个名字了-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
public class contextLoaderListener implements ServletContextListener {
//上下文初始化时做的动作
public void contextInitialized(ServletContextEvent sce) {
// 获取servletContext域
ServletContext servletContext = sce.getServletContext();
// 通过servletContext获取web.xml里设置的全局参数,
// contextConfigLocation -> applicationContext.xml
String context = servletContext.getInitParameter("contextConfigLocation");
ApplicationContext app = new ClassPathXmlApplicationContext(context);
// set方法存容器
servletContext.setAttribute("app",app);
System.out.println("spring 容器建立成功");
}
}
2、优化获取ServletContext域中已经创建好的容器的方式
之前我们是采用ApplicationContext applicationContext = (ApplicationContext) servletContext.getAttribute("app");的方式利用app这个定义好的容器名去获取容器的,那么如果我直接从ServletContext里拿的话能不能确保直接拿到容器呢?写一个WebServletContextUtils类可以实现。
public class WebServletContextUtils {
// 定义这个类型直接就可以get到spring容器
public static ApplicationContext getWebServletContext(ServletContext servletContext){
return (ApplicationContext) servletContext.getAttribute("app");
}
}
public class UserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
// (1)这里的继承http servlet类,采用的do get方法,就是在服务器部署web应用时就会运行这个方法里的语句也就会相应的创建一个容器。
// ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
// (2)采用获取servletContext上下文的get方法,再用与监听器类中set方法对应的get方法获取应用程序上下文。
// ApplicationContext applicationContext = (ApplicationContext) servletContext.getAttribute("app");
// (3)这里是将get方法放在自己写的WebServletContextUtils.java类里进行调用来得到容器 webServletContext
ApplicationContext webServletContext = WebServletContextUtils.getWebServletContext(servletContext);
UserService u1 = webServletContext.getBean(UserService.class);
u1.show();
}
}
第二张图中的(2)就是我们上次用的方法,(3)与(2)相比我们不需要记住容器的名字,直接拿就好了,优化性也是有的。
3、spring依赖注入自写set方法的一个小插曲
我们知道在bean与bean之间的注入时,采用set注入需要在原java类里写上被注入的类的set方法,那么有没有想过如果这个方法自写的话,你会不会写成private型呢?你肯定不会,私有型无法共享给xml文件的,会报红。
public class UserServiceImpl implements UserService{
private UserDao userDao;
// 注意在依赖注入的过程中,配置文件里的set注入方式,
// 对应的set方法一定要是public类型的,否则xml文件解析不到userDao这个id。
// 刚才用private的类型显示解析不了符号的错误
public void setUserDao(UserDao userDao){
this.userDao = userDao;
}
@Override
public void show() {
userDao.save();
}