IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Spring底层源码解析 -> 正文阅读

[Java知识库]Spring底层源码解析

Spring流程图

?

?上面这个图呢是我自己画出来的总结图:(可以看下面我写的spring简易版代码就懂了)

? ? ? ? 我们可以知道当你使用spring的时候需要些一些配置类啊什么的那么我们是怎么去拿到的呢,

  • 首先我们有一个BeanDefinitionRead去解析你的xml配置文件然后读成BeanDefintion也可以理解为Bean的定义信息,那么拿到定义信息的时候呢我们下一步就是去实例化了,但是注意了这里并不是正在去走实例化,在走实例化的过程中我们需要一个工厂也就是BeanFactory然后工厂利用反射拿到信息,在这之前呢我们BeanFactoryPostProcessor一个增强器图上面我也写了笔记说是获取信息的时候发现需要人为修改一些信息的时候,我们就可以在这里操作了然后再通过工厂去实例化,
  • 在实例化的过程中我们还有一个BeanPostProcessor增强器也是可以做一些操作的接下来就是真正的实例化了,
  • 在实例化过后我们就是初始化但是在初始化前后呢也有两个方法一个Before一个After但是区别是Before是在初始化之前执行After是在初始化之后执行这里不要搞混了
  • 完成初始化之后就是真正的Bean了

Spring创建生命周期流程图

package com.project.bean;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class A {

    @Autowired
    private B b;
    
    public void say(){
        b.sayHello();
    }
}
package com.project.bean;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class B {

   @Autowired
    private A a;

   public void sayHello(){
       a.say();
   }
}

首先这里重点我要讲的是循环依赖:

循环依赖是什么呢,就是当a在创建bean的时候注入了b,而且在a中调用了b,然后我们依赖就会提前创建b属性,但是在c中呢也调用了a,就导致a还没有创建完就调用b,然后再创建b中又去调用了a从此生成循环依赖:那么底层解决方法是什么呢,其实图上面也说了,那我就在详细的说明一下:

  1. 当类通过构造方法的时候他会生成一个普通对象并且会放入到三级缓存中,但只是生成一个lambde不会执行只是生成
  2. 在普通对象发现有依赖注入那么首先会去创建需要依赖注入的对象
  3. 如果是正常的情况下我们会先去单例池中找
  4. 如果没有找到那么就正常的CreateBean创建Bean然后再放入单例池
  5. 如果出现循环依赖,在循环依赖的情况下我们在创建依赖对象的时候发现CreateSet就说明是循环依赖了那么我们底层会先去放入到二级缓存中(earlySingletonObjects--->是一个Map),但是在放入二级缓存中呢我们会去查找二级缓存有没有这个对象在二级缓存如果没有的话我们就去查找三级缓存(singletonFactories),这个时候会执行一开始的lambde对象如果找到了那就返回但是这里要考虑到一个情况如果你是开起来aop那么在这里他会生成代理对象放入到二级缓存,如果没有开启aop的话就不会生成代理对象而是生成普通对象放入到二级缓存中,然后二级缓存在把对象放入到单例池中。

依赖注入不正常情况下,比如加了sycn注解或者两个对象的构造器互相调用那么我们的解决方法是添加lazy注解,如果不加就会报错

这里呢也分享一个面试问题:就是说二级循环二级也能解决,为什么需要三级缓存?

答案呢是:二级缓存只能解决没有aop的循环依赖当有aop的时候就需要三级缓存了。

Spring流程---->十三个方法

?

上面这个图呢是我耗时一个上午画出来的一个详细版的spring流程图也是对应的底层十三个方法的详细解说版本的图片,制作不易请好好品一品。


这里呢我们可以先创建一个spring工程然后写一个对象和一个配置类写一个启动类

package com.project.dao;

