Simple to learn and use under springIoc reflection mechanism is how to achieve

What is springIoc

IOC (Inversion of Control)
means the inversion of control, he is a design idea is not practical technology the core idea is to create a control object instance to the program (IOC container)..
IOC container:
a management all control reverse objects created during key-value container structure (may be simply understood as: hashMap ')
the Spring of the IOC (inversion control) constructed in the object instance options?
1. Create a constructor with no arguments
2. Create static factory: static method in class constructor
3. examples of the factory was founded: the method to construct the object instance of
the demo code:
the Spring-ioc.xml profile content:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!-- 创建方式1:空参构造创建 -->
    <bean id="a" class="com.czy.project.demo6.A"/>
    <!--
        创建方式2:静态工厂创建
        调用A的createBObj方法来创建名为b的对象放入容器
    -->
    <bean id="b" class="com.czy.project.demo6.A" factory-method="createBObj"/>
    <!--
            创建方式3:实例工厂创建
            调用实例a的createCObj方法来创建名为c的对象放入容器
     -->
    <bean id="c" factory-bean="a" factory-method="createCObj"/>
</beans>

Class A Code:

public class A {
    public A() {
        System.out.println("A 无参构造器被调用了.");
    }
    public static B createBObj() {
        System.out.println("A 的静态方法 createBObj 被调用了.");
        return new B();
    }
      public C createCObj() {
        System.out.println("A 的实例方法 createCObj 被调用了.");
        return new C();
    }
}

Code Class B:

public class B {
 
}

Class C Code:

public class C {

}

Startup class code:

public class Main {
    public static void main(String[] args) {
        ApplicationContext context =
                new ClassPathXmlApplicationContext("spring-ioc.xml");
        A a = (A) context.getBean("a");
        B b = (B) context.getBean("b");
        C c = (C) context.getBean("c");
    }
}

Output:

Here Insert Picture Description
Through the above cases, we already know the way to build the concept and examples of the IOC. Next we explore his core implementation.

Handwritten springIoc realization of ideas

说明:以下代码需要的xml配置文件以及实体类还是用上边的

spring is to configure the bean in xml, know object-oriented thinking, then you certainly can think of is certainly content should xml file read out and receiving objects. Then
1. Create for receiving the xml configuration class bean

/**
 * 用于接收xml中bean标签的属性
 * 没什么东西,就是根据bean标签中的属性来定义的
 * Author : czy
 */
public class BeanConfig {
    private String id;
    private String clazz;
    private String factoryMethod;
    private String factoryBean;
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getClazz() {
        return clazz;
    }
    public void setClazz(String clazz) {
        this.clazz = clazz;
    }
    public String getFactoryMethod() {
        return factoryMethod;
    }
    public void setFactoryMethod(String factoryMethod) {
        this.factoryMethod = factoryMethod;
    }
    public String getFactoryBean() {
        return factoryBean;
    }
    public void setFactoryBean(String factoryBean) {
        this.factoryBean = factoryBean;
    }
}

spring inlet is not new ClassPathXmlApplicationContext ( "xml file name");
then we will use XmlApplicationContext ( "xml file name"); // Are You Ok? -> the ok
2. Create a class XmlApplicationContext

/**
 * 相当于Springl中ClassPathXmlApplicationContext
 * 1、解析xml文件
 * 2、获取xml文件所有的节点内容
 * 3、利用java反射机制创建实例对象
 * 4、将实例对象添加到ioc容器
 * czy say :SO EASY
 */
public class XmlApplicationContext {
    // xml路径
    private String xmlPath;
    // 存放bean(也就是ioc的容器)
    private static HashMap map = new HashMap();
    //存放从xml中解析出来的所有bean
    private List<BeanConfig> beanConfigs = new ArrayList<BeanConfig>();

    //对外的构造函数
    public XmlApplicationContext(String xmlPath) {
        this.xmlPath = xmlPath;
        try {
            //解析xml到beanConfigs
            getAllElements();
            //初始化ioc容器
            init();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 读取xml文件所有的节点内容,并放入beanConfigs集合
     */
    private void getAllElements() throws Exception {
        //1.指定路径加载xml到jvm,形成输入流,xml中的所有内容都在这个流中
        InputStream is = XmlApplicationContext.class.getClassLoader().getResourceAsStream(xmlPath);
        //2.创建解析对象
        SAXReader reader = new SAXReader();
        //3.获得文档对象(整个xml文件->将输入流转换成文档对象)
        Document document = reader.read(is);
        //4.获取根节点,也就是对应spring-ioc.xml中的树干beans
        Element rootElement = document.getRootElement();
        //5.获取元素迭代器,用于获取所有节点内容
        Iterator iterator = rootElement.elementIterator();
        while (iterator.hasNext()) {
            //用于接收xml中bean的属性值
            BeanConfig beanConfig = new BeanConfig();
            //获取beans的子节点bean
            Element bean = (Element) iterator.next();
            // 获取bean的属性迭代器
            Iterator beanAttributes = bean.attributeIterator();
            while (beanAttributes.hasNext()) {
                Attribute attribute = (Attribute) beanAttributes.next();
                String attributeName = attribute.getName();//属性名
                String attributeData = (String) attribute.getData();//属性值
                if ("id".equals(attributeName)) {
                    beanConfig.setId(attributeData);
                } else if ("class".equals(attributeName)) {
                    beanConfig.setClazz(attributeData);
                } else if ("factory-method".equals(attributeName)) {
                    beanConfig.setFactoryMethod(attributeData);
                } else {
                    beanConfig.setFactoryBean(attributeData);
                }
            }
            //将这条bean的属性值放入beanConfigs集合
            beanConfigs.add(beanConfig);
        }
    }
    
    /**
     * 这里初始化ioc容器是关键
     * 这里就要利用java的反射机制来创建bean实例
     *
     * @throws Exception
     */
    private void init() throws Exception {
        /**
         * 这里说一点:
         * 看spring-ioc.xml中:bean标签有class属性时就没有factory-bean属性,反之
         * 有class属性时,就要判断是空参构造创建还是静态工厂创建,也就是判断有没有factory-method属性
         * 有factory-bean时,必然是实例工厂创建-必须有factory-method
         * 这点要捋清楚
         */
        for (BeanConfig bean : beanConfigs) {
            if (null != bean.getClazz()) {
                //通过全限定类名拿到Class实例clazz
                Class clazz = Class.forName(bean.getClazz());
                if (null != bean.getFactoryMethod()) {//静态工厂创建bean实例
                    //方法名获取method对象
                    Method method = clazz.getDeclaredMethod(bean.getFactoryMethod());
                    putBean(bean.getId(), method.invoke(null));
                } else {//构造器创建bean实例
                    putBean(bean.getId(), clazz.newInstance());
                }
            } else if (null != bean.getFactoryBean()) {//实例工厂创建bean实例
                //从容器中拿到实体bean
                Object obj = getBean(bean.getFactoryBean());
                Method method = obj.getClass().getDeclaredMethod(bean.getFactoryMethod());
                putBean(bean.getId(), method.invoke(obj));
            } else {
                System.out.println("czy不知道在搞什么鬼");
            }
        }
    }

    /**
     * 添加实例对象到ioc容器
     *
     * @param id:就是bean中自定义的id
     * @param object :就是反射机制创建的实例对象
     */
    public void putBean(String id, Object object) {
        map.put(id, object);
    }

    /**
     * 通过id获取实例对象
     *
     * @param id:就是bean中自定义的id
     * @return
     */
    public Object getBean(String id) {
        return map.get(id);
    }
}

3. Create a startup class Main
is not the start of the presentation and the top entry code like.

public class Main {
    public static void main(String[] args) {
        XmlApplicationContext context = new XmlApplicationContext("spring-ioc.xml");
        A a = (A)context.getBean("a");
        B b = (B) context.getBean("b");
        C c = (C) context.getBean("c");
    }
}

It would have to do the test results is not a considerate person.
4. Test
Haha, to test the reader to test it! I believe you are very interested.
5. Summary
springIoc idea is roughly like this:

1, analytic xml document
2, all the nodes acquire the content xml file
3, create an instance using java reflection mechanism
4, adds the instance object to the container ioc

But to know the internal spring to achieve this not just a few hundred lines ah.
Tips: build their own projects, be able to use the code to copy directly down, and read more feeling. Pure handwritten comments in the code, feel quite detailed, read line by line. I believe certainly after reading the beginners will know how to achieve ioc spring of ideas. And it is also able to grasp how the content is read out xml and receiving objects.

最后为了方便大家创建工程:

<dependencies>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.1.8.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>dom4j</groupId>
      <artifactId>dom4j</artifactId>
      <version>1.6.1</version>
    </dependency>   
</dependencies> 
Published 17 original articles · won praise 29 · views 6542

Guess you like

Origin blog.csdn.net/weixin_45240169/article/details/104192705