hexon
发布于 2025-11-25 / 5 阅读
0

2、一节课手写模拟Spring核心原理

在上篇文章中,我们已经将SpringFramework6的源码拉取下来并编译成功了。接下来,我并不打算直接开始源码的阅读与分析。

而是会结合Spring的一些基本用法,先手写模拟下Spring的核心原理,为后面阅读源码梳理一个脉络。

我们将模拟手写以下内容:

  • 手写模拟Spring容器启动过程底层实现

  • 手写模拟Spring解析配置类底层实现

  • 手写模拟Spring扫描Bean过程底层实现

  • 手写模拟Bean生命周期创建过程底层实现

  • 手写模拟Bean生命周期依赖注入过程底层实现

  • 手写模拟Bean生命周期Aware回调过程底层实现

  • 手写模拟Bean生命周期初始化过程底层实现

  • 手写模拟BeanDefinition生成过程底层实现

  • 手写模拟@Component、@ComponentScan

  • 手写模拟@Autowired、@PostConstruct

  • 手写模拟BeanPostProcessor后置处理底层实现

  • 手写模拟Spring AOP过程底层实现

  • 手写模拟Pointcut、Advisor、Advice底层实现

Spring的基本用法

首先,我们来看下我们学习Spring时候入门的案例:

public class Main {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
        UserService userService = (UserService) applicationContext.getBean("userService");
        userService.test();
    }
}
@Component
public class UserService {
​
    public void test() {
        System.out.println("UserService#test....");
    }
​
}
@ComponentScan("com.hexon")
public class MyConfig {
}

大概的过程就是:

1、创建一个Spring容器对象

2、提供一个配置类,指定要扫描的包路径

3、使用@Component配置Bean

4、容器运行后,我们就可以根据beanName获取Bean了

这是Spring Ioc 容器的最基本用法了,下面我们手写模拟容器的启动过程。

工程结构

我们创建一个Maven的聚合工程,再创建两个模块,其中springframework代码我们要手写的spring,business则代表一个业务模块。接着我们在busniess模块引入springframework的依赖。

<dependencies>
    <dependency>
        <groupId>com.hexon</groupId>
        <artifactId>springframework</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
</dependencies>

解析配置类

AnnotationConfigApplicationContext此类就代表spring的ioc容器,它有一个构造器接收一个配置类的class对象,并且至少有一个getBean方法。所以我们可以首先定义好这个类:

public class AnnotationConfigApplicationContext {

    public AnnotationConfigApplicationContext(Class<?> configClass) {

    }

    public Object getBean(String userService) {
        return null;
    }
}

接下来我们思考下这个构造方法内会做什么事情?当然会进行一个包扫描,而且是基于配置类上面的@ComponentScan注解,所以我们再创建一个@ComponentScan注解。

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

接下来就可以解析传入配置类的ComponentScan注解的value属性,拿到要扫描的包路径。但是要注意的是扫描的是classpath,并不是源码代码的路径!所以要记得替换下路径分隔符。

package com.hexon;

import java.io.File;

/**
 * AnnotationConfigApplicationContext
 *
 * @author hex
 * @date 2025/9/10
 **/
public class AnnotationConfigApplicationContext {

    public AnnotationConfigApplicationContext(Class<?> configClass) {
        // 解析配置类
        if (configClass.isAnnotationPresent(ComponentScan.class)) {
            ComponentScan componentScanAnnotation = configClass.getAnnotation(ComponentScan.class);
            String path = componentScanAnnotation.value();  // com.hexon.service
            path = path.replace('.', '/'); // com/hexon/service  这里不要用文件分隔符,因为后面的URL默认就用 / ,否则会转义报错
            System.out.println(path);

        }
    }

    public Object getBean(String beanName) {
        return null;
    }
}

接下来就可以扫描类了,这里要注意的是spring内部使用的是ASM技术。因为是模拟,我将使用反射技术,一股脑的加载classpath下的所有类,下面来看代码:

package com.hexon;

import java.io.File;
import java.net.URL;

/**
 * AnnotationConfigApplicationContext
 *
 * @author hex
 * @date 2025/9/10
 **/
public class AnnotationConfigApplicationContext {

    public AnnotationConfigApplicationContext(Class<?> configClass) {
        // 解析配置类
        if (configClass.isAnnotationPresent(ComponentScan.class)) {
            ComponentScan componentScanAnnotation = configClass.getAnnotation(ComponentScan.class);
            String path = componentScanAnnotation.value();  // com.hexon.service
            path = path.replace('.', '/'); // com\hexon\service 这里不要用文件分隔符,因为后面的URL默认就用 / ,否则会转义报错
            System.out.println(path);

            // 扫描 反射
            ClassLoader classLoader = getClass().getClassLoader();
            URL resource = classLoader.getResource(path);
            File file = new File(resource.getFile());

            // 这里简化操作路径直接指定到最后一层包,所以就没有递归处理了
            for (File listFile : file.listFiles()) {
                String classPath = listFile.getPath();
                // D:\2025\tuling\03_Spring\zhouyu01\code\mini-spring\business\target\classes\com\hexon\service\UserService.class
                // System.out.println(classPath);
                classPath = classPath.substring(classPath.indexOf("com"), classPath.indexOf(".class"));
                // System.out.println(classPath); // com\hexon\service\UserService
                classPath = classPath.replace('\\', '.');
                System.out.println(classPath);  // com.hexon.service.UserService

                // 加载
                try {
                    Class<?> clazz = classLoader.loadClass(classPath);
                    System.out.println(clazz);

                } catch (ClassNotFoundException e) {
                    throw new RuntimeException(e);
                }
            }

        }
    }

    public Object getBean(String beanName) {
        return null;
    }
}

到这一步,相当于已经可以根据配置类上面配置的包路径,加载此包路径下面的所有类了。

接下来自然就是要考虑是否是bean的问题了。并不是所有类的对象spring都会给你管理,你必须先告诉spring我是一个bean的类,此类的对象才会被纳入到spring ioc容器管理。这里我们暂且只考虑添加了@Component注解的类。因此定义一个@Component注解:

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

为什么Spring要用ASM技术解析类?