public interface UserDao {
    public void update();
}
<?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-->

    <!--    service和dao对象创建-->
    <bean id="userService" class="com.project.Service.UserService">
        <!--        注入userdao对象-->
        <!--        name属性 : userDao是属性名称-->
        <!--        ref属性: 创建userDao对象bean标签的id值-->
        <property name="userDao" ref="userDaoimpl"></property>
    </bean>

    <bean id="userDaoimpl" class="com.project.dao.UserDaoimpl"></bean>


</beans>
 @Test
    public void testBean1() {
//        加载spring配置文件
        ApplicationContext Context = new ClassPathXmlApplicationContext("bean2.xml");

//        获取配置创建的对象
        UserService userService = Context.getBean("userService", UserService.class);
        userService.add();
    }

这里我们是在ApplicationContext Context = new ClassPathXmlApplicationContext("bean2.xml");这个地方打断点的然后进去:一直走到refresh方法然后点进去就能看见十三个方法了。那么这里呢如果要详细的说的话实在是太耗费打字了实在是太细了所以呢大家看图就行看图就行,通俗易懂。

手写简易版的Spring

嗯。。这里代码稍微有点多,我就不放那么多了就把核心的代码放出来如果您有需要的话呢可以在评论区留个言我看见了的话会把源码发给您的,感谢支持

package com.project.spring;

import java.beans.Introspector;
import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.ArrayList;
import java.util.concurrent.ConcurrentHashMap;

public class ApplicationContext {

    private Class configClass;

    private ConcurrentHashMap<String,BeanDefinition> concurrentHashMap = new ConcurrentHashMap<>();
    private ConcurrentHashMap<String,Object> singletonObjects = new ConcurrentHashMap<>();
    private ArrayList<BeanPostProsessor> beanPostProsessorArrayList = new ArrayList<>();


