步骤:
1.构建XML标签对象 ;
2.编写XML文件 ;
3.解析XML文件,构建上下文单例对象;
4.从上下文中取出对象。
项目目录:
XML标签结构:
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<bean id="id_1" class="com.backage.one">
<property name ="XX" value="XX"></property>
</bean>
<bean id="id_2" class="com.backage.two">
<property name ="XX" ref="id_1"></property>
</bean>
</beans>
构建XML对象,Beans.java , Bean.java , Property.java
package com.zjj.beans;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "beans")
public class Beans {
private List<Bean> beans = new ArrayList<>();
@XmlElement(name = "bean")
public List<Bean> getBeans() {
return beans;
}
public void setBeans(List<Bean> beans) {
this.beans = beans;
}
}
package com.zjj.beans;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "bean")
public class Bean {
private String id;
private String clazz;
private List<Property> properties = new ArrayList<>();
@XmlAttribute(name = "id")
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@XmlAttribute(name = "class")
public String getClazz() {
return clazz;
}
public void setClazz(String clazz) {
this.clazz = clazz;
}
@XmlElement(name = "property")
public List<Property> getProperties() {
return properties;
}
public void setProperties(List<Property> properties) {
this.properties = properties;
}
}
package com.zjj.beans;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name="property")
public class Property {
private String name;
private String ref;
private String value;
@XmlAttribute(name="name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@XmlAttribute(name="ref")
public String getRef() {
return ref;
}
public void setRef(String ref) {
this.ref = ref;
}
@XmlAttribute(name="value")
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
业务类接口UserDao , 业务实现类UserDaoImpl,简单对象类Student
package com.zjj.dao;
public interface UserDao {
public void print();
}
package com.zjj.impl;
import com.zjj.dao.UserDao;
import com.zjj.pojo.Student;
public class UserDaoImpl implements UserDao {
private Student student;
private Integer id;
public Student getStudent() {
return student;
}
public void setStudent(Student student) {
this.student = student;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
@Override
public void print() {
System.out.println("序号:"+id+",学号:"+student.getNumber()+","+
"姓名:"+student.getUsername());
}
}
package com.zjj.pojo;
public class Student {
private String username;
private Integer number;
private int id;
private char sex;
private boolean leader;
private double grade;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Integer getNumber() {
return number;
}
public void setNumber(Integer number) {
this.number = number;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
public double getGrade() {
return grade;
}
public void setGrade(double grade) {
this.grade = grade;
}
public boolean isLeader() {
return leader;
}
public void setLeader(boolean leader) {
this.leader = leader;
}
}
bean.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<bean id="student" class="com.zjj.pojo.Student">
<property name ="username" value="zjj"></property>
<property name ="number" value= "1234" ></property>
<property name ="id" value= "11" ></property>
<property name ="sex" value= "m" ></property>
<property name ="leader" value= "true" ></property>
<property name ="grade" value= "99.9" ></property>
</bean>
<bean id="userDaoImpl" class="com.zjj.impl.UserDaoImpl">
<property name = "id" value="1"></property>
<property name ="student" ref="student"></property>
</bean>
</beans>
上下文类 ApplicationContext.java
package com.zjj.application;
import java.io.FileInputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import com.zjj.beans.Bean;
import com.zjj.beans.Beans;
import com.zjj.beans.Property;
public class ApplicationContext {
// 对象池
private Map<String, Object> cache = new HashMap<>();
// 单例变量
private static ApplicationContext applicationContext;
// 单例上下文对象
private ApplicationContext(String path) {
try {
// 解析xml
JAXBContext context = JAXBContext.newInstance(Beans.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
Beans beans = (Beans) unmarshaller.unmarshal(new FileInputStream(path));
// 获取bean集合
List<Bean> beanList = beans.getBeans();
// 如果不为空
if (!beanList.isEmpty()) {
// 遍历bean标签
for (Bean bean : beanList) {
// 第一次迭代,bean对象的id,class
String idName = bean.getId();
String className = bean.getClazz();
// 根据bean的设置,通过反射创建对象
Class<?> clazz = Class.forName(className);
// UserDaoImpl对象
Object BeanInstance = clazz.newInstance();
// 放到上下文中
this.cache.put(idName, BeanInstance);
}
// 第二次迭代,根据属性进行设值注入
for (Bean bean : beanList) {
List<Property> properties = bean.getProperties();
if (!properties.isEmpty()) {
String id = bean.getId();
Object beanInstance = this.cache.get(id);
// 获取反射模板
Class<? extends Object> clazz = beanInstance.getClass();
// 循环执行设值方法
for (Property property : properties) {
String name = property.getName();
String value = property.getValue();
// 判断是否为设置方法
if (value != null) {
// 构造方法名
String setMethodName = "set" + name.substring(0, 1).toUpperCase() + name.substring(1);
// 执行set方法
// 通过反射获取name属性的类型
Field setField = clazz.getDeclaredField(name);
Class<?> setFieldClass = setField.getType();
String typeName = setFieldClass.getTypeName();
// System.out.println(setFieldClass.getTypeName());
// 通过反射获取该方法
Method setMethod = clazz.getDeclaredMethod(setMethodName, setFieldClass);
// 判断成员变量的类型,执行方法,参数为执行方法的对象,传入的参数
invokeByType(typeName,setMethod,beanInstance,value);
}
}
}
}
// 第三次迭代,设置ref对象属性
for (Bean bean : beanList) {
List<Property> properties = bean.getProperties();
if (!properties.isEmpty()) {
String id = bean.getId();
Object beanInstance = this.cache.get(id);
// 获取反射模板
Class<? extends Object> clazz = beanInstance.getClass();
// 循环执行设值方法
for (Property property : properties) {
String name = property.getName();
String ref = property.getRef();
// 判断是否为设置方法
if (ref != null) {
// 构造方法名
String setMethodName = "set" + name.substring(0, 1).toUpperCase() + name.substring(1);
// 执行set方法
// 通过反射获取name属性的类型
Field setField = clazz.getDeclaredField(name);
Class<?> setFieldClass = setField.getType();
// System.out.println(setFieldClass.getTypeName());
// 通过反射获取该方法
Method setMethod = clazz.getDeclaredMethod(setMethodName, setFieldClass);
// 执行方法,参数为执行方法的对象,传入的参数
setMethod.invoke(beanInstance, this.cache.get(ref));
}
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
// 上下文单例对象返回
public static ApplicationContext getInstance(String path) {
if (applicationContext == null) {
applicationContext = new ApplicationContext(path);
}
return applicationContext;
}
//返回对应的实例化对象
public Object getBean(String idName) {
Object bean = cache.get(idName);
return bean;
}
//反射获取参数类型,由String装换成需要的类型,执行设置方法
public void invokeByType(String typeName,Method setMethod,Object beanInstance,String value) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException{
if (typeName.equals("java.lang.String"))
setMethod.invoke(beanInstance, value);
if(typeName.endsWith("char"))
setMethod.invoke(beanInstance, value.charAt(0));
if (typeName.equals("java.lang.Integer"))
setMethod.invoke(beanInstance, Integer.parseInt(value));
if(typeName.endsWith("int"))
setMethod.invoke(beanInstance, Integer.parseInt(value));
if(typeName.endsWith("java.lang.Double"))
setMethod.invoke(beanInstance, Double.parseDouble(value));
if(typeName.endsWith("double"))
setMethod.invoke(beanInstance, Double.parseDouble(value));
if(typeName.endsWith("java.lang.Boolean"))
setMethod.invoke(beanInstance, Boolean.parseBoolean(value));
if(typeName.endsWith("boolean"))
setMethod.invoke(beanInstance, Boolean.parseBoolean(value));
}
}
测试类 IOCTest.java
package com.zjj.test;
import com.zjj.application.ApplicationContext;
import com.zjj.dao.UserDao;
import com.zjj.pojo.Student;
public class IOCTest {
public static void main(String[] args){
ApplicationContext applicationContext = ApplicationContext.getInstance("src/bean.xml");
Student student =(Student)applicationContext.getBean("student");
System.out.println(student.getUsername()
+","+student.getNumber()
+","+student.getSex()
+","+student.getGrade()
+","+student.isLeader()
+","+student.getId());
UserDao userDao = (UserDao) applicationContext.getBean("userDaoImpl");
userDao.print();
}
}
运行结果:
如果对本博客有疑问,或者实现过程中遇到问题,或者有更好的方法,欢迎留言提问以及分析。