ASM技术可以按需加载类,它是直接读取class文件,解析出类的信息,通过它可以避免将不是bean的类加载到JVM中,从而减少内存开销。

扫描Bean过程底层实现

标注了@Component注解的类,在Spring容器启动时会被实例化并注册为Bean定义,在需要时Spring会创建该类的实例作为Bean对象纳入容器管理。

所以,并不是扫描到的所有类我们都要去创建Bean,我们只要包含@Component注解的类。所以势必会对我们加载的每个类进行解析,获取类上的注释等信息,手段很就是通过Class对象反射的方式获取。请注意,这里有一个很重要的概念要引入,那就是BeanDefinition。

主要目的是将 "客户端程序员" 对每个类的配置封装成一个BeanDefinition对象,便于后面直接获取特定类的信息,避免要使用时再次解析。BeanDefinition在Spring源码中是一个接口,这里我们将它定义成一个类:

public class BeanDefinition {

    private Class<?> beanClass;
    private String scope;
    private Boolean isLazy;

    public Class<?> getBeanClass() {
        return beanClass;
    }

    public void setBeanClass(Class<?> beanClass) {
        this.beanClass = beanClass;
    }

    public String getScope() {
        return scope;
    }

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

    public Boolean getLazy() {
        return isLazy;
    }

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

scope是作用域,这个应该很熟悉,常见的值就是singleton(单例)、prototype(原型),单例bean会在spring容器启动过程中创建,而原型bean会在getBean的时候创建。另外,可以使用lazy来控制是否需要在容器启动时就创建bean。这里很自然的又衍生出两个注释,一个是@Scope,一个是@Lazy,定义如下:

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

    boolean value() default true;

}

下面我们来实现BeanDefinition的收集。

package com.hexon;

import java.beans.Introspector;
import java.io.File;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

/**
 * AnnotationConfigApplicationContext
 *
 * @author hex
 * @date 2025/9/10
 **/
public class AnnotationConfigApplicationContext {

    Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();

    public AnnotationConfigApplicationContext(Class<?> configClass) {
        // 解析配置类
        if (configClass.isAnnotationPresent(ComponentScan.class)) {
            ComponentScan componentScanAnnotation = configClass.getAnnotation(ComponentScan.class);
            String path = componentScanAnnotation.value();  // com.hexon.service
            path = path.replace('.', '/'); // com\hexon\service 这里不要用文件分隔符,因为后面的URL默认就用 / ,否则会转义报错
            System.out.println(path);

            // 扫描 反射
            ClassLoader classLoader = getClass().getClassLoader();
            URL resource = classLoader.getResource(path);
            File file = new File(resource.getFile());

            // 这里简化操作路径直接指定到最后一层包,所以就没有递归处理了
            for (File listFile : file.listFiles()) {
                String classPath = listFile.getPath();
                // D:\2025\tuling\03_Spring\zhouyu01\code\mini-spring\business\target\classes\com\hexon\service\UserService.class
                // System.out.println(classPath);
                classPath = classPath.substring(classPath.indexOf("com"), classPath.indexOf(".class"));
                // System.out.println(classPath); // com\hexon\service\UserService
                classPath = classPath.replace('\\', '.');
                // System.out.println(classPath);  // com.hexon.service.UserService

                // 加载
                try {
                    Class<?> clazz = classLoader.loadClass(classPath);
                    // System.out.println(clazz);

                    if (clazz.isAnnotationPresent(Component.class)) {
                        // 代表是一个Bean

                        Component component = clazz.getAnnotation(Component.class);
                        String beanName = component.value();

                        if("".equals(beanName)) {
                            beanName = Introspector.decapitalize(clazz.getSimpleName());
                        }

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

                        if (clazz.isAnnotationPresent(Scope.class)) {
                            String scope = clazz.getAnnotation(Scope.class).value();
                            beanDefinition.setScope(scope);
                        } else {
                            beanDefinition.setScope("singleton");
                        }

                        if (clazz.isAnnotationPresent(Lazy.class)) {
                            boolean lazy = clazz.getAnnotation(Lazy.class).value();
                            beanDefinition.setLazy(lazy);
                        } else {
                            beanDefinition.setLazy(false);
                        }

                        beanDefinitionMap.put(beanName, beanDefinition);

                    }

                } catch (ClassNotFoundException e) {
                    throw new RuntimeException(e);
                }
            }

            // 循环遍历,创建Bean
            for (Map.Entry<String, BeanDefinition> stringBeanDefinitionEntry : beanDefinitionMap.entrySet()) {
                System.out.println(stringBeanDefinitionEntry);
            }

        }
    }

    public Object getBean(String beanName) {
        return null;
    }
}

在实现后续功能之前,我们先来将代码进行一个重构,将刚刚的逻辑抽取成一个扫描的方法:

package com.hexon;

import java.beans.Introspector;
import java.io.File;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

/**
 * AnnotationConfigApplicationContext
 *
 * @author hex
 * @date 2025/9/10
 **/
public class AnnotationConfigApplicationContext {

    Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();

    public AnnotationConfigApplicationContext(Class<?> configClass) {
        
        scan(configClass);
        
        
    }

