简单模拟spring装载注入bean原理
来源:互联网 发布:ios sql 编辑:程序博客网 时间:2024/05/22 15:59
简单模拟spring装载注入bean原理
前言:自己工作时间也将近9个月了,但还没系统学习过spring的知识,近来跟着马士兵老师的spring2.5的视频学,一步一个脚印的向前走。
主要步骤:
一 将需要被加载的类放入beans.xml中
二 通过jdom读取xml配置
三 通过反射机制,将beans.xml中对应类加载进来
beans.xml文件如下:
<beans> <bean id="userDAO" class="org.zeng.dao.impl.UserDAOImpl" /> <bean id="userService" class="org.zeng.service.UserService"> <property name="userDAO" bean="userDAO"/> </bean></beans>
UserService类代码如下:
package org.zeng.service;import org.zeng.dao.UserDAO;import org.zeng.dao.impl.UserDAOImpl;import org.zeng.model.User;public class UserService { private UserDAO userDAO; public UserDAO getUserDAO() { return userDAO; } public void setUserDAO(UserDAO userDAO) { this.userDAO = userDAO; } public void add(User u) { this.userDAO.save(u); }}
#读取xml文件,及利用反射机制,加载类的代码:
package org.zeng.spring;import java.io.IOException;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.util.HashMap;import java.util.List;import java.util.Map;import org.jdom.Document;import org.jdom.Element;import org.jdom.JDOMException;import org.jdom.input.SAXBuilder;public class ClassPathXMLApplicationContext implements BeanFactory { private Map<String, Object> beans = new HashMap<String, Object>(); public ClassPathXMLApplicationContext() throws Exception { SAXBuilder sb = new SAXBuilder(); Document doc = sb.build("src/beans.xml"); // 构造文档对象 Element root = doc.getRootElement(); // 获取根元素 List list = root.getChildren("bean");// 先遍历所有的bean,放入beans的map对象中 for (int i = 0; i < list.size(); i++) { Element element = (Element) list.get(i); String id = element.getAttributeValue("id"); String clazz = element.getAttributeValue("class"); Object o = Class.forName(clazz).newInstance(); beans.put(id, o); } for (int i = 0; i < list.size(); i++) { //在遍历一次xml文件,将含有property元素的bean的属性bean也装载进来(重复扫描,需要优化) Element element = (Element) list.get(i); String id = element.getAttributeValue("id"); String clazz = element.getAttributeValue("class"); Object o = Class.forName(clazz).newInstance(); List list1 = element.getChildren("property"); for (int j = 0; j < list1.size(); j++) { Element e = (Element) list1.get(j); String name = e.getAttributeValue("name"); String bean = e.getAttributeValue("bean"); // userDAO Object object = beans.get(bean);// userDAOImpl的实例 System.out.println(object); String methodName = "set" + name.substring(0, 1).toUpperCase() + name.substring(1, name.length()); Method m = o.getClass().getMethod(methodName, object.getClass().getInterfaces()[0]); //第二个参数是参数类型,即获取该类实现的接口的类型 m.invoke(o, object); beans.put(id, o); } } } public Object getBean(String beanName) { return beans.get(beanName); }}
该类实现的接口(bean工厂)代码:
package org.zeng.spring;import java.io.IOException;import org.jdom.JDOMException;public interface BeanFactory { public Object getBean(String beanName);}
总结: spring其中的一个重要核心IOC控制反转
(也基本同于与DI依赖注入
),大体是说,一些常被用到的类的实现,不需要开发者自己去控制,而全部交给sprintContext(理解为运行环境)去控制。
下面说一说自己理解的好处:
- 一般的,一个项目中至少有
实体类层
(Entity层)、业务逻辑层
(Service层)、数据访问层
(DAO层)这三层,而每层会有很多类,且这些类的成员属性也可能是其他类。如上代码,UserService下有UserDAO类型的属性,如果按照传统的方法,需要先new UserService()记为对象s,再new UserDAO()记为对象d,然后再将d对象set到对象s中,才能调用d对象的save方法!(很繁琐)。如果将这些类都配置在文件中,每次项目移动时一一的去装载这些类,放入到容器中,什么时候需要,什么时候取就可以了,没必要再new新的对象了。 - 在
面向接口编程
时,比如UserDAO的接口是专门操作User对象CRUD的接口,而实现类UserDAOImpl1确可以是mysql,或者是oracle的方式。
如果要切换数据库环境时,对访问数据层DAO来讲有3种方法:
(1). 要新增一个对应实现类UserDAOImpl2,并将调用UserDAO1地方全部改为调用UserDAO2。这样就会要改很多处代码,可能增加新的bug,显得并不安全。
(2). 干脆将UserDAOImpl2的代码完全copy到UserDAOImpl1上替换到原来的内容。即使将原来的内容进行备份,但对整个代码管理角度来讲,这种做法很不优雅。
(3). 在spring的配置文件中,将对UserDAO1的配置改为UserDAO2的配置(修改bean的路径即可)。这种是最好的做法,很简单,对源代码的改变也是最小的。
附注: 以上列出的是核心代码,还有User实体类,UserDAO接口,及其实现类UserDAOImpl代码,全部源代码在我的github上
0 0
- 简单模拟spring装载注入bean原理
- spring依赖注入原理的简单模拟
- spring 注入简单模拟
- Spring笔记——模拟spring的bean管理原理以及依赖注入原理
- spring Bean装载顺序
- Spring简单配置-基于工厂模式装载bean
- Spring中Bean的简单属性注入
- spring之BeanFactory创建bean原理模拟
- 模拟spring的依赖注入原理
- 模拟spring框架注入实现原理
- java简单模拟Spring的依赖注入
- spring的管理bean和依赖注入的原理剖析
- Spring的bean注入
- Spring自动注入Bean
- Spring注入内部Bean
- servlet spring bean注入
- SPring Bean注入 job
- Spring注入Bean
- Android 开源框架Universal-Image-Loader完全解析(二)--- 图片缓存策略详解
- AQS简介
- KNN算法
- 外网访问OpenWrt
- BASIC HTTP AUTHENTICATION ON ANDROID
- 简单模拟spring装载注入bean原理
- 2015年十大热门Android开源新项目
- Leetcode ☞ 83. Remove Duplicates from Sorted List
- Android 开源框架Universal-Image-Loader完全解析(三)---源代码解读
- 输出最大数和第二大数
- 1010. Radix (25)
- 高效的使用okhttp
- 深入分析Java ClassLoader原理
- Ubuntu Remmina 远程桌面提示 “无法连接到RDP服务器”