1、新建一个web项目,jdk版本为1.8.0_111,使用 Jsp + Servlet + Model 实现MVC模式,并使用BeanFactory工厂 + xml配置文件 + 反射 来解耦合

  整个web项目的结构如下图:

  

  1.1、编写BeanFactory工厂

package com.oy;

import java.util.HashMap;
import java.util.Map; public class BeanFactory { private static BeanFactory beanFactory = new BeanFactory(); // 用于封装bean实例
private Map<String, Object> map = new HashMap<>(); private BeanFactory() {} public static BeanFactory getInstance() {
return beanFactory;
} /**
* 获取参数name指定的实例,而且每次调用返回的是同一个实例。
* @param name
* @return
*/
public Object getBean(String name) {
Bean bean = (Bean) map.get(name);
if (bean == null) {
// System.out.println("map.get(" + name + "),返回null");
return null;
}
return bean.getBeanInstance();
} /**
* 根据类名反射创建一个新的实例
* @param name
* @return
*/
public Object getNewBean(String name) {
Bean bean = (Bean) map.get(name);
try {
return Class.forName(bean.getbeanClassName()).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return null;
} public void setMap(Map<String, Object> map) {
this.map = map;
} public Map<String, Object> getMap() {
return map;
}
}
package com.oy;

public class Bean {
private String beanName;
private String beanClassName;
private Object beanInstance; public String getBeanName() {
return beanName;
} public void setBeanName(String beanName) {
this.beanName = beanName;
} public String getbeanClassName() {
return beanClassName;
} public void setbeanClassName(String beanClassName) {
this.beanClassName = beanClassName;
} public Object getBeanInstance() {
return beanInstance;
} public void setBeanInstance(Object beanInstance) {
this.beanInstance = beanInstance;
} @Override
public String toString() {
return "Bean [beanName=" + beanName + ", beanClassName=" + beanClassName + ", beanInstance=" + beanInstance
+ "]";
}
}

  1.2、为了在服务器启动时就创建bean实例,写一个监听器 BeanFactoryListener implements ServletContextListener

package com.oy;

import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map; import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener; import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader; public class BeanFactoryListener implements ServletContextListener { public void contextInitialized(ServletContextEvent sce) {
ServletContext sc = sce.getServletContext();
if (sc.getAttribute("beanFactory") != null) {
throw new RuntimeException("beanFactory已经存在!");
}
BeanFactory beanFactory = BeanFactory.getInstance(); // 把所有bean加载进beanFactory
loadBeans(sc, beanFactory); // 把beanFactory添加到ServletContext容器中
// System.out.println("把beanFactory添加到ServletContext容器中");
// System.out.println(beanFactory.getMap());
sc.setAttribute("beanFactory", beanFactory);
// System.out.println(sc.getAttribute("beanFactory"));
} private void loadBeans(ServletContext sc, BeanFactory beanFactory) {
String contextConfigLocation = sc.getInitParameter("contextConfigLocation");
String config = contextConfigLocation.split(":")[1];
InputStream inputStream = BeanFactoryListener.class.getClassLoader().getResourceAsStream(config); SAXReader saxReader = new SAXReader();
try {
Document document = saxReader.read(inputStream);
Element root = document.getRootElement();
@SuppressWarnings("unchecked")
List<Element> list = root.elements(); // 只有map指向beanFactory里面的map,这样每次读一个<bean>就加载一个bean;
// 然后,后面加载的bean就可以使用前面已经加载的bean
beanFactory.setMap(new HashMap<String, Object>());
Map<String, Object> map = beanFactory.getMap(); Bean bean = null;
for (Element e : list) {
String beanName = e.attributeValue("id");
String beanClassName = e.attributeValue("class");
bean = new Bean();
bean.setBeanName(beanName);
bean.setbeanClassName(beanClassName);
bean.setBeanInstance(Class.forName(beanClassName).newInstance());
map.put(beanName, bean);
}
// 如果等所有bean都添加进map后再把map设置给beanFactory,会造成后面加载的bean无法使用前面加载的bean
// beanFactory.setMap(map);
} catch (Exception e) {
e.printStackTrace();
}
}
}

  1.3、beans.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<beans>
<bean id="bookDao" class="com.oy.dao.impl.BookDaoImpl"/>
<bean id="bookService" class="com.oy.service.impl.BookServiceImpl"/>
</beans>

  1.4、web.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5"> <!-- 监听器:初始化beanFactory -->
<listener>
<listener-class>com.oy.BeanFactoryListener</listener-class>
</listener> <!-- beanFactory的配置文件 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:beans.xml</param-value>
</context-param> <servlet>
<servlet-name>BookServlet</servlet-name>
<servlet-class>com.oy.servlet.BookServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>BookServlet</servlet-name>
<url-pattern>/book</url-pattern>
</servlet-mapping>
</web-app>

2、编写web、service和dao层代码进行测试:

  BookServlet类:

package com.oy.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import com.oy.BeanFactory;
import com.oy.entity.Book;
import com.oy.service.BookService; public class BookServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private BookService bookService = (BookService) BeanFactory.getInstance().getBean("bookService"); public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String method = (String) request.getParameter("method");
if ("add".equals(method)) {
add(request, response);
}
} public void add(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("调用servlet层的add()方法。。。");
Book book = new Book();
book.setName((String) request.getParameter("name"));
bookService.add(book);
} public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}

  service层接口和实现类:

