尊重原创:原创和源代码地址
项目中的的spring出现问题,不想使用spring框架进行注入,编写一个简单的spring,实现xml解析和类的注入。所有的框架都可以用java项目,用到了java提供的基础类,所以用到的原理也就呢么多(我刚开始工作2个月,说的不对请谅解)。因此spring用到了注入用到java中的反射机制,aop用到了java的代理机制proxy对象。总结一下自己的设计:
设计范围三层:
第一层是实体层,根据自己定义的xml规则抽象除了两个对象实体,一个是实体对象bean(程序中定义为BeanDefineModel),另一个是属性实体对象(程序中定义为ParamDefineModel)。
第二层是xml解析层,既将xml进行解析,生成beanDefineFactory对象的连。(这里采用的第三方的dom4j的jar包)进行解析,将xml解析成一个一个的对象链。
第三层是实例化,并对实例化的对象进行属性注入。ApplicationContext
(本模拟spring用到了dom4j.jar还有commom.collection.jar和common.lang.jar)源码在后面资源中提供。所有的框架开始是定义xml规范,对规范的内容进行解析注入,最终生成一个访问bean的hashMap的接口,xml格式如下:
<?xml version="1.0" encoding="UTF-8"?>
<!--@author chunlei 原创:url-->
<beans>
<bean name="blueHair" class ="com.test.source.Hair">
<property name="color" value="blue"></property>
<property name="hair" value="good"></property>
<property name="stringList">
<list>
<li value="zhang"></li>
<li value="chun"></li>
</list>
</property>
</bean>
<bean name ="body" class ="com.source.Body">
<property name="name" value="zhang"></property>
<property name="hair" ref="blueHair"></property>
</bean>
</beans>
作为bean标签只有name 和class当然后期你可以加上type等属性,不过需要对model解析进行修改,property的属性定义为name,value,ref,list,map,和set。map和set的没有实现,其他的都实现了,会抽时间继续填补自己的框架。其中list标签必须以li来开头,这样li下面可以存在name,value,ref,list等属性,实现param的model的重用。同样在解析和实例化的时候可以使用递归。
在完成这个任务时遇到问题就是在注入的地方,因为利用反射机制寻找到方法可以使用method(methodName,propertyType)来获得方法,不过容易报错,因为我们在xml中注入的时候有可能使用实体类注入,有可能使用接口注入。后来使用了比较麻烦的办法,先拼接方法名,然后获得bean的所有方法,遍历所有的方法根据方法名找到方法,然后找到方法的参数类型,判断是否和注入属性是否相同,若相同则直接调用反射机制进行注入,若不同则得到参数的所有接口,遍历接口判断是否和参数接口相同来进行注入,具体的代码如下:,最终代码在公司,没有拿来,现在的代码是自己回来加班做的,只考虑到实体类注入,下发上去,后期会修改。资源在后面分享,中秋节的时间排满了,还要看solr的源代码等,作业很多。谅解。重要代码,递归注入:
<pre name="code" class="java">package com.test;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
public class ApplicationContext{
private static HashMap<String,Object> hashMap = new HashMap<String,Object>();//用来存放bean对象
public static HashMap<String,Object> getBeanMap(String xmlPath){
List<BeanDefine> beanDefineList = BeanDefineFactory.getBeanDefineList(xmlPath);//获得beanDefineList的
if(CollectionUtils.isNotEmpty(beanDefineList)){
for(BeanDefine beanDefine : beanDefineList){//遍历beanDefineList获得所有的beanDefine
if(beanDefine != null){
String beanName = beanDefine.getBeanName();//以beanName作为key放到beanMap中
Object object = getBeanObject(beanDefine);//将beanDefine转化为bean对象
hashMap.put(beanName, object);
}
}
}
return hashMap;
}
public static Object getBeanObject(BeanDefine beanDefine){
String beanClass = beanDefine.getBeanClass();//获得bean的类型
Object beanObject = getObjectByClass(beanClass);//根据bean对象获得对象
List<ParamDefine> paramDefineList = beanDefine.getPropertyList();//bean获取propertyList
if(CollectionUtils.isNotEmpty(paramDefineList)){
for(ParamDefine paramDefine : paramDefineList){//遍历属性列表进行注入
if(paramDefine != null){
String paramName = paramDefine.getPropertyName();
Object paramObject = getParamObject(paramDefine);//获得paramDefine对象
beanObject = getRegistBeanObject(beanObject,paramName,paramObject);//注入bean对象
}
}
}
return beanObject;
}
public static Object getParamObject(ParamDefine paramDefine){
Object paramObject = null;
String paramValue = paramDefine.getPropertyValue();//注入的是String类型
if(StringUtils.isNotEmpty(paramValue)){
paramObject = new String(paramValue);
return paramObject;
}
String propertyRef = paramDefine.getPropertyRef();//判断注入是否Ref类型
if(StringUtils.isNotEmpty(propertyRef)){
if(hashMap.containsKey(propertyRef)){
paramObject = hashMap.get(propertyRef);
}
return paramObject;
}
List<ParamDefine> paramDefineList = paramDefine.getList();//判断注入是否List类型
if(CollectionUtils.isNotEmpty(paramDefineList)){
List<Object> list = new LinkedList<Object>();
for(ParamDefine tempParamDefine : paramDefineList){
Object tempParamObject = getParamObject(tempParamDefine);
list.add(tempParamObject);
}
return paramObject = list;
}
// Set<ParamDefine> paramDefineSet = paramDefine.getSet();//判断注入是否Set类型
// if(CollectionUtils.isNotEmpty(paramDefineList)){
// object = registObjectBySet(object,paramName,paramDefineList);
// return object;
// }
// Map<String,ParamDefine> paramDefineMap = paramDefine.getMap();//判断是否是Map类型
// if(paramDefineMap != null && paramDefineMap.size() !=0){
// object = registObjectByMap(object,paramName,paramDefineMap);
// return object;
// }
return paramObject;
}
/**
* 使用java反射机制对bean对象进行注入
* @param beanObject bean对象
* @param paramName 属性名称
* @param paramObject 属性参数
* @return
*/
public static Object getRegistBeanObject(Object beanObject,String paramName,Object paramObject){
String methodName = "set" + paramName.substring(0,1).toUpperCase()+paramName.substring(1);//获取方法的名称
System.out.println(paramObject.getClass().toString());
System.out.println(methodName);
try {
Method method = beanObject.getClass().getMethod(methodName, paramObject.getClass());//通过class类型,方法名和参数类型来获得方法
method.invoke(beanObject,paramObject);//java反射调用set方法,进行属性设置
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return beanObject;
}
/**
* 根据xml中bean的class属性值来创建bean对象:这里的bean对象时未被设置属性的对象
* @param classNamee
* @return
*/
public static Object getObjectByClass(String beanClass){//根据ClassName生成对象
Object beanObject = null;
try {
beanObject = Class.forName(beanClass).newInstance();//调用class驱动实例化对象
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return beanObject;
}
}
其中额注入代码有缺陷,等后期整理的更好后在弄,同时让set和map都可以,大体的结构已经设计好了。
分享到:
相关推荐
模拟Spring IOC 自己实现依赖注入 自己的Spring 自己的代码模拟spring的依赖注入 自己写的 绝对独一无二
揭秘spring核心机制, 模拟spring依赖注入
通过java代码模拟spring的依赖注入
NULL 博文链接:https://zmx.iteye.com/blog/688299
模拟spring的xml配置文件注入对象,里面用saxbuilder来解析xml文件。
通过动态代理模拟Spring AOP,通过动态代理模拟Spring AOP
简单的模拟了spring的依赖注入功能,
如何将Spock模拟注入到Spring集成测试中该项目旨在用作示例指南,以说明如何将Spock与Spring(和Spring Boot)结合使用,并结合使用Spring配置和Spock模拟。 有时,您想使用整个Spring上下文进行更完整的集成测试。 ...
模拟 HttpServletRequest和HttpServletResponse类在Web应用单元测试是很方便的。 如何选择这些发布包,决定选用哪些发布包其实相当简单。如果你正在构建Web应用并将全程使用Spring,那么最好就使用单个全部的 ...
NULL 博文链接:https://tedtian.iteye.com/blog/1988917
通过手写模拟,了解扫描逻辑和依赖注入等底层源码工作流程 通过手写模拟,了解初始化机制工作流程 通过手写模拟,了解BeanDefinition、BeanPostProcessor的概念 通过手写模拟,了解Spring AOP的底层源码工作流程
一个全面使用JDK1.8语法的J2EE示例,附带模拟数据库操作和基于注解的Bean注入管理。供J2EE开发新手学习。无需spring,掌握SpringMvc主要的开发思路。
该工程主要是模拟spring中IOC功能,自己模拟实现了简单的依赖注入。导入执行时,只需将文件拷入到自己的工程中即可使用。
第三课:模拟Spring功能 5 第四课:搭建sping的运行环境 8 一、 建立一个新的项目 8 二、 建立spring的配置文件 8 三、 引入spring的jar包 8 四、 测试代码: 8 五、 注意接口的使用: 8 第五课:IOC(DI)配置及应用 ...
3. 如果一切正常,你会看到使用Java集合、XML API,以及反射技术模拟Spring的get注入和自定义的IoC容器实现的例子--get注入了Hello类和一个MyFrame类,并且实例化之后可以运行! 4. 看一下testDemoSpringDI()方法,...
(1)主演示就是一张t_user表,利用常见的用户登录来模拟sql注入对后台数据的侵入 (2)数据库脚本 — postgresql DROP TABLE IF EXISTS "public"."t_user"; CREATE TABLE "public"."t_user" ( "id" int8 NOT ...
假定两个Controller都在同一个工程中。 如果有比较合理的分层设计,这样的需求应该是非常...因为Controller B的实例中,Spring Boot为其进行配置和对象注入,这些准备工作不是简单通过实例化Controller B可以完成。
目的是让您可以轻松地将任何模拟库创建的模拟注入到您的 Spring 测试中。 目前,支持 mockito 和 spock 模拟。 为什么? Spring Boot 仅支持 mockito 作为 mocks 提供者,如果你用 java 编写测试,这很好。 使用 ...
该代码主要用于spring IOC的实现(墨者革离),模拟一个城门叩问的编剧场景
掌握Spring框架相关技术,学会Spring框架技术中依赖注入和面向切面编程的软件开发方法。快速熟悉相关内容,编写基于Spring框架技术的依赖注入和面向切面编程的相关代码,掌握Spring框架技术中依赖注入和面向切面编程...