spring框架

1.手写spring框架

        1.1准备工作
        

package com.powernode.myspring.bean;

public class User {
    private String name;
    private int age;

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
package com.powernode.myspring.bean;

public class UserDao{
    public void insert(){
        System.out.println("mysql数据库正在保存信息");
    }
}

public class UserService {
    private UserDao userDao;

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
    public void save(){
        userDao.insert();
    }
}



    
        
        
    
    
    
        
    

        1.2核心接口实现
                不知道怎么写就看看之前写的项目模块。

package org.myspringframework.core;
//MySpring框架应用上下文接口
public interface ApplicationContext {
  /*
  * 根据Bean的名称获取对应的bean对象
   * @param BeanName myspring配置文件中bean标签 的id
   * @return 对应的单例Bean对象
   * */
    Object getBean(String BeanName);
}

                ApplicationContext里面有个getBean,它还能new ClassPathXmlApplicationContext

package org.myspringframework.core;

import java.util.HashMap;
import java.util.Map;

public class ClassPathXmlApplicationContext implements ApplicationContext{
    private Map singltonObjects = new HashMap<>();//把bean对象放到这
//    你想,反射机制springDI核心实现时,不是讲了三个缓存吗

//    构造方法来配置spring文件,一执行,解析spring文件,实例化所有bean对象
    /*
    * 解析myspring的配置文件,再初始化所有Bean对象
    * @param configLocation spring配置文件的路径。注意:使用ClassPathXmlApplicationContext,配置文件应放到类路径下
    * */

    public ClassPathXmlApplicationContext(String configLocation) {
//        解析myspring的配置文件,再初始化所有Bean对象,将Bean存放到singltonObjects集合当中
    }

    @Override
    public Object getBean(String BeanName) {
        return singltonObjects.get(BeanName);
    }
}

        1.3实例化Bean

                再往下就得实现ClassPathXmlApplicationContext的构造方法的核心程序了。
         对上面代码的类ClassPathXmlApplicationContext的构造方法进行补充

private static final Logger logger = LoggerFactory.getLogger(ClassPathXmlApplicationContext.class);

public ClassPathXmlApplicationContext(String configLocation) {
        try {
//        解析myspring的配置文件,再初始化所有Bean对象,将Bean存放到singltonObjects集合当中
//        SAXReader是dom4j解析xml文件的核心对象。
            SAXReader reader = new SAXReader();
//        获取一个输入流,指向配置文件   类加载器,get系统类加载器,再输入文件config,将其资源变为流
            InputStream in = ClassLoader.getSystemClassLoader().getResourceAsStream(configLocation);
//            读文件
            Document document = reader.read(in);
//            获取所有的bean标签
            List nodes = document.selectNodes("//bean");
//            遍历bean标签
            nodes.forEach(node -> {
                try {
                    //                System.out.println(node);
//                向下转型的目的是为了使用Element接口更加丰富的方法---
//                --为啥说向下。 Element extends Branch;Branch extends Node,类图中,Element在下,Node在上,在下的有更多方法
                    Element beanEle = (Element) node;
//                获取id属性(beanName)
                    String id = beanEle.attributeValue("id");
//                获取class属性
                    String className = beanEle.attributeValue("class");
//                    logger.info("beanName="+id);
//                    logger.info("ClassName="+className);
//                    通过反射机制创建对象,将其放到Map集合中,提前曝光。
//                    获取class
                    Class aClass = Class.forName(className);
//                    获取无参数构造方法
                    Constructor defaultCon = aClass.getDeclaredConstructor();
//                    调用无参数构造方法实例化Bean
                    Object bean = defaultCon.newInstance();
//                    将Bean曝光,加入Map集合
                    singltonObjects.put(id,bean);
//                    记录日志
                    logger.info(singltonObjects.toString());
                }catch (Exception e){
                    e.printStackTrace();
                }

            });

        }catch (Exception e){
            e.printStackTrace();
        }
    }

        1.4获取所有set方法

再次把所有bean标签遍历一次,这一次主要是给对象的属性赋值
     nodes.forEach(node -> {
          try {
              Element beanEle = (Element) node;
//                获取id
              String id = beanEle.attributeValue("id");
//                获取className
              String className = beanEle.attributeValue("class");

//                获取类class
              Class aClass = Class.forName(className);

//                获取该bean标签下 所有的属性property标签
              List propertys = beanEle.elements("property");

//                遍历所有的属性标签
              propertys.forEach(property -> {

                   try {
//                    获取属性名
                      String propertyName = property.attributeValue("name");
                      logger.info("属性名"+propertyName);
//                获取属性类型
                      Field field = aClass.getDeclaredField(propertyName);

//                获取set方法名
                      String setMethodName = "set" + propertyName.toUpperCase().charAt(0)+propertyName.substring(1);

//                      获取set方法
                            Method setMethod = aClass.getDeclaredMethod(setMethodName, field.getType());
调用set方法(set方法没有返回值)
setMethod.invoke(singltonObjects.get(id),传入什么具体的值?);

        1.5给非简单类型属性赋值

非简单的不就是ref=”bean对象id“ , 既然它是beanId,那就是拿个bean对象作属性,我们前面不是把所有实例化bean对象都放到Map中了吗,那我拿到ref不就拿到BeanId,就用id从map中取出不就好了。
 

   获取属性对应的具体的值

   String value = property.attributeValue("value");
//既然我不知道它属性对应的值是value还是ref,我就都要
   String ref = property.attributeValue("ref");

   if(value!=null){
//                      说明这个值是简单类型
//                      调用set方法(set方法没有返回值)
        setMethod.invoke(singltonObjects.get(id),传入什么类型的具体值);
                   }
   if (ref!=null){
//                      说明这个值是非简单类型
//                      调用set方法(set方法没有返回值)
                            setMethod.invoke(singltonObjects.get(id),singltonObjects.get(ref));

        能进哪个if,就说明它是value 还是 ref

        1.6给简单类型属性赋值

        简单类型有很多种,不想ref,直接拿个bean对象作为属性。 
        我们得知道它得简单类型 是 什么类型,,才好传具体值

switch-case太惨了,这么多种。。。

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