手写IOC-实现

908 阅读1分钟

github地址:github.com/zexho994/IO…

流程

image.png

Bean的声明

以注解的方式为例,在类上添加@Bean注解即表示该Class为一个Bean,例如:

@Bean
public class BeanTest1 implements BeanTest {

    @Override
    public void print() {
        System.out.println("BeanTest1");
    }

}

在项目启动的时候会扫描目录下所有的Class,流程如下:

image.png

public static List<Class<?>> findAllBean() {
    ClassLoader contextClassLoader = getDefaultClassLoader();  //获取默认类加载器
    List<String> classes = scanClasses(contextClassLoader);    //扫描所有Class类
    return filtersAndLoadBeans(classes, contextClassLoader);   //过滤,获取所有Bean
}

public void loadBean() {
    BeanScanner
        .findAllBean()
        .forEach(bean -> AnnotationDefinitionLoaderRegistry.
                 this.register(bean.getSimpleName(), bean));  //注册所有的bean
}

具体的的代码细节不详细展开,需要的可以看源码。

到此,所有的Bean都已经保存到了map结构中,当需要使用Bean的时候根据bean name进行获取就好了。

@Autowired实现

image.png

@Bean
public class AutowiredTest {

    @Autowired
    public BeanTest1 beanTest1;
    @Autowired
    public BeanTest2 beanTest2;

    public void print1() {
        beanTest1.print();
    }

    public void print2() {
        beanTest2.print();
    }
}
// 初始化bean
private void initBean(BeanDefinition beanDefinition) throws IllegalAccessException {
    Object instance = beanDefinition.getInstance();

    // 初始化Autowired
    this.initAutowire(instance);

    beanDefinition.setStatusInitialized();
}

/** 
* 设置bean里面的注入字段
*/
private void initAutowire(Object instance) throws IllegalAccessException {
    // 获取所有字段,如果有Autowired注解,获取该bean,然后赋值给字段
    for (Field field : instance.getClass().getFields()) {
        if (field.getDeclaredAnnotationsByType(Autowired.class).length == 0) {
            continue;
        }
        Class<?> fieldType = field.getType();
        Object bean = this.getBean(fieldType.getSimpleName());
        field.set(instance, bean);
    }
}