文章目录
前言
为了更好的了解spring注入bean和获取bean的原理。
一、步骤分析
1、将xml文件进行解析
2、生成对象并放进容器中
3、提供获取容器对象的方法getBean(id)
二、maven坐标引入
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
<!--dom4j xml文档解析-->
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
三、示例代码
1、Person类
package com.example.demo5.testBean;
import lombok.Data;
import java.io.Serializable;
/**
* @Author lcb
* @Date 2023/03/19
**/
@Data
public class Person implements Serializable {
private Long id;
private String nickName;
private Double weight;
}
2、Student类
package com.example.demo5.testBean;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* @Author lcb
* @Date 2023/03/19
**/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student implements Serializable {
private Integer id;
private String name;
private Integer age;
}
3、TestBean.xml
<?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 http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean class="com.example.demo5.testBean.Student" id="student">
<property name="id" value="10"/>
<property name="name" value="孙悟空"/>
<property name="age" value="18"/>
</bean>
<bean class="com.example.demo5.testBean.Person" id="person">
<property name="id" value="100"/>
<property name="nickName" value="孙悟空-呵呵哒"/>
<property name="weight" value="60.0"/>
</bean>
</beans>
4、ApplicationContextStudentTest测试类
package com.example.demo5.testBean;
import lombok.NoArgsConstructor;
import lombok.SneakyThrows;
import org.apache.commons.lang3.CharUtils;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
/**
* 实现一个简单的spring容器机制
* 1、将xml文件进行解析
* 2、生成对象并放进容器中
* 3、提供获取容器对象的方法getBean(id)
*
* @Author lcb
* @Date 2023/03/19
**/
@NoArgsConstructor
@SuppressWarnings("all")
public class ApplicationContextStudentTest {
private ConcurrentHashMap<String, Object> singletonObjects = new ConcurrentHashMap<>();
@SneakyThrows
public ApplicationContextStudentTest(String pathFile) {
//1、得到类加载路径
String path = Objects.requireNonNull(this.getClass().getResource("/")).getPath();
//2、创建Saxreader对象
SAXReader saxReader = new SAXReader();
//3、得到Document对象
Document document = saxReader.read(new File(path.concat(pathFile)));
//4、得到rootDocument对象
Element rootElements = document.getRootElement();
Class<?> className;
Object obj;
//5、获取bean集合对象
List<Element> rootElementList = (List<Element>) rootElements.elements();
for (Element rootElement : rootElementList) {
className = Class.forName(rootElement.attributeValue("class"));
obj = className.newInstance();
//6、获取每个对象对应的属性
for (Element element : (List<Element>) rootElement.elements("property")) {
List<Attribute> attributes = (List<Attribute>) element.attributes();
//1)、通过方法设值
setValueByMethods(className, obj, attributes);
//2)、通过属性设值
// setValueByFields(className, obj, attributes);
//7、将bean对象及其属性信息保存到singletonObjects对象中
singletonObjects.put(rootElement.attributeValue("id"), obj);
}
}
}
@SneakyThrows
private void setValueByFields(Class<?> className, Object obj, List<Attribute> attributes) {
for (Field field : className.getDeclaredFields()) {
field.setAccessible(true);
if (field.getName().equals(attributes.get(0).getValue())) {
String typeName = field.getGenericType().getTypeName();
field.set(obj, getFieldValue(typeName, attributes.get(1).getValue()));
}
}
}
@SneakyThrows
private void setValueByMethods(Class<?> className, Object obj, List<Attribute> attributes) {
String attrName = attributes.get(0).getValue();
for (Method method : className.getDeclaredMethods()) {
method.setAccessible(true);
//如果是set属性的方法,就进行属性赋值
if (method.getName().equals("set".concat(attrName.substring(0, 1).toUpperCase(Locale.ROOT)).concat(attrName.substring(1)))) {
String typeName = method.getGenericParameterTypes()[0].getTypeName();
method.invoke(obj, getFieldValue(typeName, attributes.get(1).getValue()));
}
}
}
/**
* 根据bean的名称获取bean对象
*
* @param beanName bean的名称
* @return bean对象
*/
public Object getBean(String beanName) {
return singletonObjects.get(beanName);
}
/**
* 类型转化
*
* @param type 类型
* @param value 数据
* @return 将数据转化为对应类型的数据
*/
@SneakyThrows
private Object getFieldValue(String type, String value) {
switch (type.substring(type.lastIndexOf(".") + 1)) {
case "Byte":
return Byte.parseByte(value);
case "Short":
return Short.parseShort(value);
case "Character":
return CharUtils.toChar(value);
case "Integer":
return Integer.parseInt(value);
case "Long":
return Long.parseLong(value);
case "Boolean":
return Boolean.parseBoolean(value);
case "Float":
return Float.parseFloat(value);
case "Double":
return Double.parseDouble(value);
default:
return value;
}
}
public static void main(String[] args) {
ApplicationContextStudentTest applicationContextStudentTest = new ApplicationContextStudentTest("mapper/TestBean.xml");
System.out.println(applicationContextStudentTest.getBean("student"));
System.out.println(applicationContextStudentTest.getBean("person"));
}
}