Maven依赖:
- "1.0" encoding="UTF-8"?>
- <project xmlns="http://maven.apache.org/POM/4.0.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0modelVersion>
-
- <groupId>org.myspringframeworkgroupId>
- <artifactId>myspringartifactId>
- <version>1.0-SNAPSHOTversion>
- <packaging>jarpackaging>
- <properties>
- <maven.compiler.source>17maven.compiler.source>
- <maven.compiler.target>17maven.compiler.target>
- <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
- properties>
- <dependencies>
- <dependency>
- <groupId>dom4jgroupId>
- <artifactId>dom4jartifactId>
- <version>1.1version>
- dependency>
- <dependency>
- <groupId>jaxengroupId>
- <artifactId>jaxenartifactId>
- <version>1.2.0version>
- dependency>
- <dependency>
- <groupId>junitgroupId>
- <artifactId>junitartifactId>
- <version>4.13.2version>
- <scope>testscope>
- dependency>
- dependencies>
- project>
- public interface ApplicationContext {
- /**
- * 根据bean的名字获取对应的bean对象
- * @param beanName myspring配置文件中bean标签的id
- * @return 对应的bean对象
- */
-
T getBean(String beanName,Class type) ; - Object getBean(String beanName);
- }
- public class ClassPathXmlApplicationContext implements ApplicationContext{
- // 对应一级缓存
- private Map
singletonObject=new HashMap<>(); -
-
- /**
- * 解析myspring的配置文件,然后初始化所有的bean对象。
- * @param configLocation Spring配置文件的路径,注意,使用ClassPathXmlApplicationContext,配置文件应放在类路径中
- */
- public ClassPathXmlApplicationContext(String configLocation) {
- // 解析myspring.xml配置文件,实例化bean,把bean放到集合中
- try {
- // 获取一个解析器对象
- SAXReader saxReader=new SAXReader();
- // 获取所要读取的文件的输入流
- URL resource = ClassLoader.getSystemClassLoader().getResource(configLocation);
- // 获取文档对象
- Document document = saxReader.read(resource);
- // 获取指定标签 //bean 表示获得多个bean标签
- List beans = document.selectNodes("//bean");
- // 遍历所有的bean并放到集合中
- beans.forEach(new Consumer() {
- @Override
- public void accept(Object o) {
- //向下转型,拥有更丰富的方法
- Element element= (Element) o;
- //获取bean后,再获取属性值id和class 注:class是全类名
- String id = element.attributeValue("id");
- String className = element.attributeValue("class");
- try {
- //有了类名后,直接反射创建对象
- Class clazz= Class.forName(className);
- //获取无参构造方法
- Constructor declaredConstructor = clazz.getDeclaredConstructor();
- //创建对象并放到map中 进行曝光
- Object bean = declaredConstructor.newInstance();
- singletonObject.put(id,bean);
- } catch (Exception e) {
- e.printStackTrace();
- throw new RuntimeException(e);
- }
- }
- });
- // 进行set注入,为属性赋值
- //首先得获得
标签,获取其中的属性name和value 或是 name和ref - beans.forEach(new Consumer() {
- @Override
- public void accept(Object o) {
- try {
- //获取bean的id和className
- Element element= (Element) o;
- String className=element.attributeValue("class");
- String id=element.attributeValue("id");
- //获取
中的所有标签 - List properties = element.elements();
- //遍历该bean所有
标签 - properties.forEach(new Consumer() {
- @Override
- public void accept(Object o) {
- Element property= (Element) o;
- String fieldName = property.attributeValue("name");
- String propertyValue = property.attributeValue("value");
- String ref = property.attributeValue("ref");
- try {
- //利用反射
- Object bean=singletonObject.get(id);
- //获取set()方法
- String setMethodName="set"+fieldName.toUpperCase().charAt(0)+fieldName.substring(1);
- //获取全限定类型名
- Class propertyType= bean.getClass().getDeclaredField(fieldName).getType();
- //如果所获取的方法有参数的话,需要加上参数类型
- Method setMethod = bean.getClass().getDeclaredMethod(setMethodName,propertyType);
- //获取bean的set方法
- if(propertyValue!=null){
- Object propertyVal=null;
- //对于基本数据类型,如果想要调用相应的set方法,必须知道类型是什么
- String propertyTypeSimpleName=propertyType.getSimpleName();
- switch (propertyTypeSimpleName) {
- case "byte": case "Byte":
- propertyVal = Byte.valueOf(propertyValue);
- break;
- case "short": case "Short":
- propertyVal = Short.valueOf(propertyValue);
- break;
- case "int": case "Integer":
- propertyVal = Integer.valueOf(propertyValue);
- break;
- case "long": case "Long":
- propertyVal = Long.valueOf(propertyValue);
- break;
- case "float": case "Float":
- propertyVal = Float.valueOf(propertyValue);
- break;
- case "double": case "Double":
- propertyVal = Double.valueOf(propertyValue);
- break;
- case "boolean": case "Boolean":
- propertyVal = Boolean.valueOf(propertyValue);
- break;
- case "char": case "Character":
- propertyVal = propertyValue.charAt(0);
- break;
- case "String":
- propertyVal = propertyValue;
- break;
- }
- setMethod.invoke(singletonObject.get(id), propertyVal);
- }else if(ref!=null){
- //这个简单,直接把所需要的曝光后的对象赋值给它就行。
- setMethod.invoke(bean,singletonObject.get(ref));
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- });
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
- });
-
-
- }catch (Exception e){
- e.printStackTrace();
- }
- }
- // 加个泛型
- @Override
- public
T getBean(String beanName,Class type) { - return (T)singletonObject.get(beanName);
- }
-
- @Override
- public Object getBean(String beanName) {
- return singletonObject.get(beanName);
- }
-
-
- }