19.Spring源码解读之简单手写spring框架

1.Spring底层源码解读课程安排
2.Springxml、注解实现IOC区别
3.简单模拟手写出xml方式实现IOC
4.简单模拟手写出注解方式实现IOC

2022版本Spring5深入源码解读
Spring5源码分析之IOC原理掌握Spring5的源码正确阅读方式、bean对象创建与初始化、一步一步手绘spring源码架构图
Spring5源码分析之IOC原理掌握BeanFactory与FactoryBean原理分析、后置处理器增强、Bean的生命周期源码分析监听器与事件监听事件机制源码分析
Spring5源码分析之循环依赖掌握怎么检测循环依赖、怎么解决循环依赖、循环依赖无法解决的场景、三级与二级缓存设计
Spring5源码分析之AOP原理掌握手绘Aop流程架构图、Aop调用链、动态代理模式应用、事务失效之谜与底层实现
Spring5源码分析之AOP原理掌握Spring5的高级应用、巧妙的运用在工作中、经典Spring面试题
Spring5源码分析之事务原理掌握PlatformTransactionManager、TransactionManager、传播行为原理
SpringMVC源码分析之SpringMVC请求处理流程掌握SpringMVC请求处理流程、SpringMVC的工作机制、DispatcherServlet
SpringMVC源码分析之SpringMVC请求处理流程掌握SpringMVC请求的时候是如何找到正确的Controller、Controller的方法中参数的工作原理
SpringMVC源码分析之SpringMVC请求处理流程掌握json、xml自动转换的原理研究、类型转换、数据绑定详解、MVC拦截器详解、MVC视图机制详解、异常处理机制详解
SpringBoot源码解读之启动原理分析掌握@EnableAutoConfiguration @SpringBootApplication、Springboot自动装配的实现原理
SpringBoot源码解读之自定义starter组件掌握SpringBoot自定义starter组件原理

Spring环境搭建

Spring 配置bean方式

方式1 xml方式

方式2 注解方式

SpringBoot 底层 基于 Spring注解封装

maven

    <dependencies>
        <dependency>
            <groupId>dom4j</groupId>
            <artifactId>dom4j</artifactId>
            <version>1.6.1</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/jaxen/jaxen -->
        <dependency>
            <groupId>jaxen</groupId>
            <artifactId>jaxen</artifactId>
            <version>1.2.0</version>
        </dependency>
        <!-- 反射框架 -->
        <dependency>
            <groupId>org.reflections</groupId>
            <artifactId>reflections</artifactId>
            <version>0.9.11</version>
        </dependency>
    </dependencies>

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

    <!--
     配置SpringBean对象
     -->
    <bean id="userEntity" class="com.mayikt.entity.UserEntity"></bean>
    <bean id="mayiktService" class="com.mayikt.service.MayiktService"></bean>
</beans>
package com.mayikt.test;

import com.mayikt.entity.UserEntity;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author 余胜军
 * @ClassName Test01
 * @qq 644064779
 * @addres www.mayikt.com
 * 微信:yushengjun644
 */
public class Test01 {
    public static void main(String[] args) {
        //1.读取spring.xml
        ClassPathXmlApplicationContext classPathXmlApplicationContext =
                new ClassPathXmlApplicationContext("spring.xml");
        //2.从IOC容器读取到userEntity
        UserEntity userEntity =
                classPathXmlApplicationContext.getBean("userEntity", UserEntity.class);
        System.out.println(userEntity);
    }
}

注解方式

package com.mayikt.config;

import com.mayikt.entity.UserEntity;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
* @author songchuanfu
* @qq 1802284273
*/
@Configuration
@ComponentScan("com.mayikt.service")
public class MayiktConfig {
    @Bean("user")
    public UserEntity userEntity() {
        return new UserEntity();
    }
}
package com.mayikt.test;

import com.mayikt.config.MayiktConfig;
import com.mayikt.entity.UserEntity;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
* @author songchuanfu
* @qq 1802284273
*/
public class Test02 {
    public static void main(String[] args) {
        //加载MayiktConfig.class
        AnnotationConfigApplicationContext mayiktConfig
                = new AnnotationConfigApplicationContext(MayiktConfig.class);
        // 获取userEntity
        UserEntity userEntity = mayiktConfig.getBean("userEntity", UserEntity.class);
        System.out.println(userEntity);
    }
}

简单手写spring框架

简单手写spring框架 xml方式

SpringIOC容器底层实现原理:

反射+工厂模式+解析xml技术实现

1.使用解析xml技术 解析spring.xml配置文件;

2.获取 类的完整路径地址

3.使用到反射技术初始化对象

4.需要使用工厂模式封装初始化对象

package com.mayikt.ext;

import com.mayikt.entity.UserEntity;
import com.mayikt.service.MayiktService;
import org.dom4j.*;
import org.dom4j.io.SAXReader;
import org.springframework.core.io.ClassPathResource;

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

/**
* @author songchuanfu
* @qq 1802284273
*/
public class SpringIOCXml {
    private ConcurrentHashMap<String, Object> beansHashMap = new ConcurrentHashMap<>();

    public SpringIOCXml() throws IOException, DocumentException {
        // 初始化IOC容器
        initIoc();
    }