package com.oy.service;

import com.oy.entity.Book;

public interface BookService {
void add(Book book);
}
package com.oy.service.impl;

import com.oy.BeanFactory;
import com.oy.dao.BookDao;
import com.oy.entity.Book;
import com.oy.service.BookService; public class BookServiceImpl implements BookService {
private BookDao bookDao = (BookDao) BeanFactory.getInstance().getBean("bookDao"); public void add(Book book) {
System.out.println("调用service层的add()方法。。。");
if (bookDao != null) {
bookDao.add(book);
} else {
System.out.println("bookDao为null");
}
}
}

  dao层接口和实现类:

package com.oy.dao;

import com.oy.entity.Book;

public interface BookDao {
void add(Book book);
}
package com.oy.dao.impl;

import java.util.ArrayList;
import java.util.List; import com.oy.dao.BookDao;
import com.oy.entity.Book; public class BookDaoImpl implements BookDao {
private List<Book> bookList = new ArrayList<>(); public void add(Book book) {
System.out.println("调用dao层的add()方法。。。");
int size = bookList.size();
book.setId(size + 1);
bookList.add(book);
System.out.println("bookList: " + bookList);
}
}

3、项目部署及测试

  3.1、服务器:apache-tomcat-9.0.13。

  3.2、浏览器输入 http://localhost:8080/05_book/book?method=add&name=张三,回车后,再输入 http://localhost:8080/05_book/book?method=add&name=李四,回车。

    控制台打印结果:

    调用servlet层的add()方法。。。
    调用service层的add()方法。。。
    调用dao层的add()方法。。。
    bookList: [Book [id=1, name=张三]]
    调用servlet层的add()方法。。。
    调用service层的add()方法。。。
    调用dao层的add()方法。。。
    bookList: [Book [id=1, name=张三], Book [id=2, name=李四]]

4、注意事项

  根据beans.xml配置文件创建bean实例时,创建顺序是从上到下。如果改变<bean>的顺序,比如像下面这样:

    <beans>
        <bean id="bookService" class="com.oy.service.impl.BookServiceImpl"/>
        <bean id="bookDao" class="com.oy.dao.impl.BookDaoImpl"/>
    </beans>

  则创建bookService实例时依赖注入失败,因为其依赖一个bookDao实例,但是此时容器中还没有bookDao实例。

