快速手写xml的IOC容器-精简版-简易实现demo-免费提供源码下载
【摘要】
手写IOC
手写XMLIOC流程MyIocApplicationXmlContext解析xml定义bean以及创建bean信息定义ns图getbean的ns图定义BeanDefinition (b...
前言
手写XMLIOC流程
- 新建maven工程
- 新建package(包)分层
-创建model
//class
package com.kang.model;
/**
* @Description TODO
* @ClassName Class
* @Author 康世行
* @Date 19:46 2022/6/10
* @Version 1.0
**/
public class Class {
private String className;
public String getClassName() {
return className;
}
@Override
public String toString() {
return "Class{" +
"className='" + className + '\'' +
'}';
}
public void setClassName(String className) {
this.className = className;
}
}
//student
package com.kang.model;
/**
* @Description TODO
* @ClassName Student
* @Author 康世行
* @Date 19:46 2022/6/6
* @Version 1.0
**/
public class Student {
private Integer age;
private String name;
@Override
public String toString() {
return "Student{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
//theater
package com.kang.model;
/**
* @Description TODO
* @ClassName Theater
* @Author 康世行
* @Date 19:45 2022/6/10
* @Version 1.0
**/
public class Theater {
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Theater{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
-
在resources 目录下新建 test.xml
-
在test.xml 定义bean
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="student" class="com.kang.model.Student" scope="prototype">
<property name="age" value="1"/>
<property name="name" value="康世行"/>
</bean>
<bean id="theater" class="com.kang.model.Theater">
<property name="name" value="快快快"/>
<property name="age" value="22"/>
</bean>
<bean id="class" class="com.kang.model.Class">
<property name="className" value="阶梯教室"/>
</bean>
</beans>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
MyIocApplicationXmlContext
解析xml定义bean以及创建bean信息定义ns图
getbean的ns图
getbean(获取bena)
createBean(创建bean)
创建对象实例并且赋值
首字母大写
定义BeanDefinition (bean定义信息实体)
存储bean定义的信息:对象名(beanName) class对象 属性值 scope(单例/原型)
package com.kang.myIoc;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.lang.Nullable;
/**
* @Description bean 定义,用于存储bean 配置信息
* @ClassName BeanDefinition
* @Author 康世行
* @Date 19:49 2022/6/20
* @Version 1.0
**/
public class BeanDefinition {
String SCOPE_SINGLETON = "singleton";
String SCOPE_PROTOTYPE = "prototype";
//beanname
private String beanName;
//bean属性值
@Nullable
private MutablePropertyValues propertyValues;
//作用域
private String scope;
//class对象
private Class beanClass;
public String getBeanName() {
return beanName;
}
public void setBeanName(String beanName) {
this.beanName = beanName;
}
@Nullable
public MutablePropertyValues getPropertyValues() {
return propertyValues;
}
public void setPropertyValues(@Nullable MutablePropertyValues propertyValues) {
this.propertyValues = propertyValues;
}
public String getScope() {
return scope;
}
public void setScope(String scope) {
this.scope = scope;
}
public Class getClassloader() {
return beanClass;
}
public void setClassloader(Class classloader) {
this.beanClass = classloader;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
新建IOC(MyIocApplicationXmlContext)
package com.kang.myIoc;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyValue;
import org.w3c.dom.*;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @Description 模拟IOC容器
* @ClassName MyIocApplicationcontext
* @Author 康世行
* @Date 19:38 2022/6/20
* @Version 1.0
**/
public class MyIocApplicationXmlContext {
//存储单例对象(成品)
private Map<String, Object> singletonMap=new ConcurrentHashMap<>();
//bean定义(半成品)
private Map<String,BeanDefinition> beanDefinitionsMap=new ConcurrentHashMap<>();
public MyIocApplicationXmlContext(String applicationContext) {
try {
//加载xml文件,获取定义的bean
InputStream resourceAsStream = this.getClass().getResourceAsStream(applicationContext);
//使用 DocumentBuilderFactory 把xml 输入流转成xml文件
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
Document beanDefinitionXml = factory.newDocumentBuilder().parse(resourceAsStream);
//获取xml 定义的bean
NodeList beans = beanDefinitionXml.getElementsByTagName("bean");
//获取beanList长度
int length = beans.getLength();
//遍历所有bean节点获取 bean定义的信息
for (int i = 0; i < length; i++) {
//获取bean节点
Node item = beans.item(i);
//获取bean id ,beanClassName
String beanName = item.getAttributes().getNamedItem("id").getNodeValue();
String beanClassName = item.getAttributes().getNamedItem("class").getNodeValue();
//获取Scope节点
Node scopeNode = item.getAttributes().getNamedItem("scope");
//bean类型默认是空的,也就是单例类型
String scope="";
if (scopeNode!=null){
scope = item.getAttributes().getNamedItem("scope").getNodeValue();
}
//根据beanClassName 获取beanClass 对象
Class<?> beanObjectClass = Class.forName(beanClassName);
//获取bean 注入的内容-属性和属性值
MutablePropertyValues propertyValues=new MutablePropertyValues();
//获取item 子节点,bean的属性值及属性值
NodeList propertyList = item.getChildNodes();
for (int i1 = 0; i1 < propertyList.getLength(); i1++) {
Node propertyNode = propertyList.item(i1);
//判断是否获取到属性节点
if (propertyNode==null){
//跳过本次循环
continue;
}
Node nextSibling = propertyNode.getNextSibling();
if (nextSibling==null){
continue;
}
//一对属性(键值)
NamedNodeMap attributes = nextSibling.getAttributes();
if (attributes!=null){
String name = attributes.getNamedItem("name").getNodeValue();
String value = attributes.getNamedItem("value").getNodeValue();
//赋值到 propertyValues 里
propertyValues.addPropertyValue(name,value);
}
}
// 新建BeanDefinition 对象
BeanDefinition beanDefinition=new BeanDefinition();
beanDefinition.setBeanName(beanName);
beanDefinition.setClassloader(beanObjectClass);
beanDefinition.setPropertyValues(propertyValues);
beanDefinition.setScope(scope);
//bean定义存入到集合中,用于getbean 的时候,创建对象使用。
beanDefinitionsMap.put(beanName,beanDefinition);
}
//遍历beanDefinitionsMap 把单例bean对象创建出来使用getbean
for (Map.Entry<String, BeanDefinition> stringBeanDefinitionEntry : beanDefinitionsMap.entrySet()) {
String beanNameId = stringBeanDefinitionEntry.getKey();
BeanDefinition beanDefinition = stringBeanDefinitionEntry.getValue();
String scope = beanDefinition.getScope();
//如果是单例类型,调用getbean创建bean
if ("singleton".equals(scope)){
getbean(beanNameId);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* @author 康世行
* @description: 根据对象ID,在ioc容器获取对象。
* @date 2022/6/20 19:43
* @param beanName
* @return java.lang.Object
* @Version1.0
**/
public Object getbean(String beanName){
//先从单例map中获取指定对象名的单例对象
Object singleBean = singletonMap.get(beanName);
if (singleBean==null){
//没有获取到单例bean对象,从bean定义map中获取bean信息进行创建
BeanDefinition beanDefinition = beanDefinitionsMap.get(beanName);
//只有获取到bean的定义信息才进行创建对象
if (beanDefinition!=null){
singleBean= createBean(beanDefinition);
}
}
return singleBean;
}
/**
* @author 康世行
* @description: 创建bean对象
* @date 2022/6/20 23:56
* @param beanDefinition
* @return java.lang.Object
* @Version1.0
**/
private Object createBean(BeanDefinition beanDefinition){
String scope = beanDefinition.getScope();
Object result=new Object();
//判断bean类型(默认是单例类型)
if ("singleton".equals(scope)||"".equals(scope)){
//创建对象实例
result = createInstance(beanDefinition);
//获取beanName
String beanName = beanDefinition.getBeanName();
//创建的对象放入到单例bean容器
singletonMap.put(beanName,result);
//返回容器对象
result= singletonMap.get(beanName);
return result;
}else if ("prototype".equals(scope)){
//进行原型类型 逻辑处理
//创建对象实例
result = createInstance(beanDefinition);
return result;
}
return result;
}
/**
* @author 康世行
* @description: 创建对象实例并且赋值
* @date 2022/6/21 9:37
* @param beanDefinition
* @return java.lang.Object
* @Version1.0
**/
private Object createInstance(BeanDefinition beanDefinition){
//组装完属性之后的对象
Object result=new Object();
//进行单例类型逻辑处理
try {
//获取bean属性
MutablePropertyValues propertyValues = beanDefinition.getPropertyValues();
//获取beanClass
Class beanClass = beanDefinition.getClassloader();
//beanClass 创建对象
result= beanClass.newInstance();
for (PropertyValue propertyValue : propertyValues) {
String name = propertyValue.getName();
Object value = propertyValue.getValue();
//根据name 获取指定字段
Field declaredField = beanClass.getDeclaredField(name);
//获取字段类型
Class<?> type = declaredField.getType();
if (type.equals(Integer.class)){
//通过反射拼接方法名,获取方法。
Method method = beanClass.getMethod("set" + firstLetterName(name),Integer.class);
method.invoke(result,Integer.valueOf(value.toString()));
}else if (type.equals(Float.class)){
//通过反射拼接方法名,获取方法。
Method method = beanClass.getMethod("set" + firstLetterName(name),Float.class);
method.invoke(result,Float.valueOf(value.toString()));
}else if (type.equals(Double.class)){
//通过反射拼接方法名,获取方法。
Method method = beanClass.getMethod("set" + firstLetterName(name),Double.class);
method.invoke(result,Double.valueOf(value.toString()));
}else{
//通过反射拼接方法名,获取方法。
Method method = beanClass.getMethod("set" + firstLetterName(name),String.class);
method.invoke(result,value);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
//首字母大写
public static String firstLetterName(String name) {
name = name.substring(0, 1).toUpperCase() + name.substring(1);
return name;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 199
- 200
- 201
- 202
- 203
- 204
- 205
- 206
- 207
- 208
- 209
- 210
- 211
- 212
- 213
- 214
测试
编写测试代码
import com.kang.model.Student;
import com.kang.myIoc.MyIocApplicationXmlContext;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @Description TODO
* @ClassName Test
* @Author 康世行
* @Date 19:52 2022/6/6
* @Version 1.0
**/
public class Test {
public static void main(String[] args) {
MyIocApplicationXmlContext myIocApplicationXmlContext=new MyIocApplicationXmlContext("/test.xml");
System.out.println("");
// /*原型bean*/
Object student = myIocApplicationXmlContext.getbean("student");
Object student2 = myIocApplicationXmlContext.getbean("student");
System.out.println(student);
System.out.println(student2);
/*单例bean*/
Object theater = myIocApplicationXmlContext.getbean("theater");
System.out.println(theater);
System.out.println("");
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
测试效果
可以从下面的图中看到-student对象连续获取两次,不是同一个对象(原型类型)
源代码下载
https://download.csdn.net/download/kangshihang1998/85720711
感谢阅读! 都已经看到这了,还不给小编一个,一键三连。点赞,收藏。
文章来源: kangshihang.blog.csdn.net,作者:康世行,版权归原作者所有,如需转载,请联系作者。
原文链接:kangshihang.blog.csdn.net/article/details/125387212
【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)