Skip to content

tragoedia0722/MySpringSimDemo

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Spring模拟实现

手动模拟Spring,实现了单例、原型Bean的创建,简单依赖注入,根据名称获取Bean实例对象,初始化与后置处理器等基本功能

注解

ComponentScan

组件扫描注解,在配置类上添加,用于扫描指定包名下的组件

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ComponentScan {
    String value() default "";
}

Component

组件注解,在需要被扫描的类上添加,用于指定该Bean的名称

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Component {
    String value() default "";
}

Scope

作用域注解,用于指定该Bean对象是单例或原型

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Scope {
    String value() default "";
}

Autowired

自动注入注解,可添加至字段上

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Autowired {
	String value() default "";
}

接口

InitializingBean

初始化方法接口,实现该接口方法进行初始化

public interface InitializingBean {
    void afterPropertiesSet();
}

BeanPostProcessor

Bean后置处理器,实现初始化前后的操作

public interface BeanPostProcessor {
    default Object postProcessorBeforeInitializing(Object bean, String beanName) {
        return bean;
    }

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

容器类

BeanDefinition

该类为Bean的定义对象,存放Bean的相关信息

public class BeanDefinition {
    private Class<?> type; // Bean类型
    private String scope;  // Bean作用域
    private boolean bLazy; // 是否懒加载
	// getter & setter ...
}

MySpringApplicaitonContext

该类为Spring容器,用于创建和管理Bean对象

public class MySpringApplicationContext {
    // ...
}

创建Bean对象

添加构造方法MySpringApplicationContext,用于读取配置类

private final Class<?> configClass; // 配置类

public MySpringApplicationContext(Class<?> configClass) {
    this.configClass = configClass;
}

添加扫描方法scan,通过扫描配置类上@ComponentScan注解内的值来获取查找需要创建Bean对象的类,并将该Bean信息添加到BeanDefinitionMap中

private final Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>(); // Bean定义Map

public MySpringApplicationContext(Class<?> configClass) {
    // ...
    scan(configClass);
}

public void scan(Class<?> configClass) {
    // 扫描注解获取文件路径
    if (configClass.isAnnotationPresent(ComponentScan.class)) {
        ComponentScan componentScan = configClass.getAnnotation(ComponentScan.class);
        String scanPath = componentScan.value();
        scanPath = scanPath.replace(".", "/");
        ClassLoader classLoader = configClass.getClassLoader();
        URL resource = classLoader.getResource(scanPath);
        if (Objects.nonNull(resource)) {
            File file = new File(resource.getFile());
            if (file.isDirectory()) {
                // 遍历目录下文件
                for (File f : Objects.requireNonNull(file.listFiles())) {
                    String absolutePath = f.getAbsolutePath();
                    absolutePath = absolutePath.substring(absolutePath.indexOf("com"), absolutePath.indexOf(".class")).replace("\\", ".");
                    // 加载类文件获取注解
                    try {
                        Class<?> clazz = classLoader.loadClass(absolutePath);
                        if (clazz.isAnnotationPresent(Component.class)) {
                            // Bean信息添加到BeanDefinitionMap中
                            BeanDefinition beanDefinition = new BeanDefinition();
                            Component component = clazz.getAnnotation(Component.class);
                            String beanName = component.value();
                            if ("".equals(beanName)){
                                beanName = Introspector.decapitalize(clazz.getSimpleName());
                            }
                            beanDefinition.setType(clazz);
                            if (clazz.isAnnotationPresent(Scope.class)) {
                                Scope scope = clazz.getAnnotation(Scope.class);
                                String value = scope.value();
                                beanDefinition.setScope(value);
                            } else {
                                beanDefinition.setScope("singleton");
                            }
                            beanDefinitionMap.put(beanName, beanDefinition);
                        }
                    } catch (ClassNotFoundException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        }
    }
}

添加创建方法createBean,该方法通过Bean的定义类BeanDefinition来创建相应的Bean对象

修改构造方法MySpringApplicationContext,在构造时直接创建单例Bean对象,并将该对象存入单例池singletonObjects中,用于后续单例对象的调用

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

public Object createBean(String beanName, BeanDefinition beanDefinition) {
    Class<?> clazz = beanDefinition.getType();
    Object instance;
    try {
        instance = clazz.getConstructor().newInstance();
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
    return bean;
}

public MySpringApplicationContext(Class<?> configClass) {
    // ...
    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);
        }
    }
}

添加getBean方法获取Bean对象,若为单例对象则从线程池中直接获取,若为原型对象则通过返回一个新的Bean对象,此时可以对单例与原型Bean进行基本的创建使用功能

public Object getBean(String beanName) {
    if (!beanDefinitionMap.containsKey(beanName)) {
        throw new RuntimeException("Bean不存在");
    }
    BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
    String scope = beanDefinition.getScope();
    if (scope.equals("singleton")) {
        Object singletonBean = singletonObjects.get(beanName);
        // 解决依赖与单例Bean创建顺序不一致导致的从单例池返回结果为null的问题
        if (singletonBean == null) {
            singletonBean = createBean(beanName, beanDefinition);
            singletonObjects.put(beanName, singletonBean);
        }
        return singletonBean;
    }
    if (scope.equals("prototype")) {
        return createBean(beanName, beanDefinition);
    }
    return null;
}

依赖注入

修改createBean方法,在创建Bean对象后通过反射进行依赖注入为属性赋值

public Object createBean(String beanName, BeanDefinition beanDefinition) {
    Class<?> clazz = beanDefinition.getType();
    Object instance;
    try {
        instance = clazz.getConstructor().newInstance();
        // 遍历属性,查看是否有依赖注入注解 Autowired
        for (Field field : clazz.getDeclaredFields()) {
            if (field.isAnnotationPresent(Autowired.class)) {
                field.setAccessible(true);
                field.set(instance, getBean(field.getName()));
            }
        }
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
    return bean;
}

初始化

修改createBean方法,实现初始化功能,实现InitializingBean接口并调用接口中的afterPropertiesSet方法

public Object createBean(String beanName, BeanDefinition beanDefinition) {
    Class<?> clazz = beanDefinition.getType();
    Object instance;
    try {
        instance = clazz.getConstructor().newInstance();
        // 遍历属性,查看是否有依赖注入注解 Autowired
        for (Field field : clazz.getDeclaredFields()) {
            if (field.isAnnotationPresent(Autowired.class)) {
                field.setAccessible(true);
                field.set(instance, getBean(field.getName()));
            }
        }
        // 初始化方法
        if (instance instanceof InitializingBean) {
            ((InitializingBean) instance).afterPropertiesSet();
        }
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
    return instance;
}

BeanPostProcessor

修改scan方法,在类获取到@Component注解后查询该类是否实现了BeanPostProcessor接口,若实现该接口则将该类添加到beanPostProcessors 缓存中,否则作为普通Bean添加信息到BeanDefinitionMap

private final List<BeanPostProcessor> beanPostProcessors = new ArrayList<>(); // 后置对象缓存列表

public void scan(Class<?> configClass) {
    // ...
    try {
        Class<?> clazz = classLoader.loadClass(absolutePath);
        if (clazz.isAnnotationPresent(Component.class)) {
            // BeanPostProcessor实现
            if (BeanPostProcessor.class.isAssignableFrom(clazz)) {
                BeanPostProcessor beanPostProcessor = (BeanPostProcessor) clazz.getConstructor().newInstance();
                beanPostProcessors.add(beanPostProcessor);
            }
            // Bean信息添加到BeanDefinitionMap中
            else {
                BeanDefinition beanDefinition = new BeanDefinition();
                Component component = clazz.getAnnotation(Component.class);
                String beanName = component.value();
                if ("".equals(beanName)) {
                    beanName = Introspector.decapitalize(clazz.getSimpleName());
                }
                beanDefinition.setType(clazz);
                if (clazz.isAnnotationPresent(Scope.class)) {
                    Scope scope = clazz.getAnnotation(Scope.class);
                    String value = scope.value();
                    beanDefinition.setScope(value);
                } else {
                    beanDefinition.setScope("singleton");
                }
                beanDefinitionMap.put(beanName, beanDefinition);
            }
        }
    // ...
} 

修改createBean方法,在创建Bean初始��方法前后调用BeanPostProcessor的初始化前后方法postProcessorBeforeInitializingpostProcessorAfterInitializing,通过该BeanPostProcessor可完成包括AOP、Aware在内的多种扩展方法

public Object createBean(String beanName, BeanDefinition beanDefinition) {
	// ...
    // 初始化前方法
    for (BeanPostProcessor beanPostProcessor : beanPostProcessors) {
        instance = beanPostProcessor.postProcessorBeforeInitializing(instance, beanName);
    }
    // 初始化方法
    if (instance instanceof InitializingBean) {
        ((InitializingBean) instance).afterPropertiesSet();
    }
    // 初始化后方法
    for (BeanPostProcessor beanPostProcessor : beanPostProcessors) {
        instance = beanPostProcessor.postProcessorAfterInitializing(instance, beanName);
    }
    // ...
}

测试类

Appconfig

容器配置类,用于指定扫描的包

@ComponentScan(value = "com.example.service")
public class AppConfig {
}

Service

TestService

组件方法类,在类上添加Component注解指定该类为一个Bean容器

@Component
@Scope(value = "prototype")
public class TestService implements InitializingBean {
    @Autowired
    private TestWiredService testWiredService;

    public void test() {
        System.out.println("testService test!");
    }

    public void wiredTest() {
        testWiredService.wiredTest();
    }

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

TestWiredService

测试注入类

@Component
public class TestWiredService {
    public void wiredTest() {
        System.out.println("testWiredService test!");
    }
}

TestBeanPostProcessor

测试后置处理器

@Component
public class TestBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessorBeforeInitializing(Object bean, String beanName) {
        System.out.println(beanName + " 初始化前方法");
        return BeanPostProcessor.super.postProcessorBeforeInitializing(bean, beanName);
    }

    @Override
    public Object postProcessorAfterInitializing(Object bean, String beanName) {
        System.out.println(beanName + " 初始化后方法");
        return BeanPostProcessor.super.postProcessorAfterInitializing(bean, beanName);
    }
}

Main

主测试类,用于调用Spring容器,获取容器中的Bean对象并调用方法

public class Test {
    public static void main(String[] args) {
        MySpringApplicationContext applicationContext = new MySpringApplicationContext(AppConfig.class);
        TestService testService = (TestService) applicationContext.getBean("testService");
        testService.test();
        testService.wiredTest();
    }
}

Console

测试结果打印

testWiredService 初始化前方法
testWiredService 初始化后方法
testService 初始化前方法
testService 初始化
testService 初始化后方法
testService test!
testWiredService test!

About

Spring原理手动模拟实现

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages