模拟实现Spring中的注解装配
作者:网络转载 发布时间:[ 2015/12/17 10:12:36 ] 推荐标签:测试开发技术 编程语言
核心注解分析并实现注入的类:
import java.lang.reflect.Field;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import fengzheng.fzAnnotation.MyAutowired;
import java.util.stream.*;
public class FzClassPathXMLApplication {
//xml配置文件中 bean定义的集合
private List<BeanDefine> beanList = new ArrayList<BeanDefine>();
// 存储bean实例和bean的id的对应关系 以便可以根据注解名称找到对应的实例
Map<String, Object> beanInstanceList = new HashMap<String, Object>();
//xml配置文件中 被扫描类的定义的集合 在Spring框架中 直接扫描一个或多个包
List<ScanDefine> scanList = new ArrayList<ScanDefine>();
// 存储被扫描的待注入的实体集合
Map<String, Object> annotationInstanceList = new HashMap<String, Object>();
public FzClassPathXMLApplication(String xmlName) {
ReadXml(xmlName);
//实例化所有定义的bean
BeanInstance();
//实例化所有的待注入类
ScanClassInstance();
//开始根据注解实现依赖注入
InjectAnnotation();
}
/**
* 读取配置文件 收集bean集合和待注入类的集合
* @param xmlFileName
*/
public void ReadXml(String xmlFileName) {
URL xmlPath = this.getClass().getClassLoader().getResource(xmlFileName);
System.out.println(xmlPath);
SAXReader reader = new SAXReader();
try {
Document dom = reader.read(xmlPath);
Element root = dom.getRootElement();
List<Element> iters = root.elements();
Stream<Element> beans = iters.stream().filter(bean -> bean.getName().equals("bean"));
Iterator<Element> iterBeans = beans.iterator();
while (iterBeans.hasNext()) {
Element bean = iterBeans.next();
String id = bean.attributeValue("id");
String clsName = bean.attributeValue("class");
//System.out.println("id:" + id + " class:" + clsName);
BeanDefine bd = new BeanDefine();
bd.setId(id);
bd.setClsName(clsName);
beanList.add(bd);
}
Stream<Element> scanClasses = iters.stream().filter(scan -> scan.getName().equals("component-scan"));
//iters.stream().forEach(scan -> System.out.println(scan.getName()));
Iterator<Element> iterScans = scanClasses.iterator();
while (iterScans.hasNext()) {
Element scan = iterScans.next();
String id = scan.attributeValue("id");
String clsName = scan.attributeValue("class");
ScanDefine sd = new ScanDefine();
sd.setId(id);
sd.setClassName(clsName);
scanList.add(sd);
}
System.out.println("scanList.size():"+scanList.size());
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 收集bean实例
*/
private void BeanInstance() {
for (BeanDefine bd : beanList) {
try {
Object beanInstance = Class.forName(bd.getClsName()).newInstance();
System.out.println(beanInstance.getClass().getName());
beanInstanceList.put(bd.getId(), beanInstance);
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 收集被扫描的待注入的类的实例
*/
private void ScanClassInstance(){
for(ScanDefine sd:scanList){
try {
Object scanInstance = Class.forName(sd.getClassName()).newInstance();
System.out.println(scanInstance.getClass().getName());
annotationInstanceList.put(sd.getId(), scanInstance);
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 循环遍历待注入的类
*/
public void InjectAnnotation() {
Iterator<Map.Entry<String, Object>> iters = annotationInstanceList.entrySet().iterator();
while (iters.hasNext()) {
Map.Entry<String, Object> iter = iters.next();
Object scanInstance = iter.getValue();
InjectField(scanInstance);
}
}
/**
* 注入:把需要注入类中的注解为MyAutowired的字段 注入bean实例
* @param injectClass
*/
private void InjectField(Object injectClass) {
try {
Field[] fields = injectClass.getClass().getDeclaredFields();
for (Field field : fields) {
if (field != null && field.isAnnotationPresent(MyAutowired.class)) {
System.out.println(field.getName());
MyAutowired myAutowired = field.getAnnotation(MyAutowired.class);
String beanName = myAutowired.name();
Object value = null;
if (beanName != null && !beanName.equals("")) {
value = beanInstanceList.get(beanName);
} else {
Class<?> fType = field.getType();
for (String key : beanInstanceList.keySet()) {
if (fType.isAssignableFrom(beanInstanceList.get(key).getClass())) {
value = beanInstanceList.get(key);
break;
}
}
}
field.setAccessible(true);
field.set(injectClass, value);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public Object getScan(String scanName){
return this.annotationInstanceList.get(scanName);
}
}
注解处理类中用到的两个实体类:
package fengzheng.simpleSpring;
public class BeanDefine {
private String id;
private String clsName;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getClsName() {
return clsName;
}
public void setClsName(String clsName) {
this.clsName = clsName;
}
}
package fengzheng.simpleSpring;
public class ScanDefine {
public String id;
public String className;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
}
对这段程序逻辑的解释:
1.首先通过ReadXml()方法读取配置文件beans.xml,找到其中的bean节点和context:component-scan节点,然后把bean节点实例化为BeanDefine,并加入beanList集合,把component-scan节点实例化为ScanDefine,并加入scanList集合;
2.通过BeanInstance()方法,把配置文件中的bean都实例化存储到Map集合beanInstanceList中;
3.通过ScanClassInstance()方法,把配置文件中的component-scan节点(即待注入的类)实例化并处处到Map集合annotationInstanceList中;
4.通过InjectAnnotation()方法,遍历annotationInstanceList集合,为其中的被@MyAutowired注解的字段赋值(即对应的bean的实例)
后调用实现如下:
FzClassPathXMLApplication ctx = new FzClassPathXMLApplication("beans.xml");
Test test =(Test) ctx.getScan("test");
test.Say();
本文内容不用于商业目的,如涉及知识产权问题,请权利人联系SPASVO小编(021-61079698-8054),我们将立即处理,马上删除。
相关推荐
Java性能测试有哪些不为众人所知的原则?Java设计模式??装饰者模式谈谈Java中遍历Map的几种方法Java Web入门必知你需要理解的Java反射机制知识总结编写更好的Java单元测试的7个技巧编程常用的几种时间戳转换(java .net 数据库)适合Java开发者学习的Python入门教程Java webdriver如何获取浏览器新窗口中的元素?Java重写与重载(区别与用途)Java变量的分类与初始化JavaScript有这几种测试分类Java有哪四个核心技术?给 Java开发者的10个大数据工具和框架Java中几个常用设计模式汇总java生态圈常用技术框架、开源中间件,系统架构及经典案例等
更新发布
功能测试和接口测试的区别
2023/3/23 14:23:39如何写好测试用例文档
2023/3/22 16:17:39常用的选择回归测试的方式有哪些?
2022/6/14 16:14:27测试流程中需要重点把关几个过程?
2021/10/18 15:37:44性能测试的七种方法
2021/9/17 15:19:29全链路压测优化思路
2021/9/14 15:42:25性能测试流程浅谈
2021/5/28 17:25:47常见的APP性能测试指标
2021/5/8 17:01:11热门文章
常见的移动App Bug??崩溃的测试用例设计如何用Jmeter做压力测试QC使用说明APP压力测试入门教程移动app测试中的主要问题jenkins+testng+ant+webdriver持续集成测试使用JMeter进行HTTP负载测试Selenium 2.0 WebDriver 使用指南