Spring ioc 简单理解

本文通过实现一个简易的IoC容器,介绍了BeanDefinition、BeanReader、BeanRegister和BeanFactory等核心组件的功能及交互过程,帮助读者理解Spring IoC的基本原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参看资料:《Spring揭秘》

DefaultListableBeanFactory看的糊里糊涂的,这篇博客写一下我对Spring ioc的理解,肯定有错误的地方,希望各位指点,不要喷我哈(o.o)。如果你是小白,你可能需要看一下java的反射机制

首先,如果你想要通过配置文件的方法来给bean配置,
你可以就需要四个类,
第一个是BeanDefinition,这个类中保存有配置文件中的每一个配置的bean的信息,最终会通过BeanDefinition提供的信息来生产bean.
第二个是BeanReader,这个类读取配置文件,并把相应的信息转换成BeanDefinition。
第三个是BeanRegist,这个类的作用,就是保存BeanDefinition,BeanDefinition保存bean的信息,BeanRegist保存所有的BeanDefinition(配置文件的每个bean都会有一个相对应的BeanDefinition)。
第四才是我们的BeanFactory,所有的类最后都是通过BeanFactory跟程序员打交道的。
现在我们可以试着来实现一个简单的ioc容器:我们用.properties来所配置文件,用java的Properties类来读取我们的配置文件。
首先是配置文件:

bean_name=com.myioc.Book
book_name=ceshi
book_author=ceshizhe

/*然后是我们的实体类*/
package com.myioc;

public class Book {

    private String book_name;
    private String book_author;
    public String getBook_name() {
        return book_name;
    }
    public void setBook_name(String book_name) {
        this.book_name = book_name;
    }
    public String getBook_author() {
        return book_author;
    }
    public void setBook_author(String book_author) {
        this.book_author = book_author;
    }
    @Override
    public String toString() {
        return "Book [book_name=" + book_name + ", book_author=" + book_author
                + "]";
    }

}

现在需要我们的BeanDefinition

import java.util.Properties;

public class BeanDefinition {

    /*我用一个String来保存bean的名字*/
    private String beanName;

    /*用Properties来保存配置的信息*/
    private Properties propertieslist;

    /*setter,getter方法,用来设置属性,不然怎么保存*/

    /*为了测试,把toString方法重写*/
    @Override
    public String toString() {
        return "BeanDefinition [beanName=" + beanName + ", propertieslist="
                + propertieslist + "]";
    }
}

BeanReader

import java.io.File;
import java.io.FileInputStream;
import java.util.Properties;

public class MyReader {

    public void loadfile(String classpath,MyRegister myRegister) {
        /*这个地方有点绕,reader不但要读取文件,还要将从文件读取到的BeanDefinition注册到Register中,这样Register才能管理Bean*/


        Properties properties = new Properties();

        /*给定classpath将配置文件读入*/
        try {
            File file = new File(classpath);
            FileInputStream inStream = new FileInputStream(file);

            /*读取配置文件*/
            properties.load(inStream);

        } catch(Exception e) {
            System.out.println("配置文件没找到");
        }

        /*生成一个BeanDefinition*/
        BeanDefinition beanDefinition = new BeanDefinition();

        /*设置Bean的名字*/
        beanDefinition.setBeanName(properties.getProperty("bean_name"));

        /*properties中保存了属性名字和对应的名字,直接保存就行了*/
        beanDefinition.setPropertieslist(properties);

        /*向传入的myRegister注册Beandefinition*/
        myRegister.registerBeanDefinition(beanDefinition);
    }
}

然后是BeanRegister

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

public class MyRegister {

    private Map<String, BeanDefinition> beanDefinitions = new HashMap<>();

    /*将beanDefinition放入自己的Map中管理*/
    public void registerBeanDefinition(BeanDefinition beanDefinition) {

        beanDefinitions.put(beanDefinition.getBeanName(), beanDefinition);
    }

    /*方便测试*/
    public Map<String, BeanDefinition> getBeanDefinitions() {
        return beanDefinitions;
    }

    public void setBeanDefinitions(Map<String, BeanDefinition> beanDefinitions) {
        this.beanDefinitions = beanDefinitions;
    }

/*这个方式是方便BeanFactory从Regist中取得BeanDefinition然后生成实例的*/
    public Object getBeanDefinition(String beanName) {
        return beanDefinitions.get(beanName);
    }   
}

/*Register和BeanFactory的关系,Spring揭秘一书中讲的很好,就好比图书馆与图书馆里面的书架的关系,借书虽然是跟图书馆打交道,但是书本是放在书架上的,这里我们的BeanFactory充当图书馆的角色,Register充当书架的角色。*/

接下来就是我们的BeanFactory

package com.myioc;

import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.Properties;
import java.util.Set;

public class MyBeanFactory {

    /*图书馆里面肯定有书架放书,Reader也可以有其他的写法,但是这里为了测试方便就放在BeanFactory中了*/
    private MyRegister myRegister = new MyRegister();
    private MyReader myReader = new MyReader();


    public MyBeanFactory(String classpath) {
        myReader.loadfile(classpath,myRegister);
        /*将配置文件的路径和Rrgister给Reader,Reader就会找到配置文件,并且将读取到的信息注册给Register*/
    }

    public Object getBean(String beanName) {

        BeanDefinition beanDefinition = (BeanDefinition)myRegister.getBeanDefinition(beanName);

        if(beanDefinition != null) {    
            try {
                /*得到beanName的Class对象*/
                Class cl = Class.forName(beanDefinition.getBeanName());

                /*得到beanDefinition中保存所有的属性值*/
                Properties properties = beanDefinition.getPropertieslist();

                /*得到properties的key值*/
                Set<Object> keySet = properties.keySet();

                Iterator<Object> si = keySet.iterator();

                /*生成实例*/
                Object newObject = cl.newInstance();

                String field;

                /*遍历,通过setter方法给 beanName的属性赋值*/
                while(si.hasNext()) {

                    /*遍历keyset中的值*/
                    field = (String)si.next();

                    if( !"bean_name".equals(field) && field != null) {
                        try {

                            Method m = cl.getMethod(makeMethod(field), String.class);
                            m.invoke(newObject, properties.getProperty(field));

                        } catch(Exception e) {
                            System.out.println("没有"+field+"的set方法");
                        }
                    }
                }
                return newObject;

            } catch(Exception e){
                System.out.println("forname错误");
            }
        }
        return null;
    }

    /*得到field的set方法*/
    private String makeMethod(String field) {
        if(field!=null) {
            field = field.substring(0, 1).toUpperCase() + field.substring(1);
            return  "set"+field;
        }
        return null;
    }
}

就这样 看起来很简单,那是因为我们实现的是简单的ioc更本不能在实际中使用,Sping在实现DefaultListableBeanFactory的时候考虑了很多东西。

现在我们可以测试了

package com.myioc;

public class Test {

    public static void main(String ar[]) {

        MyBeanFactory bf = new MyBeanFactory("src/Myioc.properties");
        Book b = (Book)bf.getBean("com.myioc.Book");
        System.out.println(b);

    }
}

文件结构:
这里写图片描述

运行结果:
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值