【学习笔记】手写一个简单的 Spring IOC

目录

一、什么是 Spring IOC?

二、IOC 的作用

1. IOC 怎么知道要创建哪些对象呢?

2. 创建出来的对象放在哪儿?

3. 创建出来的对象如果有属性,如何给属性赋值?

三、实现步骤

1. 创建自定义注解

2. 创建 IOC 容器

1. 创建 Bean 定义类

2. 创建 IOC 容器

3. 扫描包

4. 使用自定义注解

5. 在 Servlet 中初始化 IOC 对象

6. 测试

3. 实例化 Bean 

测试

4. 设置属性

1. 创建一个Controller

2. 属性赋值

3. 测试

四、使用 Bean

1. 创建获取 Bean 的方法

2. 使用 Bean 

3. 测试

五、优化 IOC 容器


一、什么是 Spring IOC?

Spring 的核心之一是 IOC,全称 Inversion Of Control ,控制反转,用来统一管理 Bean

二、IOC 的作用

IOC 的作用就是帮程序员创建 Bean 对象

1. IOC 怎么知道要创建哪些对象呢?

xml 配置文件中指定要创建哪些对象,或者使用注解的方式

如果使用注解的方式,需要自定义注解,自定义注解说白了就是告诉 JVM 这个 Bean 不同于其他普通的 Bean ,它有其他的用途,标记一下。

@Component、@Controller、@Service 可以用于创建 Bean 的注解

2. 创建出来的对象放在哪儿?

先记录需要被创建的 Bean 对象的信息,存到 HashMap 中,然后根据 HashMap 中存储的Bean 的信息创建对象,存到IOC容器中

3. 创建出来的对象如果有属性,如何给属性赋值?

使用注解 @Autowired

三、实现步骤

1. 创建自定义注解

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Controller {
    String value() default "";
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Autowired {
    String value() default "";
}

2. 创建 IOC 容器

扫描包,判断类上是否有注解,如果有,存储需要被创建的对象的id,也就是全类名。

定义一个类用于存储这些信息,这个类就是 BeanDefinition  叫做 Bean 定义类,Bean 定义类创建对象后称为 Bean 定义对象,这个对象存储了 Bean 的信息

然后把 Bean 定义对象存放到 HashMap 中,这个 Map 叫做 Bean 定义Map

1. 创建 Bean 定义类

package com.shao.IOC;

public class BeanDefinition {

    private String id;
    private String className;


    public BeanDefinition() {
    }

    public BeanDefinition(String id, String className) {
        this.id = id;
        this.className = className;
    }

    /**
     * 获取
     *
     * @return id
     */
    public String getId() {
        return id;
    }

    /**
     * 设置
     *
     * @param id
     */
    public void setId(String id) {
        this.id = id;
    }

    /**
     * 获取
     *
     * @return className
     */
    public String getClassName() {
        return className;
    }

    /**
     * 设置
     *
     * @param className
     */
    public void setClassName(String className) {
        this.className = className;
    }

    public String toString() {
        return "BeanDefinition{id = " + id + ", className = " + className + "}";
    }
}

2. 创建 IOC 容器

3. 扫描包

扫描包需要先知道路径是什么,从哪开始

这里扫描的是编译后的 class 文件,并不是类文件,因为程序运行后使用的是编译后的文件

那如何从这里开始呢?

使用类加载器获取路径

package com.shao.IOC;

import com.shao.Annotation.Controller;
import com.shao.Annotation.Service;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.HashMap;

/**
 * ApplicationContext 类. 当作 IOC 容器
 *
 * @author shao.
 */
public class ApplicationContext {
    /**
     * Bean 定义Map   存储Bean 定义对象
     */
    private HashMap<String, BeanDefinition> beanDefinitionMap = new HashMap<>();

    /**
     * Bean 实例Map 存储Bean 实例对象
     */
    private HashMap<String, Object> BeanMap = new HashMap<>();


    public ApplicationContext(String basePackage) throws UnsupportedEncodingException {
        scanPackage(basePackage);
    }

    /**
     * 1. 扫描包,扫描需要被创建的类,创建 Bean 定义对象,并放入 Bean 定义Map中
     */
    public void scanPackage(String basePackage) throws UnsupportedEncodingException {
//        String basePackage = "com.shao";

        // 获取类加载器
        ClassLoader classLoader = this.getClass().getClassLoader();
        // 获取包路径
        String path = classLoader.getResource(basePackage.replace(".", "/")).getPath();
        // 路径解码,如果路径有空格或者中文,会出现 16 进制的字符
        String packagePath = URLDecoder.decode(path, "UTF-8");

        // 创建文件对象
        File fileDir = new File(packagePath);

        // 获取包下的文件列表
        File[] files = fileDir.listFiles();

        for (File file : files) {
            if (file.isFile()) {
                // 判断是否是class文件
                if (file.getName().endsWith(".class")) {

                    // 包路径 + 文件名 构成全类名
                    String className = basePackage + "." + file.getName().replace(".class", "");

                    try {
                        // 动态加载了名为 className 的类,获取该类的 Class 对象
                        Class<?> aClass = Class.forName(className);

                        // 判断该类是否有 &#
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值