手写Spring源码,了解bean的重要生命周期

Spring系列文章目录

第一章 手写Spring



前言

本篇文章是围绕AnnotationConfigApplicationContext加载的spring当中bean的生命周期过程,所有注解,类都可以在Spring当中找到对应的类。


一、代码主体结构

示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。

二、spring代码

  • 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.lotus</groupId>
  <artifactId>handle-write-spring</artifactId>
  <version>1.0-SNAPSHOT</version>
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
          <source>8</source>
          <target>8</target>
        </configuration>
      </plugin>
    </plugins>
  </build>

  <name>Maven</name>
  <inceptionYear>2001</inceptionYear>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

</project>

  • Autowired
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 {}
  • Component
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
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 "";
}
  • Scope
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 "";
}
  • BeanNameAware
public interface BeanNameAware {void setBeanName(String name);
}
  • BeanPostProcessor
public interface BeanPostProcessor {default Object postProcessBeforeInitialization(Object bean, String beanName) {
        return bean;
    }default Object postProcessAfterInitialization(Object bean, String beanName) {
        return bean;
    }
}
  • InitializingBean
public interface InitializingBean {void afterPropertiesSet();
}
  • AppConfig
/**
 * 声明扫描
 **/
@ComponentScan("com.lotus.demo")
public class AppConfig {}
  • BeanDefinition
public class BeanDefinition {private Class<?> type;private String scope;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;
    }
}
  • AnnotationConfigApplicationContext
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.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;/**
 * 模拟spring 注解启动上下文
 **/
public class AnnotationConfigApplicationContext {private Class<?> appConfig;private ConcurrentHashMap<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>();
    private ConcurrentHashMap<String, Object> singletonObjects = new ConcurrentHashMap<>();
    private List<BeanPostProcessor> beanPostProcessorList = new ArrayList<>();public AnnotationConfigApplicationContext(Class<?> appConfig) {
        this.appConfig = appConfig;scanConfig(appConfig);// 将扫描到的BeanDefinition判断属性是否放入到单例
        for (Map.Entry<String, BeanDefinition> definitionEntry : beanDefinitionMap.entrySet()) {
            String beanName = definitionEntry.getKey();
            BeanDefinition definition = definitionEntry.getValue();
            if (definition.getScope().equals("singleton")) {
                singletonObjects.put(beanName, createBean(beanName, definition));
            }
        }
    }/**
     * 扫描配置的包路径
     **/
    private void scanConfig(Class<?> appConfig) {
        if (appConfig.isAnnotationPresent(ComponentScan.class)) {
            ComponentScan componentScan = appConfig.getAnnotation(ComponentScan.class);
            String componentScanVal = componentScan.value();
            System.out.println("spring  获取ComponentScan定义扫描路径: " + componentScanVal);ClassLoader classLoader = AnnotationConfigApplicationContext.class.getClassLoader();
            componentScanVal = componentScanVal.replace(".", "/");
            URL resource = classLoader.getResource(componentScanVal);File file = new File(resource.getFile());
            loadFile(classLoader, file);
        }
    }/**
     * 加载文件
     **/
    private void loadFile(ClassLoader classLoader, File file) {
        if (file.isDirectory()) {
            for (File listFile : file.listFiles()) {
                // 如果为文件夹则递归
                if (listFile.isDirectory()) {
                    loadFile(classLoader, listFile);
                }
                String absolutePath = listFile.getAbsolutePath();
                if (absolutePath.lastIndexOf(".class") == -1) {
                    continue;
                }
                absolutePath = absolutePath.substring(absolutePath.indexOf("com"), absolutePath.indexOf(".class")).replace("\\", ".");try {
                    Class<?> loadClass = classLoader.loadClass(absolutePath);
                    // 查看类上是否有注解 标明这是一个bean
                    if (loadClass.isAnnotationPresent(Component.class)) {
                        // 对于通过实现BeanPostProcessor的bean单独放到一个list当中保存
                        if (BeanPostProcessor.class.isAssignableFrom(loadClass)) {
                            BeanPostProcessor instance = (BeanPostProcessor) loadClass.getConstructor().newInstance();
                            beanPostProcessorList.add(instance);
                        }Component component = loadClass.getAnnotation(Component.class);
                        String beanName = component.value();
                        // 获取bean的名称 如果赋值则取赋值的名称,否则取类名第一个单词小写的名称
                        beanName = beanName == null || "".equals(beanName) ? Introspector.decapitalize(loadClass.getSimpleName()) : beanName;
                        // 构造beanDefinition后续加载bean
                        BeanDefinition beanDefinition = new BeanDefinition();
                        beanDefinition.setType(loadClass);
                        if (loadClass.isAnnotationPresent(Scope.class)) {
                            Scope scope = loadClass.getAnnotation(Scope.class);
                            String scopeVal = scope.value();
                            beanDefinition.setScope(scopeVal);
                        } else {
                            beanDefinition.setScope("singleton");
                        }
                        beanDefinitionMap.put(beanName, beanDefinition);
                    }} catch (ClassNotFoundException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                }
            }
        }
    }/**
     * 从 beanDefinitionMap 获取单例bean 或者 原型bean
     **/
    public Object getBean(String beanName) {
        if (!beanDefinitionMap.containsKey(beanName)) {
            throw new NullPointerException();
        }
        BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
        String scope = beanDefinition.getScope();
        Object singletonBean = null;
        if ("singleton".equals(scope)) {
            singletonBean = singletonObjects.get(beanName);
            singletonObjects.put(beanName, singletonBean);
        } else {
            singletonBean = createBean(beanName, beanDefinition);
        }
        return singletonBean;
    }/**
     * 通过beanDefinition创建bean实例,同时加载bean的生命周期
     **/
    private Object createBean(String beanName, BeanDefinition beanDefinition) {
        Object instance = null;
        Class<?> clazz = beanDefinition.getType();
        try {
            instance = clazz.getConstructor().newInstance();for (Field field : clazz.getDeclaredFields()) {
                if (field.isAnnotationPresent(Autowired.class)) {
                    field.setAccessible(true);
                    field.set(instance, getBean(beanName));
                }
            }if (instance instanceof BeanNameAware) {
                ((BeanNameAware) instance).setBeanName(beanName);
            }for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
                instance = beanPostProcessor.postProcessBeforeInitialization(instance, beanName);
            }if (instance instanceof InitializingBean) {
                ((InitializingBean) instance).afterPropertiesSet();
            }for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
                instance = beanPostProcessor.postProcessAfterInitialization(instance, beanName);
            }} catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        return instance;
    }
}