模拟spring的IoC的更多相关文章

  1. [原]容器学习(一):动手模拟spring的IoC

    介绍 学习经典框架的实现原理以及设计模式在其实际中的运用,是非常有必要的,可以让我们更好进行面向对象. 本篇文章就来模拟Spring的IOC功能,明白原理后,可以更好的使用它,进而为进行面向对象提供一 ...

  2. 容器学习(一):动手模拟spring的IoC

    介绍 学习经典框架的实现原理以及设计模式在事实上际中的运用,是很有必要的,能够让我们更好进行面向对象. 本篇文章就来模拟Spring的IOC功能.明确原理后,能够更好的使用它,进而为进行面向对象提供一 ...

  3. JAVA模拟Spring实现IoC过程(附源码)

    前言:本人大四学生,第一次写博客,如果有写得不好的地方,请大家多多指正 一.IoC(Inversion of Control)反转控制 传统开发都是需要对象就new,但这样做有几个问题: 效率低下,创 ...

  4. 自己动手模拟spring的IOC

    我们这里是模拟spring,主要模拟spring中的IOC功能,所以在此我们一样要在service层中定义dao的实例,当然不用new出来,我们就通过spring的IOC把这里的dao层注入进来.不要 ...

  5. spring的IOC/DI功能实践

    一.写在前面: 做这个Demo主要是为了能够更好的理解Spring的原理,看再多的文章,听再多的讲解最终都最好自己去实现一遍,可以将Spring的功能分块实现,最终自然比较容易将各个功能组合起来. 这 ...

  6. Java-马士兵设计模式学习笔记-工厂模式-用Jdom模拟Spring

    一.概述 1.目标:模拟Spring的Ioc 2.用到的知识点:利用jdom的xpath读取xml文件,反射 二.有如下文件: 1.applicationContext.xml <?xml ve ...

  7. Java反射机制详解(3) -java的反射和代理实现IOC模式 模拟spring

    IOC(Inverse of Control) 可翻译为“控制反转”,但大多数人都习惯将它称为“依赖注入”.在Spring中,通过IOC可以将实现类.参数信息等配置在其对应的配置文件中,那么当 需要更 ...

  8. (反射+内省机制的运用)简单模拟spring IoC容器的操作

    简单模拟spring IoC容器的操作[管理对象的创建.管理对象的依赖关系,例如属性设置] 实体类Hello package com.shan.hello; public class Hello { ...

  9. 尚学堂Spring视频教程(一):模拟Spring

    Spring简单的说就是作为控制反转的容器,看这篇文章前需要先搞懂“控制反转和依赖注入“这个设计模式 我们先来模拟Spring,实现用户添加的功能,新建WEB项目”Spring_0100_Abstra ...

随机推荐

  1. (zhuan) Prioritized Experience Replay

    Prioritized Experience Replay JAN 26, 2016 Schaul, Quan, Antonoglou, Silver, 2016 This Blog from: ht ...

  2. ngnix简介以及如何实现负载均衡原理

    1 负载均衡 先来简单了解一下什么是负载均衡,单从字面上的意思来理解就可以解释N台服务器平均分担负载,不会因为某台服务器负载高宕机而某台服务器闲置的情况.那么负载均衡的前提就是要有多台服务器才能实现, ...

  3. HDU 5459 Jesus Is Here(递推)

    http://acm.hdu.edu.cn/showproblem.php?pid=5459 题意: S(1) = c,S(2) = ff, S(3) = cff,之后S(i) = S(i-1)+S( ...

  4. JavaScript运行机制详解

    JavaScript运行机制详解   var test = function(){ alert("test"); } var test2 = function(){ alert(& ...

  5. 设置电脑中的某个程序不弹出UAC用户控制提示的方法

    有用户发现在电脑开机后总是会弹出UAC用户账户控制窗口,这是因为电脑中的某个程序设置了开机启动,这样就会在开机后启动该程序时出现UAC提示.如果想要省略该提示,可以在电脑中设置该程序不弹出UAC用户控 ...

  6. python连接MongoDB(无密码无认证)

    无密码无认证下连接 from pymongo import MongoClient host = '127.0.0.1' # 你的ip地址 client = MongoClient(host, ) # ...

  7. 前端阶段_div以及css介绍

    1.div div是html的一个标签,是块级元素,单独使用没有意义,必须结合css来使用,进行网页布局 2.span span是一个html标签,是一个内联元素,主要对括起来的内容进行修饰 3.&l ...

  8. CC4 表达方式----输赢

    “我要赢,不管付出什么,我一定要赢!”当我赢得时候,“我赢了!(欢呼)”.当我输的时候“不,我不要输.不开心.(垂头丧气)”.这样的场景你是否熟悉呢?我的一生都在经历输赢.以前我会为了赢一场游戏,花费 ...

  9. 在docker 容器中安装命令

    apt-get update ##跟新 //vi apt install vim //weget apt install weget //yum apt install yum //ifconfig ...

  10. Codeforces 984 D - XOR-pyramid

    D - XOR-pyramid 思路: 区间dp dp[l][r]表示ƒ([l, r])的值 显然,状态转移方程为dp[l][r] = dp[l][r-1] ^ dp[l+1][r] 初始状态dp[i ...