    private void scan(Class<?> configClass) {
        // 解析配置类
        if (configClass.isAnnotationPresent(ComponentScan.class)) {
            ComponentScan componentScanAnnotation = configClass.getAnnotation(ComponentScan.class);
            String path = componentScanAnnotation.value();  // com.hexon.service
            path = path.replace('.', '/'); // com\hexon\service 这里不要用文件分隔符,因为后面的URL默认就用 / ,否则会转义报错
            System.out.println(path);

            // 扫描 反射
            ClassLoader classLoader = getClass().getClassLoader();
            URL resource = classLoader.getResource(path);
            File file = new File(resource.getFile());

            // 这里简化操作路径直接指定到最后一层包,所以就没有递归处理了
            for (File listFile : file.listFiles()) {
                String classPath = listFile.getPath();
                // D:\2025\tuling\03_Spring\zhouyu01\code\mini-spring\business\target\classes\com\hexon\service\UserService.class
                // System.out.println(classPath);
                classPath = classPath.substring(classPath.indexOf("com"), classPath.indexOf(".class"));
                // System.out.println(classPath); // com\hexon\service\UserService
                classPath = classPath.replace('\\', '.');
                // System.out.println(classPath);  // com.hexon.service.UserService

                // 加载
                try {
                    Class<?> clazz = classLoader.loadClass(classPath);
                    // System.out.println(clazz);

                    if (clazz.isAnnotationPresent(Component.class)) {
                        // 代表是一个Bean

                        Component component = clazz.getAnnotation(Component.class);
                        String beanName = component.value();

                        if ("".equals(beanName)) {
                            beanName = Introspector.decapitalize(clazz.getSimpleName());
                        }

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

                        if (clazz.isAnnotationPresent(Scope.class)) {
                            String scope = clazz.getAnnotation(Scope.class).value();
                            beanDefinition.setScope(scope);
                        } else {
                            beanDefinition.setScope("singleton");
                        }

                        if (clazz.isAnnotationPresent(Lazy.class)) {
                            boolean lazy = clazz.getAnnotation(Lazy.class).value();
                            beanDefinition.setLazy(lazy);
                        } else {
                            beanDefinition.setLazy(false);
                        }

                        beanDefinitionMap.put(beanName, beanDefinition);

                    }

                } catch (ClassNotFoundException e) {
                    throw new RuntimeException(e);
                }
            }

        }
    }

    public Object getBean(String beanName) {
        return null;
    }
}

现在我们已经将所有的Bean的定义信息收集到了beanDefinitionMap中,接下来就可以遍历创建bean了,并且创建后要放入一个容器中,供后续getBean方法获取。

package com.hexon;

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

/**
 * AnnotationConfigApplicationContext
 *
 * @author hex
 * @date 2025/9/10
 **/
public class AnnotationConfigApplicationContext {

    Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();
    Map<String, Object> singletonObjects = new HashMap<>();

    public AnnotationConfigApplicationContext(Class<?> configClass) {

        scan(configClass);

        // 循环创建bean
        for (Map.Entry<String, BeanDefinition> beanDefinitionEntry : beanDefinitionMap.entrySet()) {
            String beanName = beanDefinitionEntry.getKey();
            BeanDefinition beanDefinition = beanDefinitionEntry.getValue();

            if ("singleton".equals(beanDefinition.getScope()) && !beanDefinition.getLazy()) {
                Object singletonBean = createBean(beanName, beanDefinition);
                singletonObjects.put(beanName, singletonBean);
            }
        }

    }

    private Object createBean(String beanName, BeanDefinition beanDefinition) {

        Class<?> beanClass = beanDefinition.getBeanClass();

        try {
            // 实例化Bean 普通java对象
            Object instance = beanClass.getConstructor().newInstance();
            return instance;
        } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
            throw new RuntimeException(e);
        }

    }

    private void scan(Class<?> configClass) {
        // 解析配置类
        if (configClass.isAnnotationPresent(ComponentScan.class)) {
            ComponentScan componentScanAnnotation = configClass.getAnnotation(ComponentScan.class);
            String path = componentScanAnnotation.value();  // com.hexon.service
            path = path.replace('.', '/'); // com\hexon\service 这里不要用文件分隔符,因为后面的URL默认就用 / ,否则会转义报错
            System.out.println(path);

            // 扫描 反射
            ClassLoader classLoader = getClass().getClassLoader();
            URL resource = classLoader.getResource(path);
            File file = new File(resource.getFile());

            // 这里简化操作路径直接指定到最后一层包,所以就没有递归处理了
            for (File listFile : file.listFiles()) {
                String classPath = listFile.getPath();
                // D:\2025\tuling\03_Spring\zhouyu01\code\mini-spring\business\target\classes\com\hexon\service\UserService.class
                // System.out.println(classPath);
                classPath = classPath.substring(classPath.indexOf("com"), classPath.indexOf(".class"));
                // System.out.println(classPath); // com\hexon\service\UserService
                classPath = classPath.replace('\\', '.');
                // System.out.println(classPath);  // com.hexon.service.UserService

                // 加载
                try {
                    Class<?> clazz = classLoader.loadClass(classPath);
                    // System.out.println(clazz);

                    if (clazz.isAnnotationPresent(Component.class)) {
                        // 代表是一个Bean

                        Component component = clazz.getAnnotation(Component.class);
                        String beanName = component.value();

                        if ("".equals(beanName)) {
                            beanName = Introspector.decapitalize(clazz.getSimpleName());
                        }

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

                        if (clazz.isAnnotationPresent(Scope.class)) {
                            String scope = clazz.getAnnotation(Scope.class).value();
                            beanDefinition.setScope(scope);
                        } else {
                            beanDefinition.setScope("singleton");
                        }

                        if (clazz.isAnnotationPresent(Lazy.class)) {
                            boolean lazy = clazz.getAnnotation(Lazy.class).value();
                            beanDefinition.setLazy(lazy);
                        } else {
                            beanDefinition.setLazy(false);
                        }

                        beanDefinitionMap.put(beanName, beanDefinition);

                    }

                } catch (ClassNotFoundException e) {
                    throw new RuntimeException(e);
                }
            }

        }
    }

    public Object getBean(String beanName) {
        return null;
    }
}

接下来就可以完成getBean方法,然后在客户端测试了。

package com.hexon;

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

/**
 * AnnotationConfigApplicationContext
 *
 * @author hex
 * @date 2025/9/10
 **/
public class AnnotationConfigApplicationContext {

    Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();
    Map<String, Object> singletonObjects = new HashMap<>();

    public AnnotationConfigApplicationContext(Class<?> configClass) {

        scan(configClass);

        // 循环创建bean
        for (Map.Entry<String, BeanDefinition> beanDefinitionEntry : beanDefinitionMap.entrySet()) {
            String beanName = beanDefinitionEntry.getKey();
            BeanDefinition beanDefinition = beanDefinitionEntry.getValue();

            if ("singleton".equals(beanDefinition.getScope()) && !beanDefinition.getLazy()) {
                Object singletonBean = createBean(beanName, beanDefinition);
                singletonObjects.put(beanName, singletonBean);
            }
        }

    }

