核心技术点:XML解析+反射
具体思路:
1、根据需求编写XML文件,配置需要创建的bean。
2、编写程序读取XML文件,获取bean相关信息,类、属性、id。
3、根据第2步获取到的信息,结合反射机制动态创建对象,同时完成属性的赋值。
4、将创建好的bean存入Map集合,设置key-value映射,key 就是bean中id值,value 就是bean对象。
5、提供方法从Map中通过id获取到对应的value。
spring.xml
<bean id="car" class="com.lmh.entity.Car">
<property name="num" value="1"></property>
<property name="brand" value="奥迪"></property>
</bean>
<bean id="car2" class="com.lmh.entity.Car">
<property name="num" value="2"></property>
<property name="brand" value="大奔"></property>
</bean>
pom.xml
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.20</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.2.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.3.20</version>
</dependency>
<!-- dom4j方法-->
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
</dependencies>
仿照ClassPathXmlApplicationContext类。自己建一个 MyClassPathXmlApplicationContext
public class MyClassPathXmlApplicationContext implements ApplicationContext {
private Map<String, Object> ioc;
//处理传进来的spring.xml文档
public MyClassPathXmlApplicationContext(String path) {
ioc = new HashMap<>();
//解析xml
parseXML(path);
}
//解析xml的方法
public void parseXML(String path) {
SAXReader saxReader = new SAXReader();
try {
//spring.xml文档,转成了Document对象
Document document = saxReader.read("src/main/resources/" + path);
//根节点 相当于beans
Element rootElement = document.getRootElement();
//根节点迭代器
Iterator<Element> rootIter = rootElement.elementIterator();
while (rootIter.hasNext()) {
//得到bean
Element bean = rootIter.next();
//key
String id = bean.attributeValue("id");
String className = bean.attributeValue("class");
//System.out.println("bean的id是:" + id + "。bean的className是:" + className);
//反射动态创建对象
Class clazz = Class.forName(className);
//通过无参
Constructor constructor = clazz.getConstructor();
// System.out.println("class:" + clazz);
// System.out.println("构造器:" + constructor);
//拿到对象 , value
Object object = constructor.newInstance();
// System.out.println(object);
//属性迭代器,给属性赋值
Iterator<Element> beanIter = bean.elementIterator();
while (beanIter.hasNext()) {
Element property = beanIter.next();
//拿到key和value 就是name和值 num1 brand奥迪 num2 brand大奔
String propertyName = property.attributeValue("name");
String propertyValue = property.attributeValue("value");
//System.out.println(propertyName+propertyValue);
//获取set方法
// num -- setNum, brand --setBrand
//切片
String methodName = "set" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);
//拿到,属性类型,set方法要传参
Field field = clazz.getDeclaredField(propertyName);
//方法名,参数类型
Method method = clazz.getMethod(methodName, field.getType());
Object value = propertyValue;
//类型转换。 根据实体类 的类型选择转换为Integer类型
switch (field.getType().getName()) {
case "java.lang.Integer":
value = Integer.parseInt(propertyValue);
break;
case "java.lang.Double":
value = Double.parseDouble(propertyValue);
break;
}
//反射机制、调用方法
method.invoke(object, value);
System.out.println(method);
//调用方法
}
//然后用getBean方法返回出去
ioc.put(id, object);
}
} catch (DocumentException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
@Override
public Object getBean(String name) throws BeansException {
//通过map的key 得到 value并返回
return ioc.get(name);
}
Test
public class Test {
public static void main(String[] args) {
ApplicationContext context = new MyClassPathXmlApplicationContext("spring_Ioc.xml");
System.out.println(context.getBean("car"));
}
}