SpringIoc底层实现原理
- 读取bean 的XML配置文件
- 使用beanId查找bean配置,并获取配置文件class地址
- 使用java反射技术实例化对象
- 获取属性配置,使用反射技术进行赋值
步骤
1.利用传入的参数获取xml文件的流,并且利用dom4j解析成Document对象
2.对于Document对象获取根元素对象<beans>后对下面的<bean>标签进行遍历,判断是否有符合的id.
3.如果找到对应的id,相当于找到了一个Element元素,开始创建对象,先获取class属性,根据属性值利用反射建立对象.
4.遍历<bean>标签下的property标签,并对属性赋值.注意,需要单独处理int,float类型的属性.因为在xml配置中这些属性都是以字符串的形式来配置的,因此需要额外处理.
5.如果属性property标签有ref属性,说明某个属性的值是一个对象,那么根据id(ref属性的值)去获取ref对应的对象,再给属性赋值.
6.返回建立的对象,如果没有对应的id,或者<beans>下没有子标签都会返回null
实现
新建maven工程
添加依赖
<dependencies>
<!--工具包-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
</dependency>
<!--解析dom-->
<dependency>
<groupId>org.dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>2.0.0</version>
</dependency>
</dependencies>
public class UserEntity {
private String userId;
private String userName;
public UserEntity() {
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
@Override
public String toString() {
return "UserEntity [userId=" + userId + ", userName=" + userName + "]";
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<bean id="user1" class="com.springioc.test.entity.UserEntity">
<property name="userId" value="a1"></property>
<property name="userName" value="小明"></property>
</bean>
<bean id="user2" class="com.springioc.test.entity.UserEntity">
<property name="userId" value="a2"></property>
<property name="userName" value="小军"></property>
</bean>
</beans>
public class ClassPathXmlApplicationContext {
private static String PATH;
private static String ID;
private static String CLASS;
private static String NAME;
private static String VALUE;
public void init() {
ID = "id";
CLASS = "class";
NAME = "name";
VALUE = "value";
}
public ClassPathXmlApplicationContext(String path) {
PATH = path;
init();
}
public Object getBean(String beanId) throws DocumentException, ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
//解析xml
if (StringUtils.isEmpty(beanId)) {
return null;
}
SAXReader saxReader = new SAXReader();
//获取xml
Document applicationContext = saxReader.read(this.getClass().getClassLoader().getResource(PATH));
//获取最外层根元素beans
Element rootElement = applicationContext.getRootElement();
//所有的二级节点
List<Element> elements = rootElement.elements();
for (Element element : elements) {
String id = element.attributeValue(ID);
if (!beanId.equals(id)) {
continue;
}
//获取class节点属性
String clazz = element.attributeValue(CLASS);
//使用java反射机制初始化类
Class<?> forName = Class.forName(clazz);
//获取类的对象
Object newInstance = forName.newInstance();
//获取属性
List<Element> childElemets = element.elements();
for (Element childElemet : childElemets) {
String name = childElemet.attributeValue(NAME);
String value = childElemet.attributeValue(VALUE);
Field declaredField = forName.getDeclaredField(name);
//设置私有客可访问权限
declaredField.setAccessible(true);
declaredField.set(newInstance, value);
}
return newInstance;
}
return null;
}
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
try {
UserEntity user1 = (UserEntity) context.getBean("user1");
if (null != user1) {
System.out.println(user1.toString());
} else {
System.out.println("获取失败");
}
} catch (DocumentException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
}
运行结果