三、测试代码

  • UserService
public interface UserService {void test();
}
  • OrderService
import com.lotus.spring.BeanNameAware;
import com.lotus.spring.BeanPostProcessor;
import com.lotus.spring.Component;
import com.lotus.spring.InitializingBean;@Component
public class OrderService implements BeanNameAware, BeanPostProcessor, InitializingBean {private String beanName;@Override
    public void setBeanName(String name) {
        System.out.println("spring-->初始化前优先设置bean名称" + name);
        this.beanName = name;
    }@Override
    public void afterPropertiesSet() {
        System.out.println("spring-->初始化bean,此时bean的名称:" + beanName);
    }@Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
        System.out.println("spring-->初始化bean之前,做的事" + beanName);
        return bean;
    }@Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        System.out.println("spring-->初始化bean之后,做的事" + beanName);
        return bean;
    }
}
  • UserServiceImpl
@Component
public class UserServiceImpl implements UserService {public void test() {
        System.out.println("==============");
    }
}

四、测试类

  • DemoTest
import com.lotus.demo.service.impl.UserServiceImpl;
import com.lotus.spring.AnnotationConfigApplicationContext;
import com.lotus.spring.AppConfig;public class DemoTest {public static void main(String[] args) {AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);UserServiceImpl userServiceImpl = (UserServiceImpl) applicationContext.getBean("userServiceImpl");
        userServiceImpl.test();
    }
}
  • 执行结果如图所示
    在这里插入图片描述

源码地址:https://gitee.com/zengzheng-pro/handle-write-spring.git

总结

以上就是简单实现手写Spring的过程,主要包含了扫描包路径,创建单例bean和原型bean,bean生命周期较为重要的几个阶段。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小白努力学java

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

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

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

打赏作者

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

抵扣说明:

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

余额充值