核心技术点:XML解析 + 反射 + 工厂模式 具体思路: 1、根据需求编写 XML 文件,配置需要创建的 bean。 2、编写程序读取 XML 文件,获取 bean 相关信息,类、属性、id。 3、根据第 2 步获取到的信息,结合反射机制动态创建对象,同时完成属性的赋值。 4、将创建好的 bean 存入到 Map 集合,设置 key-value 映射,key 就是 bean 中的 id 值,value 就是 bean 对象。 5、提供方法从 Map 中通过 id 获取到对应的 value。
创建实体类:
package com.southwind.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Car {
private Integer num;
private String brand;
}
配置 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"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="car" class="com.southwind.pojo.Car">
<property name="num" value="1"></property>
<property name="brand" value="奥迪"></property>
</bean>
</beans>
创建 MyClassPathXmlApplicationContext,实现 ApplicationContext 类:
package com.southwind.ioc;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.MessageSourceResolvable;
import org.springframework.context.NoSuchMessageException;
import org.springframework.core.ResolvableType;
import org.springframework.core.env.Environment;
import org.springframework.core.io.Resource;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
public class MyClassPathXmlApplicationContext implements ApplicationContext {
private Map<String, Object> iocMap;
public MyClassPathXmlApplicationContext(String path){
iocMap = new HashMap<>();
parseXML(path);
}
public void parseXML(String path){
SAXReader reader = new SAXReader();
try {
Document document = reader.read("src/main/resources/"+path);
Element rootElement = document.getRootElement();
Iterator<Element> elementIterator = rootElement.elementIterator();
while(elementIterator.hasNext()){
Element bean = elementIterator.next();
String idStr = bean.attributeValue("id");
String className = bean.attributeValue("class");
Class clazz = Class.forName(className);
Constructor constructor = clazz.getConstructor();
Object object = constructor.newInstance();
Iterator<Element> beanIter = bean.elementIterator();
while(beanIter.hasNext()){
Element property = beanIter.next();
String propertyName = property.attributeValue("name");
String propertyValue = property.attributeValue("value");
String methodName = "set" + propertyName.substring(0,1).toUpperCase() + propertyName.substring(1);
Field field = clazz.getDeclaredField(propertyName);
Method method = clazz.getMethod(methodName, field.getType());
Object value = propertyValue;
switch(field.getType().getName()){
case "java.lang.Integer":
value = Integer.parseInt(propertyValue);
break;
}
method.invoke(object, value);
}
iocMap.put(idStr, object);
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public Object getBean(String name) throws BeansException {
return iocMap.get(name);
}
@Override
public String getId() {
return null;
}
@Override
public String getApplicationName() {
return null;
}
@Override
public String getDisplayName() {
return null;
}
@Override
public long getStartupDate() {
return 0;
}
@Override
public ApplicationContext getParent() {
return null;
}
@Override
public AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException {
return null;
}
@Override
public BeanFactory getParentBeanFactory() {
return null;
}
@Override
public boolean containsLocalBean(String name) {
return false;
}
@Override
public boolean containsBeanDefinition(String beanName) {
return false;
}
@Override
public int getBeanDefinitionCount() {
return 0;
}
@Override
public String[] getBeanDefinitionNames() {
return new String[0];
}
@Override
public <T> ObjectProvider<T> getBeanProvider(Class<T> requiredType, boolean allowEagerInit) {
return null;
}
@Override
public <T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType, boolean allowEagerInit) {
return null;
}
@Override
public String[] getBeanNamesForType(ResolvableType type) {
return new String[0];
}
@Override
public String[] getBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) {
return new String[0];
}
@Override
public String[] getBeanNamesForType(Class<?> type) {
return new String[0];
}
@Override
public String[] getBeanNamesForType(Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
return new String[0];
}
@Override
public <T> Map<String, T> getBeansOfType(Class<T> type) throws BeansException {
return null;
}
@Override
public <T> Map<String, T> getBeansOfType(Class<T> type, boolean includeNonSingletons, boolean allowEagerInit) throws BeansException {
return null;
}
@Override
public String[] getBeanNamesForAnnotation(Class<? extends Annotation> annotationType) {
return new String[0];
}
@Override
public Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType) throws BeansException {
return null;
}
@Override
public <A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType) throws NoSuchBeanDefinitionException {
return null;
}
@Override
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
return null;
}
@Override
public Object getBean(String name, Object... args) throws BeansException {
return null;
}
@Override
public <T> T getBean(Class<T> requiredType) throws BeansException {
return null;
}
@Override
public <T> T getBean(Class<T> requiredType, Object... args) throws BeansException {
return null;
}
@Override
public <T> ObjectProvider<T> getBeanProvider(Class<T> requiredType) {
return null;
}
@Override
public <T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType) {
return null;
}
@Override
public boolean containsBean(String name) {
return false;
}
@Override
public boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
return false;
}
@Override
public boolean isPrototype(String name) throws NoSuchBeanDefinitionException {
return false;
}
@Override
public boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException {
return false;
}
@Override
public boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException {
return false;
}
@Override
public Class<?> getType(String name) throws NoSuchBeanDefinitionException {
return null;
}
@Override
public Class<?> getType(String name, boolean allowFactoryBeanInit) throws NoSuchBeanDefinitionException {
return null;
}
@Override
public String[] getAliases(String name) {
return new String[0];
}
@Override
public void publishEvent(Object event) {
}
@Override
public String getMessage(String code, Object[] args, String defaultMessage, Locale locale) {
return null;
}
@Override
public String getMessage(String code, Object[] args, Locale locale) throws NoSuchMessageException {
return null;
}
@Override
public String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException {
return null;
}
@Override
public Environment getEnvironment() {
return null;
}
@Override
public Resource[] getResources(String locationPattern) throws IOException {
return new Resource[0];
}
@Override
public Resource getResource(String location) {
return null;
}
@Override
public ClassLoader getClassLoader() {
return null;
}
}
使用 SAXReader 解析 xml 文件,并利用反射创建对象,然后将对象放入 iocMap 中,通过 getBean 方法,将对象返回。
测试方法:
package com.southwind.test;
import com.southwind.ioc.MyClassPathXmlApplicationContext;
import com.southwind.pojo.Car;
import org.springframework.context.ApplicationContext;
public class Test1 {
public static void main(String[] args) {
ApplicationContext context = new MyClassPathXmlApplicationContext("spring-ioc.xml");
Car car = (Car) context.getBean("car");
System.out.println(car);
}
}
测试结果:
Car(num=1, brand=奥迪)
|