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. JQ插入节点方法

    1.append()  appendTo()  prepend() prependTo() 2. before() insertBefore() after() insertAfter()

  2. BZOJ4018: 小Q的幻想之乡

    Description 背景 有一天,小Q梦见自己来到了理想国的幻想之乡. 描述 有一天,小Q梦见自己来到了理想国的幻想之乡.幻想乡有无穷户居民,第i个家庭住在编号为i的房屋里,编号从1开始,到正无穷 ...

  3. 配置和运行 MatchNet CVPR 2015 MatchNet: Unifying Feature and Metric Learning for Patch-Based Matching

    配置和运行 MatchNet CVPR 2015 GitHub: https://github.com/hanxf/matchnet 最近一个同学在配置,测试这个网络,但是总是遇到各种问题. 我也尝试 ...

  4. (转载)winform图片标尺控件

    最近要做个winform的东西,要在里面集成一个类似Windows自带画图的标尺功能,还要能在图片上画矩形框.在网上找了好久也没找到写好的控件,无奈自己做了一个. 目前还有些bug,这里先做个分享.( ...

  5. CIFAR-10与ImageNet图像识别

    2.1.2 下载CIFAR-10 数据 python cifar10_download.py # Copyright 2015 The TensorFlow Authors. All Rights R ...

  6. yyyy-MM-dd'T'HH:mm:ss.SSS'Z'即UTC时间,与String日期转换

    本文为博主原创,未经允许不得转载: 最近在使用一个时间插件的时候,接收到的时间格式是 ’2017-11-27T03:16:03.944Z’ ,当我进行双向数据绑定的时候,由后台传过来的时间绑定到时间 ...

  7. react native 渐变组件 react-native-linear-gradient

    github:  https://github.com/react-native-community/react-native-linear-gradient 安装:yarn add  react-n ...

  8. _event_team

    EventId 事件ID TeamId 事件玩家分组,仅传送(0为联盟 1为部落)对线(防守为1,进攻为2),自定义阵营(_faction表自定义阵营ID),公会(公会guid) TeamName 事 ...

  9. JAVA关于泛型的笔记

    1.Java SE 5.0中增加泛型机制的主要原因是为了满足在1999年制定的最早的Java规范需求之一(JSR 14). 2.使用泛型机制编写的程序代码要比那些杂乱的使用Object变量,然后再进行 ...

  10. 【C#】采用OleDB读取Excel文件转DataTable

    using System; using System.Data; using System.Data.OleDb; using System.IO; using System.Linq; using ...