    private Object createBean(String beanName, BeanDefinition beanDefinition) {

        Class<?> beanClass = beanDefinition.getBeanClass();

        try {
            // 实例化Bean 普通java对象
            Object instance = beanClass.getConstructor().newInstance();
            return instance;
        } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
            throw new RuntimeException(e);
        }

    }

    private void scan(Class<?> configClass) {
        // 解析配置类
        if (configClass.isAnnotationPresent(ComponentScan.class)) {
            ComponentScan componentScanAnnotation = configClass.getAnnotation(ComponentScan.class);
            String path = componentScanAnnotation.value();  // com.hexon.service
            path = path.replace('.', '/'); // com\hexon\service 这里不要用文件分隔符,因为后面的URL默认就用 / ,否则会转义报错
            System.out.println(path);

            // 扫描 反射
            ClassLoader classLoader = getClass().getClassLoader();
            URL resource = classLoader.getResource(path);
            File file = new File(resource.getFile());

            // 这里简化操作路径直接指定到最后一层包,所以就没有递归处理了
            for (File listFile : file.listFiles()) {
                String classPath = listFile.getPath();
                // D:\2025\tuling\03_Spring\zhouyu01\code\mini-spring\business\target\classes\com\hexon\service\UserService.class
                // System.out.println(classPath);
                classPath = classPath.substring(classPath.indexOf("com"), classPath.indexOf(".class"));
                // System.out.println(classPath); // com\hexon\service\UserService
                classPath = classPath.replace('\\', '.');
                // System.out.println(classPath);  // com.hexon.service.UserService

                // 加载
                try {
                    Class<?> clazz = classLoader.loadClass(classPath);
                    // System.out.println(clazz);

                    if (clazz.isAnnotationPresent(Component.class)) {
                        // 代表是一个Bean

                        Component component = clazz.getAnnotation(Component.class);
                        String beanName = component.value();

                        if ("".equals(beanName)) {
                            beanName = Introspector.decapitalize(clazz.getSimpleName());
                        }

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

                        if (clazz.isAnnotationPresent(Scope.class)) {
                            String scope = clazz.getAnnotation(Scope.class).value();
                            beanDefinition.setScope(scope);
                        } else {
                            beanDefinition.setScope("singleton");
                        }

                        if (clazz.isAnnotationPresent(Lazy.class)) {
                            boolean lazy = clazz.getAnnotation(Lazy.class).value();
                            beanDefinition.setLazy(lazy);
                        } else {
                            beanDefinition.setLazy(false);
                        }

                        beanDefinitionMap.put(beanName, beanDefinition);

                    }

                } catch (ClassNotFoundException e) {
                    throw new RuntimeException(e);
                }
            }

        }
    }

    public Object getBean(String beanName) {

        if (!beanDefinitionMap.containsKey(beanName)) {
            throw new RuntimeException("No bean with name [" + beanName + "] found");
        }

        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 {
            // 多例
            return createBean(beanName, beanDefinition);
        }

    }
}
public class Main {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
        UserService userService = (UserService) applicationContext.getBean("userService");
        System.out.println(userService);
        userService.test();
    }
}

其他业务代码省略...

Bean的生命周期概述

所谓生命周期就是一个对象从有到无的过程,具体体现就是上面代码的createBean方法,但是目前只包含一个实例化的操作。而实际上Spring中bean的生命周期是有非常多的步骤的。我们可以大概的推导下会有哪些步骤:

private Object createBean(String beanName, BeanDefinition beanDefinition) {

        Class<?> beanClass = beanDefinition.getBeanClass();

        try {
            // 实例化Bean 普通java对象
            Object instance = beanClass.getConstructor().newInstance();
            
            // 依赖注入
            
            // 初始化
            
            return instance;
        } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
            throw new RuntimeException(e);
        }

    }

接下来,我们先来实现依赖注入的功能。

生命周期-依赖注入

在客户端使用时,可能在UserService中注入OrderService:

@Component
public class UserService {

    @Autowired
    private OrderService orderService;

    public void test() {
        System.out.println("UserService#test.....");
        System.out.println(orderService);
    }

}

此时,我们的spring中要提供@Autowired注解:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Autowired {
    // 省略required的定义
}

依赖注入的具体实现就是在createBean方法中:

