Mr. Cappuccino的第59杯咖啡——简单手写SpringIOC框架

这篇具有很好参考价值的文章主要介绍了Mr. Cappuccino的第59杯咖啡——简单手写SpringIOC框架。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

环境搭建

基于XML方式

项目结构

Mr. Cappuccino的第59杯咖啡——简单手写SpringIOC框架,Spring,mr,java,开发语言

项目代码

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com</groupId>
    <artifactId>spring</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>5.2.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>5.2.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.1.RELEASE</version>
        </dependency>
    </dependencies>

</project>

UserBean.java

package com.spring.bean;

/**
 * @author honey
 * @date 2023-08-08 14:58:16
 */
public class UserBean {
}

spring.xml

<?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">

    <bean id="userBean" class="com.spring.bean.UserBean"/>

</beans>

SpringTest01.java

package com.spring.test;

import com.spring.bean.UserBean;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author honey
 * @date 2023-08-08 14:59:56
 */
public class SpringTest01 {

    public static void main(String[] args) {
        // 读取spring.xml
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
        // 从IOC容器中读取对象
        UserBean userBean = applicationContext.getBean("userBean", UserBean.class);
        System.out.println(userBean);
    }
}
运行结果

Mr. Cappuccino的第59杯咖啡——简单手写SpringIOC框架,Spring,mr,java,开发语言

基于注解方式

项目结构

Mr. Cappuccino的第59杯咖啡——简单手写SpringIOC框架,Spring,mr,java,开发语言

项目代码

ScanBean.java

package com.spring.bean.scan;

import org.springframework.stereotype.Component;

/**
 * @author honey
 * @date 2023-08-08 16:37:26
 */
@Component
public class ScanBean {
}

SpringConfig.java

package com.spring.config;

import com.spring.bean.UserBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
 * @author honey
 * @date 2023-08-08 16:30:21
 */
@Configuration
@ComponentScan(value = {"com.spring.bean.scan"})
public class SpringConfig {

    @Bean(name = "user")
    public UserBean userBean() {
        return new UserBean();
    }
}

SpringTest02.java

package com.spring.test;

import com.spring.bean.UserBean;
import com.spring.bean.scan.ScanBean;
import com.spring.config.SpringConfig;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * @author honey
 * @date 2023-08-08 16:31:25
 */
public class SpringTest02 {

    public static void main(String[] args) {
        // 加载SpringConfig
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
        // 从IOC容器中读取对象
        UserBean userBean = applicationContext.getBean("user", UserBean.class);
        System.out.println(userBean);
        ScanBean scanBean = applicationContext.getBean("scanBean", ScanBean.class);
        System.out.println(scanBean);
    }
}
运行结果

Mr. Cappuccino的第59杯咖啡——简单手写SpringIOC框架,Spring,mr,java,开发语言

简单手写SpringIOC框架

核心原理

底层使用map集合管理对象,key=beanId,value=实例对象

private final Map<String, Object> beanMap = new ConcurrentHashMap<>();

基于XML方式

原理

基于反射+工厂模式+DOM技术

  1. 使用DOM技术解析spring.xml文件;
  2. 获取bean的id和class属性;
  3. 根据类的完整路径使用反射技术初始化对象;
  4. 使用工厂模式管理初始化对象;
项目结构

Mr. Cappuccino的第59杯咖啡——简单手写SpringIOC框架,Spring,mr,java,开发语言

项目代码

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com</groupId>
    <artifactId>ext-spring-ioc</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>5.2.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>5.2.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>dom4j</groupId>
            <artifactId>dom4j</artifactId>
            <version>1.6.1</version>
        </dependency>
    </dependencies>

</project>

UserBean.java

package com.spring.bean;

/**
 * @author honey
 * @date 2023-08-08 16:56:32
 */
public class UserBean {
}

spring.xml

<?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">

    <bean id="userBean" class="com.spring.bean.UserBean"/>

</beans>

SpringIocXml.java

package com.spring.ext;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.core.io.ClassPathResource;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author honey
 * @date 2023-08-08 16:57:17
 */
public class SpringIocXml {

    private final Map<String, Object> beanMap = new ConcurrentHashMap<>();

    public SpringIocXml() throws IOException, DocumentException {
        init();
    }

    public <T> T getBean(String name) {
        return (T) beanMap.get(name);
    }