    // 扫描
    public ApplicationContext(Class configClass){
        this.configClass = configClass;

        if (configClass.isAnnotationPresent(ComponentScan.class)) {
            ComponentScan configClassAnnotation = (ComponentScan) configClass.getAnnotation(ComponentScan.class);
            // 扫描路径
            String path = configClassAnnotation.value();
            // 截取0到第一个.的位置
            String pathFirstName = path.substring(0,path.indexOf("."));
            // 把路径中的.替换成/
            path = path.replace(".","/");
            // 类加载器
            ClassLoader classLoader = ApplicationContext.class.getClassLoader();
            // 获取路径
            URL resource = classLoader.getResource(path);
            File file = new File(resource.getFile());
            if (file.isDirectory()){
                File[] files = file.listFiles();
                for (File f : files) {
                    // 获取绝对路径 .class文件
                    String fileName = f.getAbsolutePath();
                    if (fileName.endsWith(".class")) {
                        String className = fileName.substring(fileName.indexOf(pathFirstName), fileName.indexOf(".class"));
                        className = className.replace("\\",".");
                        try {
                            Class<?> aClass = classLoader.loadClass(className);
                            // 判断是否是bean
                            if (aClass.isAnnotationPresent(Component.class)){

                                // 判断是否实现BeanPostProsessor
                                if (BeanPostProsessor.class.isAssignableFrom(aClass)){
                                    // 直接实例化
                                    BeanPostProsessor instance = (BeanPostProsessor) aClass.newInstance();
                                    beanPostProsessorArrayList.add(instance);
                                }

                                // 拿到注解
                                Component component = aClass.getAnnotation(Component.class);
                                // 拿到注解的名字
                                String beanName = component.value();
                                // 实现默认首字母小写
                                if (beanName.equals("")){
                                    beanName = Introspector.decapitalize(aClass.getSimpleName());
                                }
                                System.out.println(beanName);
                                // 先创建bean信息
                                BeanDefinition beanDefinition = new BeanDefinition();
                                // 设置类型
                                beanDefinition.setClazz(aClass);
                                if (aClass.isAnnotationPresent(Scope.class)){
                                    // 判断是否有注解 有的话就拿到注解的名字并且设置到BeanDefinition中
                                    Scope annotation = aClass.getAnnotation(Scope.class);
                                    // 查看scope上面是否有值 没有就还是单例
                                    if (annotation.value().equals("")){
                                        // 没有的话就默认设置单例
                                        beanDefinition.setType("singleton");
                                    }else {
                                        beanDefinition.setType(annotation.value());
                                    }
                                }else {
                                    // 没有的话就默认设置单例
                                    beanDefinition.setType("singleton");
                                }
                                // 放入到map中
                                concurrentHashMap.put(beanName,beanDefinition);
                            }
                        } catch (ClassNotFoundException e) {
                            e.printStackTrace();
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        } catch (InstantiationException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }

        // 循环拿到bean
        for (String beanName : concurrentHashMap.keySet()) {
            // 拿到bean定义信息
            BeanDefinition beanDefinition = concurrentHashMap.get(beanName);
            // 如果是单例就创建然后放入单例池
            if (beanDefinition.getType().equals("singleton")){
                Object bean = createBean(beanName, beanDefinition);
                singletonObjects.put(beanName,bean);
            }else {
                // 不是单列 直接创建
                createBean(beanName,beanDefinition);
            }
        }
    }


    // 创建
    public Object createBean(String beanName,BeanDefinition beanDefinition){
        Class clazz = beanDefinition.getClazz();
        try {
            Object instance = clazz.getConstructor().newInstance();

            // DI注入 在创建实例的时候拿到所有的属性 判断属性上面有没有需要DI注入的 有的话就给他先实例化
            for (Field declaredField : clazz.getDeclaredFields()) {
                if (declaredField.isAnnotationPresent(Autowired.class)){
                    declaredField.setAccessible(true);
                    declaredField.set(instance,getBean(declaredField.getName()));
                }
            }
            // 回调
            if (instance instanceof BeanNameAware){
                ((BeanNameAware)instance).setBeanName(beanName);
            }

            // 前置
            for (BeanPostProsessor beanPostProsessor : beanPostProsessorArrayList) {
                instance = beanPostProsessor.Before(beanName,instance);
            }

            // 初始化
            if (instance instanceof InitializingBean){
                ((InitializingBean)instance).afterPropertiesSet();
            }

            // 后置
            for (BeanPostProsessor beanPostProsessor : beanPostProsessorArrayList) {
                instance = beanPostProsessor.After(beanName,instance);
            }


            return instance;
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        return null;
    }



    // 获取
    public Object getBean(String beanName){
        // 根据名字拿到定义信息
        BeanDefinition beanDefinition = concurrentHashMap.get(beanName);
        if (beanDefinition == null){
            return new RuntimeException();
        }else {
            // 拿到Scope
            String type = beanDefinition.getType();
            // 如果是单例就创建并且放入单例池
            if (type.equals("singleton")){
                // 从单例池拿到bean
                Object bean = singletonObjects.get(beanName);
                if (bean == null){
                    Object o = createBean(beanName, beanDefinition);
                    singletonObjects.put(beanName,o);
                }
                return bean;
            }else {
                // 多例直接创建
                return createBean(beanName, beanDefinition);
            }
        }
    }
}
package com.project.service;

import com.project.spring.BeanPostProsessor;
import com.project.spring.Component;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

@Component
public class MyBeanPostProsessor implements BeanPostProsessor {
    @Override
    public Object Before(String beanName, Object bean) {
        if (beanName.equals("userService")){
            System.out.println("前置执行");
        }
        return bean;
    }

    @Override
    public Object After(String beanName, Object bean) {
        if (beanName.equals("userService")){
            System.out.println("后置执行");
            Object instance = Proxy.newProxyInstance(MyBeanPostProsessor.class.getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    System.out.println("切面逻辑执行");
                    // 执行的是普通对象方法而不是代理对象
                    return method.invoke(method, args);
                }
            });
            return instance;
        }
        return bean;
    }
}

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-10-22 21:01:38  更:2022-10-22 21:04:57 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 -2025/1/30 13:18:01-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码