    public <T> T getBean(String name, Class<T> requiredType) {
        Object o = beansHashMap.get(name);
        return (T) o;
    }

    private void initIoc() throws IOException, DocumentException {
        //1.解析xml配置
        ClassPathResource classPathResource = new ClassPathResource("spring.xml");
        File xmlFile = classPathResource.getFile();
        SAXReader saxReader = new SAXReader();
        Document doc = saxReader.read(xmlFile);
        // 获取到根节点
        Element rootElement = doc.getRootElement();
        List<Element> beans = rootElement.elements("bean");
        beans.forEach((bean -> {
            try {
                //2.查找   <bean id="userEntity" class="com.mayikt.entity.UserEntity"></bean>
                //3.利用反射机制初始化 class="com.mayikt.entity.UserEntity" 将bean对象存入Map集合中
                String beanIdStr = bean.attribute("id").getValue();
                String classStr = bean.attribute("class").getValue();
                Class<?> bClass = Class.forName(classStr);
                Object object = bClass.newInstance();
                beansHashMap.put(beanIdStr, object);
            } catch (Exception e) {
            }
        }));
    }

    public static void main(String[] args) throws DocumentException, IOException {
        SpringIOCXml springIOCXml = new SpringIOCXml();
        UserEntity userEntity = springIOCXml.getBean("userEntity", UserEntity.class);
        MayiktService mayiktService = springIOCXml.getBean("mayiktService", MayiktService.class);
        mayiktService.add();
    }


}

简单手写spring框架ioc 注解方式

思路:

1.ioc容器底层核心 HashMap集合 (key=beanid value=bean对象)

user()

beanid:user bean对象 new UserEntity();

HashMap.put(user ,new UserEntity());

getBean("user ")-----new UserEntity()

1.将spring.xml配置文件读取到程序中

2.利用解析xml框架spring.xml

3.获取(bean标签)节点 beanid ====HashMap.key value 利用反射机制初始化

com.mayikt.service.OrderService

@ComponentScan(“com.mayikt.service”)

1.利用java反射机制获取到该包下所有的类(class)

2.利用java反射机制 判断每个类上是否有加上@Component

3.如果有加上该注解的情况下 类的名称 首字母变成小写 作为bean的id value

该类class 利用反射初始化

4.存入到map集合中。

1.使用@Bean注解 ----没有反射初始化对象 根据方法返回值 作为 bean对象

2.@ComponentScan 底层 使用反射初始化对象

3.xml

package com.mayikt.ext;

import com.mayikt.config.MayiktConfig;
import com.mayikt.entity.UserEntity;
import com.mayikt.service.MayiktService;
import com.mayikt.service.OrderService;
import com.mayikt.utils.ClassUtils;
import org.reflections.Reflections;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

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

/**
* @author songchuanfu
* @qq 1802284273
*/
public class SpringIOCAnnotation {
    private Object config;
    private ConcurrentHashMap<String, Object> beansHashMap = new ConcurrentHashMap<>();

    /**
     * 传递配置类
     */
    public SpringIOCAnnotation(Object config) {
        this.config = config;
        initIoc();
    }

    /**
     * 初始化IOC容器
     */
    public void initIoc() {
        Configuration configuration
                = this.config.getClass().getDeclaredAnnotation(Configuration.class);
        if (configuration == null) {
            return;
        }
        // 如果该类上有配置configuration
        // 利用java反射机制
        Class<?> aClass = config.getClass();
        Method[] declaredMethods = aClass.getDeclaredMethods();
        Arrays.stream(declaredMethods).forEach(m -> {
            Bean bean = m.getDeclaredAnnotation(Bean.class);
            if (bean != null) {
                try {
                    // 方法名称作为bean的id
                    String[] value = bean.value();
                    String beanId = value[0];
                    String defBeanId = m.getName();
                    // 获取方法返回值
                    Object result = m.invoke(config, null);
                    beansHashMap.put(StringUtils.isEmpty(beanId) ? defBeanId : beanId, result);
                } catch (Exception e) {

                }
            }
        });
        //ComponentScan
        //利用反射机制查找 该包下所有的class
        ComponentScan componentScan = aClass.getDeclaredAnnotation(ComponentScan.class);
        if (componentScan != null) {
            String[] strings = componentScan.value();
            Arrays.stream(strings).forEach(pack -> {
                Class[] classByPackage = ClassUtils.getClassByPackage(pack);
                Arrays.stream(classByPackage).forEach(c -> {
                    Annotation component = c.getDeclaredAnnotation(Component.class);
                    if (component != null) {
                        try {
                            // 注入到ioc容器中
                            String beanId = c.getSimpleName();
                            Object beanObject = c.newInstance();
                            beansHashMap.put(beanId, beanObject);
                        } catch (Exception e) {

                        }
                    }
                });
            });
        }

    }


    public <T> T getBean(String name, Class<T> requiredType) {
        Object o = beansHashMap.get(name);
        return (T) o;
    }

    public static void main(String[] args) {
        SpringIOCAnnotation springIOCAnnotation =
                new SpringIOCAnnotation(new MayiktConfig());
        OrderService orderService =
                springIOCAnnotation.getBean("OrderService", OrderService.class);
        System.out.println(orderService);
    }
}

相关code

📎spring源码day01.rar

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陌陌龙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值