    /**
     * 初始化IOC容器
     */
    private void init() throws IOException, DocumentException {
        // 解析spring.xml配置
        ClassPathResource classPathResource = new ClassPathResource("spring.xml");
        File xmlFile = classPathResource.getFile();
        SAXReader saxReader = new SAXReader();
        Document doc = saxReader.read(xmlFile);
        // 获取根节点
        Element rootElement = doc.getRootElement();
        // 获取bean节点信息
        List<Element> beans = rootElement.elements("bean");
        for (Element bean : beans) {
            try {
                String beanId = bean.attribute("id").getValue();
                String classPath = bean.attribute("class").getValue();
                // 使用反射机制初始化对象,并将对象存入Map集合
                Class<?> clazz = Class.forName(classPath);
                Object object = clazz.newInstance();
                beanMap.put(beanId, object);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

}

SpringTest01.java

package com.spring.test;

import com.spring.bean.UserBean;
import com.spring.ext.SpringIocXml;
import org.dom4j.DocumentException;

import java.io.IOException;

/**
 * @author honey
 * @date 2023-08-08 17:04:35
 */
public class SpringTest01 {

    public static void main(String[] args) throws DocumentException, IOException {
        SpringIocXml springIocXml = new SpringIocXml();
        UserBean userBean = springIocXml.getBean("userBean");
        System.out.println(userBean);
    }
}
运行结果

Mr. Cappuccino的第59杯咖啡——简单手写SpringIOC框架,Spring,mr,java,开发语言

基于注解方式

原理

基于反射+工厂模式实现

  1. 判断配置类上是否有@Configuration注解;
  2. 获取配置类中的所有方法,判断方法上是否有@Bean注解,如果有则获取方法的返回值作为实例对象;
  3. 判断配置类上是否有@ComponentScan注解,如果有则扫描指定包下的所有类,并判断类上是否有@Component注解,如果有则通过反射技术初始化对象;
  4. 使用工厂模式管理初始化对象/实例对象;
项目结构

Mr. Cappuccino的第59杯咖啡——简单手写SpringIOC框架,Spring,mr,java,开发语言

项目代码

pom.xml

<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.7.7</version>
</dependency>

ScanBean.java

package com.spring.bean.scan;

import org.springframework.stereotype.Component;

/**
 * @author honey
 * @date 2023-08-09 14:28:33
 */
@Component
public class ScanBean {
}

SpringConfig.java

package com.spring.config;

import com.spring.bean.UserBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
 * @author honey
 * @date 2023-08-09 14:26:40
 */
@Configuration
@ComponentScan(value = {"com.spring.bean.scan"})
public class SpringConfig {

    @Bean
    public UserBean userBean() {
        return new UserBean();
    }
}

SpringIocAnnotation.java

package com.spring.ext;

import cn.hutool.core.lang.ClassScanner;
import cn.hutool.core.util.StrUtil;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author honey
 * @date 2023-08-09 14:12:21
 */
public class SpringIocAnnotation {

    private final Object config;
    private final Map<String, Object> beanMap = new ConcurrentHashMap<>();

    public SpringIocAnnotation(Object config) {
        this.config = config;
        init();
    }

    /**
     * 初始化IOC容器
     */
    public void init() {
        // 判断配置类上是否有@Configuration注解
        Configuration configuration = this.config.getClass().getDeclaredAnnotation(Configuration.class);
        if (configuration == null) {
            return;
        }

        // 处理@Bean注解
        Class<?> clazz = config.getClass();
        Method[] declaredMethods = clazz.getDeclaredMethods();
        for (Method method : declaredMethods) {
            // 判断方法上是否有@Bean注解
            Bean bean = method.getDeclaredAnnotation(Bean.class);
            if (bean != null) {
                try {
                    // 获取beanId
                    String[] value = bean.value();
                    String beanId = value.length > 0 ? value[0] : method.getName();
                    // 获取方法的返回值
                    Object object = method.invoke(config);
                    beanMap.put(beanId, object);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

        // 处理@Component注解
        ComponentScan componentScan = clazz.getDeclaredAnnotation(ComponentScan.class);
        if (componentScan != null) {
            for (String packageName : componentScan.value()) {
                try {
                    // 扫描指定包下的所有类
                    Set<Class<?>> classes = ClassScanner.scanPackage(packageName);
                    for (Class<?> c : classes) {
                        // 判断类上是否有@Component注解
                        Annotation component = c.getDeclaredAnnotation(Component.class);
                        if (component != null) {
                            try {
                                // 获取beanId
                                String beanId = StrUtil.lowerFirst(c.getSimpleName());
                                // 通过反射技术初始化对象
                                Object beanObject = c.newInstance();
                                beanMap.put(beanId, beanObject);
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public <T> T getBean(String name) {
        return (T) beanMap.get(name);
    }
}

SpringTest02.java

package com.spring.test;

import com.spring.bean.UserBean;
import com.spring.bean.scan.ScanBean;
import com.spring.config.SpringConfig;
import com.spring.ext.SpringIocAnnotation;

/**
 * @author honey
 * @date 2023-08-09 14:24:36
 */
public class SpringTest02 {

    public static void main(String[] args) {
        SpringIocAnnotation springIocAnnotation = new SpringIocAnnotation(new SpringConfig());
        UserBean userBean = springIocAnnotation.getBean("userBean");
        System.out.println(userBean);
        ScanBean scanBean = springIocAnnotation.getBean("scanBean");
        System.out.println(scanBean);
    }
}
运行结果

Mr. Cappuccino的第59杯咖啡——简单手写SpringIOC框架,Spring,mr,java,开发语言文章来源地址https://www.toymoban.com/news/detail-639996.html

到了这里,关于Mr. Cappuccino的第59杯咖啡——简单手写SpringIOC框架的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Mr. Cappuccino的第55杯咖啡——Mybatis一级缓存&二级缓存

    缓存越小,查询速度越快,缓存数据越少 缓存越大,查询速度越慢,缓存数据越多 在多级缓存中,一般常见的是先查询一级缓存,再查询二级缓存,但在Mybatis中是先查询二级缓存,再查询一级缓存。 在Mybatis中,BaseExecutor属于一级缓存执行器,CachingExecutor属于二级缓存执行

    2024年02月14日
    浏览(32)
  • Mr. Cappuccino的第68杯咖啡——基于Docker安装Oracle11g

    拉取镜像 以持久化的方式启动容器 关于持久化,source=oracle_vol指的是容器中的数据卷路径,target指的是容器外需要被挂载的目录路径。 查看volume的具体位置 修改配置文件 使用I键进入编辑模式,添加以下配置信息,再使用Esc键退出编辑模式,输入:wq保存配置信息。 检查配置

    2024年01月17日
    浏览(41)
  • Mr. Cappuccino的第60杯咖啡——Spring之BeanFactory和ApplicationContext

    概述 BeanFactory,以Factory结尾,表示它是一个工厂类(接口), 它是负责生产和管理bean的一个工厂。在Spring中,BeanFactory是IOC容器的核心接口,它的职责包括:实例化、定位、配置应用程序中的对象及建立这些对象间的依赖; BeanFactory只是个接口,并不是IOC容器的具体实现,但是

    2024年02月13日
    浏览(27)
  • Mr. Cappuccino的第62杯咖啡——Spring之Bean的生命周期

    实现Aware接口是为了bean能获取某些信息、感知某些信息。Aware自身是一个空的接口,Spring提供了很多它的实现接口,开发者实现这些已有的接口就能获取特定的一些信息。 Spring提供了一些Aware接口的实现接口: ApplicationContextAware、ApplicationEventPublisherAware、BeanClassLoaderAware、Be

    2024年02月12日
    浏览(23)
  • Mr. Cappuccino的第58杯咖啡——MacOS配置Maven和Java环境

    如果使用的是bash,则使用以下命令 因为我这里使用的是zsh,所以使用以下命令 下载Maven Maven下载地址 配置前准备 使用command+shift+G进入/usr/local/目录 创建maven文件夹 将下载好的Maven压缩包解压 把解压后的文件复制到maven文件夹下面,并创建repo文件夹用来存放拉取的maven依赖

    2024年02月14日
    浏览(32)
  • Mr. Cappuccino的第63杯咖啡——Spring之AnnotationConfigApplicationContext源码分析

    以上一篇文章《Spring之Bean的生命周期》的代码进行源码分析 AnnotationConfigApplicationContext.java AbstractApplicationContext.java BeanFactory中两个重要的对象 DefaultListableBeanFactory.java DefaultSingletonBeanRegistry.java Debug源码分析 register(componentClasses):注册指定的配置类SpringConfig02到beanDefinitionMap集

    2024年02月13日
    浏览(24)
  • 三分钟简单了解VR、AR、MR、XR是什么

    目录 一、VR虚拟现实( Virtual Reality ) 二、AR增强现实(Augmented Reality) 三、MR 混合现实(Mixed Reality) 四、XR扩展现实( Extended Reality)         如今随着各类3D技术、AI技术的不断发展,随着“元宇宙”概念的兴起,VR、AR、MR、XR等词频频映入眼帘,究竟什么是AR?VR?

    2024年02月08日
    浏览(28)
  • 【cobra】手写你的第一个命令行脚手架工具 | cobra整合go template通过终端以命令行方式生成.drone.yml 模板

    本次教程使用的开源框架如下: 名字 开源地址 作用 Cobra 命令行工具 https://github.com/spf13/cobra Aurora 字体颜色 https://github.com/logrusorgru/aurora go-zero go-z框架 模板功能 https://github.com/zeromicro/go-zero 本项目完整源码 :https://github.com/ctra-wang/cobra-gen-drone 概述 :Cobra 是一个 Golang 包,它

    2024年02月16日
    浏览(30)
  • 【框架源码】手写Spring框架IOC容器核心流程

    要是想要了解Spring IOC底层,首先我们就得先了解什么是IOC。 IOC就是控制反转,把对象创建和对象之间的调用过程交给Spring进行管理。 使用IOC目的就是之前我们创建对象的方式都是用new的方式创建,这个方式有个缺点,被创建对象的类的位置一旦被改动,new就会报错,类与类

    2024年02月06日
    浏览(42)
  • 手写Spring框架

    各位道友,我发现现在贼卷底层代码,看完源码发下几天后,额!!!我当时看了啥! 还是自己写个迷你的spring框架,这样印象更加深刻,上干货,代码仓库:https://gitee.com/smd_somin/SmdSpring.git 上面是我写的迷你版的spring框架,麻雀虽小,五脏俱全,主要包括下边的内容 容器

    2024年02月06日
    浏览(17)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包