标签:style http java 使用 os strong
就在前不久,一个资深JAVA经理兼HR跟我说,做Java web的,一定要会Spring,不止是会用,还要深入进去,看看它的实现原理,以及是怎么编写的,对此我表示鸭梨很大,内部结构,原理啥都只能先放着一遍,先来看看Spring是怎么做的。
关于控制反转或者说依赖注入到底是个什么意思,这里就不多加说明了,Spring in Action专业度爆脖主的距离怕有该书作者到脖主的地理位置那么远,还是直接来看看是怎么做的吧
public class DbInfoServlet extends HttpServlet{
public void service(HttpServletRequest request,HttpServletResponse response)
throws ServletException,java.io.IOException{
request.setCharacterEncoding("GBK");
DbInfo dbinfo = new DbInfo();
String result = dbinfo.queryModelInfo();
response.setContentType("text/html;charset=UTF-8");
response.setHeader("Cache-Control", "no-cache");
PrintStream out = new PrintStream(response.getOutputStream());
out.println(result);
}
}
这是上篇中的一个servlet应用,对于类DbInfo 的使用,通过new一个新实例来实现。
public class ModelInfoControl implements Controller {
private ModelInfoService modelInfoService;
@Override
public ModelAndView handleRequest(HttpServletRequest request,HttpServletResponse response)
throws ServletException,java.io.IOException{
request.setCharacterEncoding("GBK");
String result = modelInfoService.queryModelInfo();
response.setContentType("text/html;charset=UTF-8");
response.setHeader("Cache-Control", "no-cache");
PrintStream out = new PrintStream(response.getOutputStream());
out.println(result);
out.flush();
out.close();
return null;
}
public void setModelInfoService(ModelInfoService modelInfoService) {
this.modelInfoService = modelInfoService;
}
}
虽然命名略有不同,但是不影响看出差别,这里ModelInfoService类实例modelInfoService,没有使用new关键字去创建,而且在下方,多出了一个他的set方法。
这是如何实现的,我们呼应一下标题,在这里,创建被调用者实例的工作不在由调用者完成,而是在外部实现后注入调用者,所以说,这里控制反转了或者说,这里依赖注入,那么。新的问题出现了,现在,控制反转到谁头上了,依赖于谁去注入?
暂时让我们忘掉之前的MyProject,忘掉上面的对于依赖注入的说明,来看一个Spring的简单应用:
定义两个接口,斧子和人
public interface Axe {
public String chop();
}
public interface Person {
public void useAxe();
}
定义斧子的实现类
public class StoneAxe implements Axe {
@Override
public String chop() {
// TODO Auto-generated method stub
return "石斧砍柴好慢";
}
}
以及人的实现类
public class Chinese{
private Axe axe;
public void setAxe(Axe axe) {
this.axe = axe;
}
public Axe getAxe() {
return axe;
}
}
最后测试Spring
public class SpringTest {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("bean.xml");
Chinese p = ctx.getBean("chinese",Chinese.class);
System.out.println(p.getAxe().chop());
}
}
输出:石斧砍柴好慢
但是,等等,这是怎么一回事,Chinese里明明是个接口的axe,是怎么变成StoneAxe的实例的!
我们先关注一下chinese实例p的创建。
ApplicationContext ctx = new ClassPathXmlApplicationContext("bean.xml");
Chinese p = ctx.getBean("chinese",Chinese.class);
想到什么没,虽然跟上面的方式不太一样,但是显然这里的p也没通过new关键字创建,而是通过一个叫ctx的ApplicationContext实例创建,而ctx,显然借助了数据文件bean.xml来实现自身的实例化。
我们来看一下bean.xml。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="chinese" class="sun.service.Chinese">
<property name="axe" ref="stoneAxe"/>
</bean>
<bean id="stoneAxe" class="sun.service.StoneAxe"/>
</beans>
这里定义了两个bean Chinese chinese和StoneAxe stoneAxe,而chinese的参数axe是stoneAxe的一个实现。
这下就好理解了,p是ctx所获取的bean chinese,这个Chinese类的实例中,属性axe为bean stoneAxe,看到这里,前面的问题也就呼之欲出了,ApplicationContext类作为了各个Spring实例中被调用实例的控制和注入者,我们将其称呼为容器,装纳bean的容器。
扯远了点,还是回到项目中来,添加容器配置文件applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
</beans>
并在web.xml里对其进行配置
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
定义接口ModelInfoDao和实现类ModelInfoDaoImpl
public interface ModelInfoDao {
//获取模块信息
String queryModelInfo();
}
public class ModelInfoDaoImpl implements ModelInfoDao {
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
public String queryModelInfo(){
String result = "";
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl", "Leon", "orcl");
stmt = conn.createStatement();
rs = stmt.executeQuery("select * from t_model_info");
while(rs.next()){
result =rs.getString("info");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
if(conn != null) {
conn.close();
conn = null;
}
} catch (SQLException e) {
e.printStackTrace();
}
}
return result;
}
}
注册ModelInfoDaoImpl 的实例bean modelInfoDao。
<bean id="modelInfoDao" class="dao.ModelInfoDaoImpl"/>
定义接口ModelInfoService和实现类ModelInfoServiceImpl
public interface ModelInfoService {
String queryModelInfo();
}
public class ModelInfoServiceImpl implements ModelInfoService {
private ModelInfoDao modelInfo;
@Override
public String queryModelInfo() {
String result = modelInfo.queryModelInfo();
return result;
}
public void setDbInfo(ModelInfoDao dbInfo) {
this.modelInfo = dbInfo;
}
public ModelInfoDao getModelInfo() {
return modelInfo;
}
public void setModelInfo(ModelInfoDao modelInfo) {
this.modelInfo = modelInfo;
}
}
注册ModelInfoServiceImpl的实例bean modelInfoServiceImpl,并将bean modelInfoDao作为参数modelInfo注入其中。
<bean id="modelInfoService" class="service.ModelInfoServiceImpl">
<property name="modelInfo" ref="modelInfoDao" />
</bean>
OK,这里,bean的准备都已经做好,只需等候召唤了。
话说,召唤个皮卡丘都要靠精灵球网络控制,前台请求呢
正如其命名,DispatcherServlet类来作为前置控制器,通过拦截接受前台匹配的请求请求,将其调度到指定的控制器中。
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
这里还需要为其添加配置文件,用来指定请求与控制器的关系
注意,这里配置文件命名规则为”servlet-name” + ”-servlet.xml”,存放在WEB-INF下(可通过配置修改命名与存放路径),如此处为dispatcher-servlet.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
</beans>
添加控制器ModelInfoControl
public class ModelInfoControl implements Controller {
private ModelInfoService modelInfoService;
@Override
public ModelAndView handleRequest(HttpServletRequest request,HttpServletResponse response) throws ServletException,java.io.IOException{
request.setCharacterEncoding("GBK");
String result = modelInfoService.queryModelInfo();
response.setContentType("text/html;charset=UTF-8");
response.setHeader("Cache-Control", "no-cache");
PrintStream out = new PrintStream(response.getOutputStream());
out.println(result);
out.flush();
out.close();
return null;
}
public void setModelInfoService(
ModelInfoService modelInfoService) {
this.modelInfoService = modelInfoService;
}
}
并将其在dispatcher-servlet.xml中注册,并将bean modelInfoService作为参数实例注入
<bean name="/modelInfo.htm" class="control.ModelInfoControl">
<property name="modelInfoService">
<ref bean="modelInfoService"/>
</property>
</bean>
修改前台页面请求,这次我们不请求servlet了,我们走Spring这条路
"./dbInfoServlet" —> "modelInfo.htm"
执行项目,看到醒目的首页两个字,开心~
标签:style http java 使用 os strong
原文地址:http://www.cnblogs.com/iSunyu/p/3859878.html