private Object createBean(String beanName, BeanDefinition beanDefinition) {

        Class<?> beanClass = beanDefinition.getBeanClass();

        try {
            // 实例化Bean 普通java对象
            Object instance = beanClass.getConstructor().newInstance();

            // 依赖注入
            for (Field field : beanClass.getDeclaredFields()) {
                if (field.isAnnotationPresent(Autowired.class)) {
                    // 这里简化处理默认只按名称注入
                    String name = field.getName();
                    field.setAccessible(true);
                    field.set(instance, getBean(name));
                }
            }

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

    }

写到这里说明下,真正的Spring源码中它可能还要先推断构造方法,其中有很多细节和前置处理,这里我们只是模拟,所以只考虑单一的按字段名注入。

生命周期-初始化

接着我们来实现生命周期的另一个阶段 -- 初始化。比如说我这个bean对象属性的值可能要通过我们业务上自己去赋值,spring就提供了InitializingBean接口。我们首先来模拟实现这个接口的处理。InitializingBean接口定义如下:

public interface InitializingBean {
    
    void afterPropertiesSet();
    
}

客户端程序员就可以这么使用:

package com.hexon.service;

import com.hexon.Autowired;
import com.hexon.Component;
import com.hexon.InitializingBean;

/**
 * UserService
 *
 * @author hex
 * @date 2025/9/10
 **/
@Component
public class UserService implements InitializingBean {

    @Autowired
    private OrderService orderService;

    private String name;
    
    public void test() {
        System.out.println("UserService#test.....");
        System.out.println(orderService);
    }

    @Override
    public void afterPropertiesSet() {
        // ... 查询数据库
        name = "hexon";
    }
}

接下来我们依然在createBean方法中实现:

private Object createBean(String beanName, BeanDefinition beanDefinition) {

        Class<?> beanClass = beanDefinition.getBeanClass();

        try {
            // 实例化Bean 普通java对象
            Object instance = beanClass.getConstructor().newInstance();

            // 依赖注入
            for (Field field : beanClass.getDeclaredFields()) {
                if (field.isAnnotationPresent(Autowired.class)) {
                    // 这里简化处理默认只按名称注入
                    String name = field.getName();
                    field.setAccessible(true);
                    field.set(instance, getBean(name));
                }
            }

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

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

    }

这里我用了JDK的新语法instanceof

这个afterPropertiesSet一般是spring整合其他技术时在此方法中进行一些校验操作,真实的spring中此方法可以抛出异常从而让bean创建失败,这里我没有声明异常罢了。

生命周期-初始化前(非BeanPostProcessor)

另外,与初始化相关的还有一个@PostConstruct注解,我们也来模拟实现下。此注解是jakarta ee的,可以引入依赖:

<!-- https://mvnrepository.com/artifact/jakarta.annotation/jakarta.annotation-api -->
<dependency>
    <groupId>jakarta.annotation</groupId>
    <artifactId>jakarta.annotation-api</artifactId>
    <version>3.0.0</version>
</dependency>

@PostConstruct注解的处理在真实的Spring源码中是在初始化前步骤中实现的,它的执行会先于afterPropertiesSet。下面我们也来模拟实现:

private Object createBean(String beanName, BeanDefinition beanDefinition) {

    Class<?> beanClass = beanDefinition.getBeanClass();

    try {
        // 实例化Bean 普通java对象
        Object instance = beanClass.getConstructor().newInstance();

        // 依赖注入
        for (Field field : beanClass.getDeclaredFields()) {
            if (field.isAnnotationPresent(Autowired.class)) {
                // 这里简化处理默认只按名称注入
                String name = field.getName();
                field.setAccessible(true);
                field.set(instance, getBean(name));
            }
        }

        // 初始化前
        for (Method method : beanClass.getDeclaredMethods()) {
            if (method.isAnnotationPresent(PostConstruct.class)) {
                method.invoke(instance);
            }
        }

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

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

}

生命周期-Aware回调

有初始化前,当然就有初始化后,但是在介绍初始化后之前,我们先来看下Aware回调。关于Aware回调,我们用的比较多的就是ApplicationContextAware,通常会搞一个SpringUtil工具类就会实现这个接口实现其中的setApplicationContext方法。

下面我们来模拟实现一下Aware回调机制,我们首先实现BeanNameAware,定义如下:

public interface BeanNameAware {
    void setBeanName(String name);
}

实现如下:

private Object createBean(String beanName, BeanDefinition beanDefinition) {

        Class<?> beanClass = beanDefinition.getBeanClass();

        try {
            // 实例化Bean 普通java对象
            Object instance = beanClass.getConstructor().newInstance();

            // 依赖注入
            for (Field field : beanClass.getDeclaredFields()) {
                if (field.isAnnotationPresent(Autowired.class)) {
                    // 这里简化处理默认只按名称注入
                    String name = field.getName();
                    field.setAccessible(true);
                    field.set(instance, getBean(name));
                }
            }

            // 初始化前
            for (Method method : beanClass.getDeclaredMethods()) {
                if (method.isAnnotationPresent(PostConstruct.class)) {
                    method.invoke(instance);
                }
            }

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

            if (instance instanceof BeanNameAware beanNameAware) {
                beanNameAware.setBeanName(beanName);
            }

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

    }

接着我们再模拟实现下ApplicationContextAware,其定义如下:

public interface ApplicationContextAware {

    void setApplicationContextAware(ApplicationContext context);

}

ApplicationContext接口定义:

public interface ApplicationContext {

    Object getBean(String beanName);
}

实现如下,主要是createBean方法,其它只是让AnnotationConfigApplicationContext实现ApplicationContext接口:

public class AnnotationConfigApplicationContext implements ApplicationContext {

    Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();
    Map<String, Object> singletonObjects = new HashMap<>();

    public AnnotationConfigApplicationContext(Class<?> configClass) {

        scan(configClass);

        // 循环创建bean
        for (Map.Entry<String, BeanDefinition> beanDefinitionEntry : beanDefinitionMap.entrySet()) {
            String beanName = beanDefinitionEntry.getKey();
            BeanDefinition beanDefinition = beanDefinitionEntry.getValue();

            if ("singleton".equals(beanDefinition.getScope()) && !beanDefinition.getLazy()) {
                Object singletonBean = createBean(beanName, beanDefinition);
                singletonObjects.put(beanName, singletonBean);
            }
        }

    }

    private Object createBean(String beanName, BeanDefinition beanDefinition) {

        Class<?> beanClass = beanDefinition.getBeanClass();

        try {
            // 实例化Bean 普通java对象
            Object instance = beanClass.getConstructor().newInstance();

            // 依赖注入
            for (Field field : beanClass.getDeclaredFields()) {
                if (field.isAnnotationPresent(Autowired.class)) {
                    // 这里简化处理默认只按名称注入
                    String name = field.getName();
                    field.setAccessible(true);
                    field.set(instance, getBean(name));
                }
            }

            // 初始化前
            for (Method method : beanClass.getDeclaredMethods()) {
                if (method.isAnnotationPresent(PostConstruct.class)) {
                    method.invoke(instance);
                }
            }

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

            if (instance instanceof BeanNameAware beanNameAware) {
                beanNameAware.setBeanName(beanName);
            }

            if (instance instanceof ApplicationContextAware applicationContextAware) {
                applicationContextAware.setApplicationContextAware(this);
            }

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

    }

    private void scan(Class<?> configClass) {
        // 解析配置类
        if (configClass.isAnnotationPresent(ComponentScan.class)) {
            ComponentScan componentScanAnnotation = configClass.getAnnotation(ComponentScan.class);
            String path = componentScanAnnotation.value();  // com.hexon.service
            path = path.replace('.', '/'); // com\hexon\service 这里不要用文件分隔符,因为后面的URL默认就用 / ,否则会转义报错
            // System.out.println(path);

            // 扫描 反射
            ClassLoader classLoader = getClass().getClassLoader();
            URL resource = classLoader.getResource(path);
            File file = new File(resource.getFile());

            // 这里简化操作路径直接指定到最后一层包,所以就没有递归处理了
            for (File listFile : file.listFiles()) {
                String classPath = listFile.getPath();
                // D:\2025\tuling\03_Spring\zhouyu01\code\mini-spring\business\target\classes\com\hexon\service\UserService.class
                // System.out.println(classPath);
                classPath = classPath.substring(classPath.indexOf("com"), classPath.indexOf(".class"));
                // System.out.println(classPath); // com\hexon\service\UserService
                classPath = classPath.replace('\\', '.');
                // System.out.println(classPath);  // com.hexon.service.UserService

                // 加载
                try {
                    Class<?> clazz = classLoader.loadClass(classPath);
                    // System.out.println(clazz);

                    if (clazz.isAnnotationPresent(Component.class)) {
                        // 代表是一个Bean

                        Component component = clazz.getAnnotation(Component.class);
                        String beanName = component.value();

                        if ("".equals(beanName)) {
                            beanName = Introspector.decapitalize(clazz.getSimpleName());
                        }

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

                        if (clazz.isAnnotationPresent(Scope.class)) {
                            String scope = clazz.getAnnotation(Scope.class).value();
                            beanDefinition.setScope(scope);
                        } else {
                            beanDefinition.setScope("singleton");
                        }

                        if (clazz.isAnnotationPresent(Lazy.class)) {
                            boolean lazy = clazz.getAnnotation(Lazy.class).value();
                            beanDefinition.setLazy(lazy);
                        } else {
                            beanDefinition.setLazy(false);
                        }

                        beanDefinitionMap.put(beanName, beanDefinition);

                    }

                } catch (ClassNotFoundException e) {
                    throw new RuntimeException(e);
                }
            }

        }
    }

    public Object getBean(String beanName) {

        if (!beanDefinitionMap.containsKey(beanName)) {
            throw new RuntimeException("No bean with name [" + beanName + "] found");
        }

        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 {
            // 多例
            return createBean(beanName, beanDefinition);
        }

    }
}

省略客户端测试代码...

BeanPostProcessor

我们先梳理下Bean的生命周期的大概脉络:

实例化、构造器注入(普通Java对象) --> 依赖注入(属性填充)--> 初始化前 --> 初始化 --> 初始化后

而初始化后的一个最重要的处理就是AOP,但是在介绍AOP之前,先要理解一下BeanPostProcessor这个接口。

这个接口中有两个方法,一个是初始化后,一个是初始化前,实际上真实的Spring源码中初始化前和初始化都是通过BeanPostProcessor实现的。下面我们先来模拟BeanPostProcessor接口的实现。

我们自己也创建一个BeanPostProcessor接口,定义如下:

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

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

再定义一个实现类AopBeanPostProcessor:

public class AopBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {

        // 动态代理 cglib基于父子类 代理类 extends UserService
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(bean.getClass());
        enhancer.setCallback(new MethodInterceptor() {
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                System.out.println("切面逻辑 before");
                Object result = method.invoke(bean, objects);
                System.out.println("切面逻辑 after");
                return result;
            }
        });
        return enhancer.create();
    }
}

为了使用cglib动态代码我们需要添加依赖:

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.3.0</version>
</dependency>

此时,我们先以简单的方法对这个接口的功能进行实现:

private Object createBean(String beanName, BeanDefinition beanDefinition) {

    Class<?> beanClass = beanDefinition.getBeanClass();

    try {
        // 实例化Bean 普通java对象
        Object instance = beanClass.getConstructor().newInstance();

        // 依赖注入
        for (Field field : beanClass.getDeclaredFields()) {
            if (field.isAnnotationPresent(Autowired.class)) {
                // 这里简化处理默认只按名称注入
                String name = field.getName();
                field.setAccessible(true);
                field.set(instance, getBean(name));
            }
        }

        // 初始化前
        for (Method method : beanClass.getDeclaredMethods()) {
            if (method.isAnnotationPresent(PostConstruct.class)) {
                method.invoke(instance);
            }
        }

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

        if (instance instanceof BeanNameAware beanNameAware) {
            beanNameAware.setBeanName(beanName);
        }

        if (instance instanceof ApplicationContextAware applicationContextAware) {
            applicationContextAware.setApplicationContextAware(this);
        }

        // 初始化后 AOP
        AopBeanPostProcessor aopBeanPostProcessor = new AopBeanPostProcessor();
        instance = aopBeanPostProcessor.postProcessAfterInitialization(instance, beanName);

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

}

这里暂时先直接写死AopBeanPostProcessor,但要注意的是返回的instance要重新接收一下,因为postProcessAfterInitialization方法中返回的不一定是原本的instance

客户端测试:

@Component
public class UserService {

    @Autowired
    private OrderService orderService;

    public void test() {
        System.out.println("hell hexon");
    }
}
=========================================================
输出结果:
切面逻辑 before
hell hexon
切面逻辑 after

如果使用的是JDK17,请添加jvm参数:--add-opens java.base/java.lang=ALL-UNNAMED ,否则会有报错。

至此,我们实现了BeanPostProcessor的postProcessAfterInitialization方法,postProcessBeforeInitialization的原理是类似的。真正的Spring源码中是直接把cglib的代码内联直接放到源码中的。


生命周期-初始化后

这个BeanPostProcessor其实就是一个扩展点,是针对所有Bean的。也就是Bean依赖注入后还想对其进行一些复杂的操作就可以把操作逻辑封装到BeanPostProcessor里面,因此不仅仅是Spring源码内容可以有内置的BeanPostProcessor,客户端程序员也可以自己定义BeanPostProcessor。

例如在business模块中定义MyBeanPostProcessor:

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        if("userService".equals(beanName)) {
            System.out.println("myBeanPostProcessor....");
        }
        return bean;
    }
}

接下来就要改造框架端的代码,我们肯定不能把AopBeanProcessor写死在代码中。而且对于外部的BeanPostProcessor都是Bean,内部的我们也要添加进来。改造后的代码如下:

public class AnnotationConfigApplicationContext implements ApplicationContext {

    Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();
    Map<String, Object> singletonObjects = new HashMap<>();
    List<BeanPostProcessor> beanPostProcessorList = new ArrayList<>();

    public AnnotationConfigApplicationContext(Class<?> configClass) {

        scan(configClass);

        // 在真正创建Bean之前收集所有的BeanPostProcessor的Bean
        // 添加内置的AopBeanPostProcessor
        // beanPostProcessorList.add(new AopBeanPostProcessor());  // 这里放后面吧,放前面createBean会给自己代理一次
        for (Map.Entry<String, BeanDefinition> beanDefinitionEntry : beanDefinitionMap.entrySet()) {
            String beanName = beanDefinitionEntry.getKey();
            BeanDefinition beanDefinition = beanDefinitionEntry.getValue();

            if (BeanPostProcessor.class.isAssignableFrom(beanDefinition.getBeanClass())) {
                beanPostProcessorList.add((BeanPostProcessor) createBean(beanName, beanDefinition)); // 这里也可以getBean
            }
        }
        beanPostProcessorList.add(new AopBeanPostProcessor());


        // 循环创建bean
        for (Map.Entry<String, BeanDefinition> beanDefinitionEntry : beanDefinitionMap.entrySet()) {
            String beanName = beanDefinitionEntry.getKey();
            BeanDefinition beanDefinition = beanDefinitionEntry.getValue();

            if ("singleton".equals(beanDefinition.getScope()) && !beanDefinition.getLazy()) {
                // 排除BeanPostProcessor的Bean,防止重复创建
                if (!BeanPostProcessor.class.isAssignableFrom(beanDefinition.getBeanClass())) {
                    Object singletonBean = createBean(beanName, beanDefinition);
                    singletonObjects.put(beanName, singletonBean);
                }
            }
        }

    }

    private Object createBean(String beanName, BeanDefinition beanDefinition) {

        Class<?> beanClass = beanDefinition.getBeanClass();

        try {
            // 实例化Bean 普通java对象
            Object instance = beanClass.getConstructor().newInstance();

            // 依赖注入
            for (Field field : beanClass.getDeclaredFields()) {
                if (field.isAnnotationPresent(Autowired.class)) {
                    // 这里简化处理默认只按名称注入
                    String name = field.getName();
                    field.setAccessible(true);
                    field.set(instance, getBean(name));
                }
            }

            // 初始化前
            for (Method method : beanClass.getDeclaredMethods()) {
                if (method.isAnnotationPresent(PostConstruct.class)) {
                    method.invoke(instance);
                }
            }

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

            if (instance instanceof BeanNameAware beanNameAware) {
                beanNameAware.setBeanName(beanName);
            }

            if (instance instanceof ApplicationContextAware applicationContextAware) {
                applicationContextAware.setApplicationContextAware(this);
            }

            // 初始化后 AOP
            for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
                instance = beanPostProcessor.postProcessAfterInitialization(instance, beanName);
            }

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

    }

    private void scan(Class<?> configClass) {
        // 解析配置类
        if (configClass.isAnnotationPresent(ComponentScan.class)) {
            ComponentScan componentScanAnnotation = configClass.getAnnotation(ComponentScan.class);
            String path = componentScanAnnotation.value();  // com.hexon.service
            path = path.replace('.', '/'); // com\hexon\service 这里不要用文件分隔符,因为后面的URL默认就用 / ,否则会转义报错
            // System.out.println(path);

            // 扫描 反射
            ClassLoader classLoader = getClass().getClassLoader();
            URL resource = classLoader.getResource(path);
            File file = new File(resource.getFile());

            // 这里简化操作路径直接指定到最后一层包,所以就没有递归处理了
            for (File listFile : file.listFiles()) {
                String classPath = listFile.getPath();
                // D:\2025\tuling\03_Spring\zhouyu01\code\mini-spring\business\target\classes\com\hexon\service\UserService.class
                // System.out.println(classPath);
                classPath = classPath.substring(classPath.indexOf("com"), classPath.indexOf(".class"));
                // System.out.println(classPath); // com\hexon\service\UserService
                classPath = classPath.replace('\\', '.');
                // System.out.println(classPath);  // com.hexon.service.UserService

                // 加载
                try {
                    Class<?> clazz = classLoader.loadClass(classPath);
                    // System.out.println(clazz);

                    if (clazz.isAnnotationPresent(Component.class)) {
                        // 代表是一个Bean

                        Component component = clazz.getAnnotation(Component.class);
                        String beanName = component.value();

                        if ("".equals(beanName)) {
                            beanName = Introspector.decapitalize(clazz.getSimpleName());
                        }

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

                        if (clazz.isAnnotationPresent(Scope.class)) {
                            String scope = clazz.getAnnotation(Scope.class).value();
                            beanDefinition.setScope(scope);
                        } else {
                            beanDefinition.setScope("singleton");
                        }

                        if (clazz.isAnnotationPresent(Lazy.class)) {
                            boolean lazy = clazz.getAnnotation(Lazy.class).value();
                            beanDefinition.setLazy(lazy);
                        } else {
                            beanDefinition.setLazy(false);
                        }

                        beanDefinitionMap.put(beanName, beanDefinition);

                    }

                } catch (ClassNotFoundException e) {
                    throw new RuntimeException(e);
                }
            }

        }
    }

    public Object getBean(String beanName) {

        if (!beanDefinitionMap.containsKey(beanName)) {
            throw new RuntimeException("No bean with name [" + beanName + "] found");
        }

        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 {
            // 多例
            return createBean(beanName, beanDefinition);
        }

    }
}

① 首先肯定是将初始后化写死的位置,改成能动态执行,特别要注意的是BeanPostProcessor的两个方法的返回值都可能修改原本的instance,所以一定别忘记重新接收下。

② 要想执行所有的BeanPostProcessor,肯定是要先收集所有的BeanPostProcessor,而且应该是在真正循环创建Bean之前就要收集,因为创建Bean要调用createBean方法,而createBean方法中要执行BeanPostProcessor,因为我们改造中构造方法,添加了一段循环收集的逻辑。

③ 为了防止代理多次和重复创建的问题,我们进行了如下操作:

  • beanPostProcessorList.add(new AopBeanPostProcessor()); 放在循环后面

  • 循环创建bean时增加if (!BeanPostProcessor.class.isAssignableFrom(beanDefinition.getBeanClass()))判断

生命周期-初始化前(BeanPostProcessor)

现在我们再给createBean方法中增加BeanPostProcessor#postProcessAfterInitialization的处理逻辑:

private Object createBean(String beanName, BeanDefinition beanDefinition) {

    Class<?> beanClass = beanDefinition.getBeanClass();

    try {
        // 实例化Bean 普通java对象
        Object instance = beanClass.getConstructor().newInstance();

        // 依赖注入
        for (Field field : beanClass.getDeclaredFields()) {
            if (field.isAnnotationPresent(Autowired.class)) {
                // 这里简化处理默认只按名称注入
                String name = field.getName();
                field.setAccessible(true);
                field.set(instance, getBean(name));
            }
        }

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

        // 初始化前
        for (Method method : beanClass.getDeclaredMethods()) {
            if (method.isAnnotationPresent(PostConstruct.class)) {
                method.invoke(instance);
            }
        }

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

        if (instance instanceof BeanNameAware beanNameAware) {
            beanNameAware.setBeanName(beanName);
        }

        if (instance instanceof ApplicationContextAware applicationContextAware) {
            applicationContextAware.setApplicationContextAware(this);
        }

        // 初始化后 AOP
        for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
            instance = beanPostProcessor.postProcessAfterInitialization(instance, beanName);
        }

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

}

客户端测试代码:

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
        if("userService".equals(beanName)) {
            System.out.println("myBeanPostProcessor before ....");
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        if("userService".equals(beanName)) {
            System.out.println("myBeanPostProcessor after....");
        }
        return bean;
    }
}

AOP模拟实现

下面我们来详细模拟实现AOP功能。首先添加一个依赖:

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.21</version>
</dependency>


定义切面-Aspect

business模块中,定义一个MyAspect切面类:

@Component
@Aspect
public class MyAspect {
​
    @Before("execution(public void com.zhouyu.service.UserService.test())")
    public void myBefore() {
        System.out.println("myBefore...");
    }
}

这里有3个概念要注意:

Pointcut-切点,如上面的 @Before("execution(public void com.zhouyu.service.UserService.test())") 
Advice-通知,具体的方法,如上面的myBefore
Advisor = Pointcut + Advice

下面我们就来改造AopBeanPostProcessor这个类,具体模拟下AOP的过程。

Advisor

Advisor就有点像BeanDefinition一样的,它是Spring内部抽象的一个概念,我们先来创建这个类:

public class Advisor {
​
    private String pointcut;
    private Method advice;
    private Object aspect;
​
    public Advisor(String pointcut, Method advice, Object aspect) {
        this.pointcut = pointcut;
        this.advice = advice;
        this.aspect = aspect;
    }
​
    public String getPointcut() {
        return pointcut;
    }
​
    public void setPointcut(String pointcut) {
        this.pointcut = pointcut;
    }
​
    public Method getAdvice() {
        return advice;
    }
​
    public void setAdvice(Method advice) {
        this.advice = advice;
    }
​
    public Object getAspect() {
        return aspect;
    }
​
    public void setAspect(Object aspect) {
        this.aspect = aspect;
    }
}

具体实现

public class AopBeanPostProcessor implements BeanPostProcessor {
​
    private List<Advisor> advisors = new ArrayList<>();
​
    public AopBeanPostProcessor(ApplicationContext applicationContext) {
        for (Map.Entry<String, BeanDefinition> beanDefinitionEntry : applicationContext.getBeanDefinitionMap().entrySet()) {
            String beanName = beanDefinitionEntry.getKey();
            BeanDefinition beanDefinition = beanDefinitionEntry.getValue();
            Class<?> beanClass = beanDefinition.getBeanClass();
​
            if (beanClass.isAnnotationPresent(Aspect.class)) {
                for (Method method : beanClass.getDeclaredMethods()) {
                    if (method.isAnnotationPresent(Before.class)) { // 因为是模拟,这里我们只收集了Before注解
                        Before beforeAnnotation = method.getAnnotation(Before.class);
                        String pointcut = beforeAnnotation.value();
                        Advisor advisor = new Advisor(pointcut, method, applicationContext.getBean(beanName));
                        advisors.add(advisor);
                    }
                }
            }
        }
    }
​
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        System.out.println("beanPostProcessor...");
        for (Advisor advisor : advisors) {
            Method advice = advisor.getAdvice();
            String pointcut = advisor.getPointcut();
​
            // pointcut匹配,需要进行aop
            if (pointcut.contains(bean.getClass().getSimpleName())) {  // 因为是模拟,这里我简单匹配处理了
                Enhancer enhancer = new Enhancer();
                enhancer.setSuperclass(bean.getClass());
                enhancer.setCallback(new MethodInterceptor() {
                    @Override
                    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
​
                        // 执行切面逻辑
                        advice.invoke(advisor.getAspect(), null);
​
                        // 执行原本逻辑
                        return method.invoke(bean, objects);
                    }
                });
                return enhancer.create();
            }
        }
​
        return bean;
    }
}

这时实现是一样的套路,先在构造器中扫描所有的Advisor,再到具体处理方法中循环调用。

只不过,我们给ApplicationContext接口增加了方法,因此代码有些重构的地方。

ApplicationContext接口:

public interface ApplicationContext {
​
    Object getBean(String beanName);
​
    Map<String, BeanDefinition> getBeanDefinitionMap();
}

AnnotationConfigApplicationContext在增加方法:

public Map<String, BeanDefinition> getBeanDefinitionMap() {
    return beanDefinitionMap;
}

总结

这课节我们通过Spring的常见应用,反推实现了内部的大概过程。真正的Spring源码已经是一个庞大的工程,里面的接口与类错综复杂,这里只能说暂时理解了大概的过程,要想深入理解细节还是要自己去看源码的,后面的课程会逐步走向源码的阅读与分析,加油!