手写模拟Spring源码启动过程

手写Spring底层源码启动过程

结构目录
在这里插入图片描述

jdk动态代理实现需要的接口

package com.szc.shizhichao.service;

public interface ShizhichaoInterface {

    public void test();
}

BeanNameAware 实现需要的接口

package com.szc.spring;

public interface BeanNameAware {

    void setBeanName(String name);
}

初始化bean需要的接口

package com.szc.spring;

public interface InitializingBean {

    void afterPropertiesSet();
}

初始化前和初始化后操作需要的接口

package com.szc.spring;

public interface BeanPostProcessor {

    default Object postProcessBeforeInitialization(Object bean, String beanName) {
        return bean;
    }

    default Object postProcessAfterInitialization(Object bean, String beanName) {
        return bean;
    }


}

自定义BeanPostProcessor

package com.szc.shizhichao.service;

import com.szc.spring.BeanPostProcessor;
import com.szc.spring.Component;

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

@Component
public class ShizhichaoBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) {

        /*自定义注解赋值*/
        for (Field field : bean.getClass().getDeclaredFields()) {
            if (field.isAnnotationPresent(Shizhichao.class)) {
                field.setAccessible(true);
                try {
                    field.set(bean,field.getAnnotation(Shizhichao.class).value());
                } catch (IllegalAccessException e) {
                    throw new RuntimeException(e);
                }
            }
        }

        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {

        /*AOP逻辑,此处利用jdk动态代理实现,原则上Spring底层是cglib*/
        if(beanName.equals("shizhichaoService")){
            Object newProxyInstance = Proxy.newProxyInstance(ShizhichaoBeanPostProcessor.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(bean,args);
                }
            });
            return newProxyInstance;
        }

        return bean;
    }

}

Autowired 注解,实现依赖注入

package com.szc.spring;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Autowired {

    String value() default "";
}

Component 注解

package com.szc.spring;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Component {

    String value() default "";
}

ComponentScan 注解

package com.szc.spring;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ComponentScan {

    String value() default "";
}

自定义注解

package com.szc.shizhichao.service;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Shizhichao {

    String value() default "";
}

Scope 注解

package com.szc.spring;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Scope {

    String value() default "";
}

演示类BeautyLadyService

package com.szc.shizhichao.service;

import com.szc.spring.Component;

@Component
public class BeautyLadyService {
}

演示类ShiZhiChaoService

package com.szc.shizhichao.service;

import com.szc.spring.*;

//@Component("shizhichaoService")
//@Scope("singleton")
@Component
public class ShiZhiChaoService implements ShizhichaoInterface, BeanNameAware {


    @Shizhichao("xxx")
    private String test;

    private String beanName;

    @Autowired
    private BeautyLadyService beautyLadyService;



    public void test(){
//        System.out.println(beautyLadyService);
//        System.out.println(test);
        System.out.println(beanName);
    }

    @Override
    public void setBeanName(String name) {
        this.beanName= name;
    }

//    @Override
//    public void afterPropertiesSet() {
//        System.out.println("初始化");
//    }
}

配置类AppConfig

package com.szc.shizhichao;

import com.szc.spring.ComponentScan;

@ComponentScan("com.szc.shizhichao.service")
public class AppConfig {
}

测试类Test

package com.szc.shizhichao;

import com.szc.shizhichao.service.BeautyLadyService;
import com.szc.shizhichao.service.ShiZhiChaoService;
import com.szc.shizhichao.service.ShizhichaoInterface;
import com.szc.spring.ShiZhiChaoApplicationContext;


public class Test {

    public static void main(String[] args) {

        //扫描----->创建单例bean
        ShiZhiChaoApplicationContext applicationContext = new ShiZhiChaoApplicationContext(AppConfig.class);

//        ShiZhiChaoService shiZhiChaoService = (ShiZhiChaoService) applicationContext.getBean("shizhichaoService");
        ShizhichaoInterface shiZhiChaoService = (ShizhichaoInterface) applicationContext.getBean("shiZhiChaoService");
//        BeautyLadyService beautyLadyService = (BeautyLadyService) applicationContext.getBean("beautyLadyService");

//        System.out.println(shiZhiChaoService);
//        System.out.println(beautyLadyService);


        /*在实现AOP逻辑后 调用此方法会进入代理对象的involve方法*/
        shiZhiChaoService.test();
    }
}

BeanDefinition

package com.szc.spring;

public class BeanDefinition {

    private  Class type;

    private String scope;

    private  boolean isLazy;

    public Class getType() {
        return type;
    }

    public void setType(Class type) {
        this.type = type;
    }

    public String getScope() {
        return scope;
    }

    public void setScope(String scope) {
        this.scope = scope;
    }

    public boolean isLazy() {
        return isLazy;
    }

    public void setLazy(boolean lazy) {
        isLazy = lazy;
    }
}

自定义ApplicationContext

package com.szc.spring;

import java.beans.Introspector;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ShiZhiChaoApplicationContext {

    private Class appConfigClass;

    private Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();
    private Map<String, Object> singletonObjects = new HashMap<>();//单例池

    private List<BeanPostProcessor> beanPostProcessorList = new ArrayList<>();


    public ShiZhiChaoApplicationContext(Class appConfig) {
        this.appConfigClass = appConfig;


        /*扫描*/
        scan(appConfigClass);

        /*创建单例bean*/
        for (Map.Entry<String, BeanDefinition> entry : beanDefinitionMap.entrySet()) {
            String beanName = entry.getKey();
            BeanDefinition beanDefinition = entry.getValue();
            if (beanDefinition.getScope().equals("singleton")) {
                Object bean = createBean(beanName, beanDefinition);
                singletonObjects.put(beanName, bean);
            }

        }

    }

    private Object createBean(String beanName, BeanDefinition beanDefinition) {
        Class clazz = beanDefinition.getType();

        Object instance = null;
        try {
            instance = clazz.getConstructor().newInstance();//利用构造方法(此处是Spring通过byte的逻辑获取的,此处不深入去实现了)

            /*依赖注入大体逻辑*/

            for (Field field : clazz.getDeclaredFields()) {
                if (field.isAnnotationPresent(Autowired.class)) {//判断属性是否有autowired注解

                    field.setAccessible(true);//反射
                    field.set(instance, getBean(field.getName()));//给当前这个类instance的这个属性field赋值(可能会有循环依赖,后续我会单独讲解)

                }
            }

            /*beanNameAware逻辑*/
            if (instance instanceof BeanNameAware) {
                ((BeanNameAware) instance).setBeanName(beanName);
            }


            /*初始化前逻辑*/
            for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
                instance = beanPostProcessor.postProcessBeforeInitialization(instance, beanName);
            }


            /*初始化简单实现*/

            if (instance instanceof InitializingBean) {
                ((InitializingBean) instance).afterPropertiesSet();
            }

            /*初始化后逻辑,其中包含AOP*/
            for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
                instance = beanPostProcessor.postProcessAfterInitialization(instance, beanName);
            }


        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        }

        return instance;


    }


    private void scan(Class appConfigClass) {
        if (appConfigClass.isAnnotationPresent(ComponentScan.class)) { //首先判断配置类是否有扫描注解
            ComponentScan componentScanAnnotation = (ComponentScan) appConfigClass.getAnnotation(ComponentScan.class);
            String path = componentScanAnnotation.value();//获取到需要扫描的包路径
            path = path.replace(".", "/");//获取到的是Java文件路径,但是类加载器加载的是target下的class文件

            //   System.out.println(path);//com/szc/shizhichao/service

            ClassLoader classLoader = ShiZhiChaoApplicationContext.class.getClassLoader();
            URL resource = classLoader.getResource(path);//path传进来,此时的path是一个相对路径,相对于类加载器的路径

            File file = new File(resource.getFile());//拿到了需要扫描的目录
            if (file.isDirectory()) {
                for (File f : file.listFiles()) {
                    String absolutePath = f.getAbsolutePath();
                    //    System.out.println(absolutePath);//D:\BaiduNetdiskDownload\tuling\yuanma\shouxieSpring\zhouyu-spring-vip\target\classes\com\szc\shizhichao\service\ShiZhiChaoService.class

                    absolutePath = absolutePath.substring(absolutePath.indexOf("com"), absolutePath.indexOf(".class"));
                    absolutePath = absolutePath.replace("\\", ".");
                    //     System.out.println(absolutePath);//com.szc.shizhichao.service.ShiZhiChaoService

                    try {
                        Class<?> clazz = classLoader.loadClass(absolutePath);
                        if (clazz.isAnnotationPresent(Component.class)) {//判断扫描的类上是否有Component注解

                            if (BeanPostProcessor.class.isAssignableFrom(clazz)) {//判断这个类是否实现了BeanPostProcessor
                                BeanPostProcessor instance = (BeanPostProcessor) clazz.getConstructor().newInstance();

                                beanPostProcessorList.add(instance);

                            } else {
                                Component componentAnnotation = clazz.getAnnotation(Component.class);
                                String beanName = componentAnnotation.value();
                                if ("".equals(beanName)) {
                                    beanName = Introspector.decapitalize(clazz.getSimpleName());//如果属性没设置名字,jdk帮我们去生成的一个名字
                                }

                                BeanDefinition beanDefinition = new BeanDefinition();
                                beanDefinition.setType(clazz);

                                if (clazz.isAnnotationPresent(Scope.class)) {//判断是否是原型bean
                                    Scope scopeAnnotation = clazz.getAnnotation(Scope.class);
                                    String value = scopeAnnotation.value();
                                    beanDefinition.setScope(value);
                                } else {
                                    //单例
                                    beanDefinition.setScope("singleton");
                                }
                                beanDefinitionMap.put(beanName, beanDefinition);
                            }


                        }
                    } catch (ClassNotFoundException | NoSuchMethodException | InstantiationException |
                             IllegalAccessException | InvocationTargetException e) {
                        throw new RuntimeException(e);
                    }
                }
            }

        }
    }


    public Object getBean(String beanName) {
        if (!beanDefinitionMap.containsKey(beanName)) {
            throw new NullPointerException();
        }
        BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
        if (beanDefinition.getScope().equals("singleton")) {
            Object singletonBean = singletonObjects.get(beanName);
            if (singletonBean == null) {//为了避免依赖注入可能会存在的问题
                singletonBean = createBean(beanName, beanDefinition);
                singletonObjects.put(beanName, singletonBean);
            }
            return singletonBean;
        } else {
            //原型(每次使用都需要去创建)
            Object bean = createBean(beanName, beanDefinition);
            return bean;
        }
    }
}

哪里不明白的评论回复~~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值