Spring依赖注入 --- 模拟实现
Spring依赖注入 --- 模拟实现
面向接口编程,又称面向抽象编程,
数据库如果发生更改,对应的数据访问层也应该改变
多写几个实现,需要用谁的时候在service里new谁就可以了
面向抽象编程的好处就是灵活。
创建用户实体类,
/ImitateSpring/src/yuki/spring/imitate/pojo/User.java
package yuki.spring.imitate.pojo;
public class User {
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
/ImitateSpring/src/yuki/spring/imitate/service/UserService.java
package yuki.spring.imitate.service;
import yuki.spring.imitate.dao.UserDAO;
import yuki.spring.imitate.pojo.User;
public class UserService {
private UserDAO userDAO/* = new UserDAOImpl()*/;
public UserDAO getUserDAO() {
return userDAO;
}
public void setUserDAO(UserDAO userDAO) {
this.userDAO = userDAO;
}
public void add(User u){
this.userDAO.save(u);
}
}
/ImitateSpring/src/yuki/spring/imitate/dao/UserDAO.java
package yuki.spring.imitate.dao;
import yuki.spring.imitate.pojo.User;
/*public class UserDAO {
public void save(User u){
System.out.println("user saved...");
}
}*/
public interface UserDAO {
void save(User u);
}
/ImitateSpring/src/yuki/spring/imitate/dao/impl/UserDAOImpl.java
package yuki.spring.imitate.dao.impl;
import yuki.spring.imitate.dao.UserDAO;
import yuki.spring.imitate.pojo.User;
public class UserDAOImpl implements UserDAO {
@Override
public void save(User u) {
System.out.println("user saved...");
}
}
之前的new很多DAO的解决方式是写工厂方法
现在,要新建一个总的工厂,把消息写在工厂文件中
用jdom解析xml,反射创建对象
引入jar包,jdom-2.0.5.jar
/ImitateSpring/src/yuki/spring/imitate/xml/test.xml
<?xml version="1.0" encoding="UTF-8"?>
<HD>
<disk name="C">
<capacity>8G</capacity>
<directories>200</directories>
<files>1580</files>
</disk>
<disk name="D">
<capacity>10G</capacity>
<directories>500</directories>
<files>3000</files>
</disk>
</HD>
/ImitateSpring/src/yuki/spring/imitate/spring/ClassPathXmlApplicationContext.java
package yuki.spring.imitate.xml;
import java.util.List;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.input.SAXBuilder;
public class Sample1 {
public static void main(String[] args) throws Exception {
SAXBuilder saxBuilder = new SAXBuilder();
Document document = saxBuilder.build(
/*Sample1.class.getClassLoader().getResourceAsStream("/text.xml")*/
"D:/Workspaces/Eclipse/ImitateSpring/bin/yuki/spring/imitate/xml/test.xml");
Element root = document.getRootElement();
List<Element> elements = root.getChildren();
for(Element element : elements){
String name = element.getAttributeValue("name");
String capacity = element.getChildText("capacity");
String directories = element.getChildText("directories");
String files = element.getChildText("files");
System.out.println("磁盘信息:");
System.out.println("分区盘符:" + name);
System.out.println("分区容量:" + capacity);
System.out.println("目录数:" + directories);
System.out.println("文件数:" + files);
System.out.println("------------------------------");
}
}
}
运行结果如下:
磁盘信息: 分区盘符:C 分区容量:8G 目录数:200 文件数:1580 ------------------------------ 磁盘信息: 分区盘符:D 分区容量:10G 目录数:500 文件数:3000 ------------------------------
可以把bean作为另一个bean的属性注入
/ImitateSpring/src/beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<bean id="u" class="yuki.spring.imitate.dao.impl.UserDAOImpl"></bean>
<bean id="userService" class="yuki.spring.imitate.service.UserService">
<property name="userDAO" bean="u"></property>
</bean>
</beans>
/ImitateSpring/src/yuki/spring/imitate/spring/BeanFactory.java
package yuki.spring.imitate.spring;
public interface BeanFactory {
Object getBean(String name);
}
/ImitateSpring/src/yuki/spring/imitate/spring/ClassPathXmlApplicationContext.java
package yuki.spring.imitate.spring;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.input.SAXBuilder;
public class ClassPathXmlApplicationContext implements BeanFactory {
private Map<String, Object> beans = new HashMap<String, Object>();
public ClassPathXmlApplicationContext() throws Exception {
SAXBuilder saxBuilder = new SAXBuilder();
Document document = saxBuilder.build(
"D:/Workspaces/Eclipse/ImitateSpring/bin/beans.xml");
Element root = document.getRootElement();
List<Element> elements = root.getChildren();
for(Element element : elements){
String id = element.getAttributeValue("id");
String clazz = element.getAttributeValue("class");
System.out.println(id + " : " + clazz);
Object o = Class.forName(clazz).newInstance();
beans.put(id, o);
for(Element propertyElement : element.getChildren("property")){
String name = propertyElement.getAttributeValue("name");
String bean = propertyElement.getAttributeValue("bean");
Object beanObject = beans.get(bean);
String methodName = "set" + name.substring(0, 1).toUpperCase() + name.substring(1);
System.out.println("method name = " + methodName);
Method m = o.getClass().getMethod(methodName, beanObject.getClass().getInterfaces()[0]);
m.invoke(o, beanObject);
}
}
}
@Override
public Object getBean(String name){
return beans.get(name);
}
}
通过JUnit,可以新建测试类

/ImitateSpring/test/yuki/spring/imitate/service/UserServiceTest.java
package yuki.spring.imitate.service;
import org.junit.Test;
import yuki.spring.imitate.pojo.User;
import yuki.spring.imitate.spring.BeanFactory;
import yuki.spring.imitate.spring.ClassPathXmlApplicationContext;
public class UserServiceTest {
@Test
public void testAdd() throws Exception {
BeanFactory factory = new ClassPathXmlApplicationContext();
UserService service = (UserService) factory.getBean("userService");
/*UserDAO userDAO = (UserDAO) factory.getBean("u");
service.setUserDAO(userDAO);*/
User u = new User();
service.add(u);
}
}
运行结果如下:
u : yuki.spring.imitate.dao.impl.UserDAOImpl userService : yuki.spring.imitate.service.UserService method name = setUserDAO user saved...
术语解释:
控制反转(IOC)、依赖注入(DI)
本来应该自己控制的,交给容器控制,可以实现随意装配
本文参考了[尚学堂马士兵_Spring_模拟Spring]的公开课程
更多好文请关注:http://www.cnblogs.com/kodoyang/
Spring依赖注入 --- 模拟实现的更多相关文章
- (转)编码剖析Spring依赖注入的原理
http://blog.csdn.net/yerenyuan_pku/article/details/52834561 Spring的依赖注入 前面我们就已经讲过所谓依赖注入就是指:在运行期,由外部容 ...
- Spring依赖注入(IOC)那些事
小菜使用Spring有几个月了,但是对于它的内部原理,却是一头雾水,这次借着工作中遇到的一个小问题,来总结一下Spring. Spring依赖注入的思想,就是把对象交由Spring容器管理,使用者只需 ...
- Spring依赖注入三种方式详解
在讲解Spring依赖注入之前的准备工作: 下载包含Spring的工具jar包的压缩包 解压缩下载下来的Spring压缩包文件 解压缩之后我们会看到libs文件夹下有许多jar包,而我们只需要其中的c ...
- Spring依赖注入:注解注入总结
更多11 spring 依赖注入 注解 java 注解注入顾名思义就是通过注解来实现注入,Spring和注入相关的常见注解有Autowired.Resource.Qualifier.S ...
- Spring 依赖注入,在Main方法中取得Spring控制的实例
Spring依赖注入机制,在Main方法中通过读取配置文件,获取Spring注入的bean实例.这种应用在实训的时候,老师曾经说过这种方法,而且学Spring入门的时候都会先学会使用如何在普通的jav ...
- Spring依赖注入 --- 简单使用说明
Spring依赖注入 --- 简单使用说明 本文将对spring依赖注入的使用做简单的说明,enjoy your time! 1.使用Spring提供的依赖注入 对spring依赖注入的实现方法感兴趣 ...
- Java Web系列:Spring依赖注入基础
一.Spring简介 1.Spring简化Java开发 Spring Framework是一个应用框架,框架一般是半成品,我们在框架的基础上可以不用每个项目自己实现架构.基础设施和常用功能性组件,而是 ...
- Spring依赖注入的三种方式
看过几篇关于Spring依赖注入的文章,自己简单总结了一下,大概有三种方式: 1.自动装配 通过配置applicationContext.xml中的标签的default-autowire属性,或者标签 ...
- spring依赖注入源码分析和mongodb自带连接本地mongodb服务逻辑分析
spring依赖注入本质是一个Map结构,key是beanId,value是bean对应的Object. autowired是怎么将定义的接口与对应的bean类建立联系? <bean name= ...
随机推荐
- C++时间戳转化(涉及GMT CST时区转化)
问题由来 时间戳转换(时间戳:自 1970 年1月1日(00:00:00 )至当前时间的总秒数.) #include <stdio.h> #include <time.h> i ...
- 【USACO】【section1.1】Your Ride Is Here
以前的账号忘记了,只能从头了. 入门题不解释,就是sumg和sumc初始值置1不能置0.开始享用一个循环计算出sumg和sumc,其实两个数组最大程度为6,节省不了什么时间. /*ID:Moment1 ...
- Java —— 枚举(Enum)的使用
想用枚举,忘了具体的用法了.网上查了下,发现了个不错的网址.分享一下. http://docs.oracle.com/javase/tutorial/java/javaOO/enum.html
- 了解thinkphp(二)
ThinkPHP的核心文件: Library文件夹下的Think文件夹目录 ThinkPHP的入口文件是: ThinkPHP.php , 我们在创建项目时都要引入这个入口文件!!! 一 , 项目的部署 ...
- windows 创建SSH Key
1. 安装git,从程序目录打开 "Git Bash" (百度或用这个连接http://pan.baidu.com/s/1dDJCx9n 下载) 2. 键入命令:ssh-keyge ...
- 无锁编程(六) - seqlock(顺序锁)
seqlock(顺序锁) 用于能够区分读与写的场合,并且是读操作很多.写操作很少,写操作的优先权大于读操作. seqlock的实现思路是,用一个递增的整型数表示sequence.写操作进入临界区时,s ...
- Z-偏移量
使用Z-偏移量 在一个三维场景中,我们可以对共面的多边形使用z-偏移量来使它们不再共面.这项技术通常用于在场景中正确的显示阴影.例如,一堵墙上的阴影与这堵墙的深度值是相同的,如果我们先渲染了墙再来渲染 ...
- Qt之等待提示框(QTimer)
简述 上节讲述了关于QPropertyAnimation实现等待提示框的显示,本节我们使用另外一种方案来实现-使用定时器QTimer,通过设置超时时间定时更新图标达到旋转效果. 简述 效果 资源 源码 ...
- Qt之设置QWidget背景色
简述 QWidget是所有用户界面对象的基类,这意味着可以用同样的方法为其它子类控件改变背景颜色. Qt中窗口背景的设置,下面介绍三种方法. 使用QPalette 使用Style Sheet 绘图事件 ...
- Hadoop实战课程
Hadoop生态系统配置Hadoop运行环境Hadoop系统架构HDFS分布式文件系统MapReduce分布式计算(MapReduce项目实战)使用脚本语言Pig(Pig项目实战)数据仓库工具Hive ...