简单实现spring的set依赖注入

 Maven依赖:



    4.0.0

    org.myspringframework
    myspring
    1.0-SNAPSHOT

    jar
    
        17
        17
        UTF-8
    
    

        
            dom4j
            dom4j
            1.1
        

        
            jaxen
            jaxen
            1.2.0
        

        
            junit
            junit
            4.13.2
            test
        
    
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);
    }


}

你可能感兴趣的:(spring,java,前端)