在上篇文章中,我们已经将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源码已经是一个庞大的工程,里面的接口与类错综复杂,这里只能说暂时理解了大概的过程,要想深入理解细节还是要自己去看源码的,后面的课程会逐步走向源码的阅读与分析,加油!