模拟spring的IoC
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的更多相关文章
- [原]容器学习(一):动手模拟spring的IoC
介绍 学习经典框架的实现原理以及设计模式在其实际中的运用,是非常有必要的,可以让我们更好进行面向对象. 本篇文章就来模拟Spring的IOC功能,明白原理后,可以更好的使用它,进而为进行面向对象提供一 ...
- 容器学习(一):动手模拟spring的IoC
介绍 学习经典框架的实现原理以及设计模式在事实上际中的运用,是很有必要的,能够让我们更好进行面向对象. 本篇文章就来模拟Spring的IOC功能.明确原理后,能够更好的使用它,进而为进行面向对象提供一 ...
- JAVA模拟Spring实现IoC过程(附源码)
前言:本人大四学生,第一次写博客,如果有写得不好的地方,请大家多多指正 一.IoC(Inversion of Control)反转控制 传统开发都是需要对象就new,但这样做有几个问题: 效率低下,创 ...
- 自己动手模拟spring的IOC
我们这里是模拟spring,主要模拟spring中的IOC功能,所以在此我们一样要在service层中定义dao的实例,当然不用new出来,我们就通过spring的IOC把这里的dao层注入进来.不要 ...
- spring的IOC/DI功能实践
一.写在前面: 做这个Demo主要是为了能够更好的理解Spring的原理,看再多的文章,听再多的讲解最终都最好自己去实现一遍,可以将Spring的功能分块实现,最终自然比较容易将各个功能组合起来. 这 ...
- Java-马士兵设计模式学习笔记-工厂模式-用Jdom模拟Spring
一.概述 1.目标:模拟Spring的Ioc 2.用到的知识点:利用jdom的xpath读取xml文件,反射 二.有如下文件: 1.applicationContext.xml <?xml ve ...
- Java反射机制详解(3) -java的反射和代理实现IOC模式 模拟spring
IOC(Inverse of Control) 可翻译为“控制反转”,但大多数人都习惯将它称为“依赖注入”.在Spring中,通过IOC可以将实现类.参数信息等配置在其对应的配置文件中,那么当 需要更 ...
- (反射+内省机制的运用)简单模拟spring IoC容器的操作
简单模拟spring IoC容器的操作[管理对象的创建.管理对象的依赖关系,例如属性设置] 实体类Hello package com.shan.hello; public class Hello { ...
- 尚学堂Spring视频教程(一):模拟Spring
Spring简单的说就是作为控制反转的容器,看这篇文章前需要先搞懂“控制反转和依赖注入“这个设计模式 我们先来模拟Spring,实现用户添加的功能,新建WEB项目”Spring_0100_Abstra ...
随机推荐
- 深度学习课程笔记(八)GAN 公式推导
深度学习课程笔记(八)GAN 公式推导 2018-07-10 16:15:07
- (zhuan) Recurrent Neural Network
Recurrent Neural Network 2016年07月01日 Deep learning Deep learning 字数:24235 this blog from: http:/ ...
- Sublime text 3 汉化教程
首先,需要安装Package Control 启动并进入sublime主界面,打开Sublime Text的控制台(快捷键 ctrl + ~) 然后我们到Package Control官方网站,复制s ...
- EPPlus实战篇——Excel写入
.net core 项目 可以向excel写入任何类型(T)的数据,只要T中的field的[Display(Name = "1233", Description = "# ...
- Qt5学习记录:QString与int值互相转换
1)QString转int 直接调用toInt()函数 例: QString str("100"); int tmp = str.toInt(); 或者: bool ok; QSt ...
- WebBrowser获取完整COOKIE
[DllImport("wininet.dll", CharSet = CharSet.Auto, SetLastError = true)] static extern bool ...
- form提交不刷新,不跳转页面
利用 iframe 标签 ,后台form处理可以返回void <form action="" method="post" target="nm_ ...
- Mybatis中sql语句中的in查询,判断null和size为0的情况
不严谨的写法,可能会报错:in (),这种情况不符合SQL的语法,导致程序报错. 如果简单只做非空判断,这样也有可能会有问题:本来in一个空列表,应该是没有数据才对,却变成了获取全部数据! 所以一个比 ...
- tkinter拦截关闭事件
import tkinter as tk from tkinter import messagebox root = tk.Tk() def on_closing(): if messagebox.a ...
- mint 安装过程
这几天因为各种原因装系统(自己因为双屏不能旋转,输入法界面始终矬,重装2次(应该都是更新内核和更新时包依赖不对的锅,以后屏蔽内核更新和linux-libc-dev这样的更新,要么就新版本出来重装),和 ...