通过手写模拟Spring
- 了解Spring的底层源码启动过程
- 了解BeanDefinition、BeanPostProcessor的概念
- 了解Spring解析配置类等底层源码工作流程
- 了解依赖注入,Aware回调等底层源码工作流程
- 了解Spring AOP的底层源码工作流程
这里实现一个简化版的 Spring 框架的核心功能,模拟应用程序上下文(ApplicationContext)的创建、bean 的定义、依赖注入、作用域管理和后置处理等过程。
实际的 Spring 框架在此基础上还有更多功能和复杂性,这里只提供一个基础的理解。
核心功能:
- BubbleApplicationContext 是主要的应用程序上下文类,负责管理 bean 的定义和实例化。
- BeanDefinition 用于封装 bean 的定义,包括类型和作用域等信息。
- BeanPostProcessor 接口定义了在 bean 创建过程中的后置处理方法。
数据结构:
- beanDefinitionMap 存储了 bean 的定义信息,以 bean 名称为键。
- singletonObjects 保存了单例 bean 的实例,以 bean 名称为键。
- beanPostProcessorList 包含实现了 BeanPostProcessor 接口的后置处理器。
初始化流程:
- 构造方法扫描配置类,初始化 beanDefinitionMap 和 beanPostProcessorList。
- 对于单例 bean,遍历 beanDefinitionMap,创建和初始化实例,存入 singletonObjects。
bean 创建和初始化:
- createBean 方法使用反射创建 bean 实例,包括依赖注入和后置处理逻辑。
- 自动注入带有 Autowired 注解的字段。
- 设置 bean 的名称,如果实现了 BeanNameAware 接口。
- 执行前置后置处理器的逻辑。
- 如果实现了 InitializingBean 接口,执行初始化逻辑。
获取 bean 实例:
- getBeen 方法根据 bean 名称获取 bean 实例。
- 对于单例,如果实例已存在,直接返回;否则创建并存入。
- 对于原型,每次获取都创建新实例。
扫描和初始化:
- scan 方法扫描配置类,初始化 bean。
- 判断是否标注了 ComponentScan 注解,获取扫描路径。
- 遍历类文件,解析 Component 注解,初始化 bean。
简易实现代码如下:
目录结构:
package com.spring;
import java.beans.Introspector;
import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class BubbleApplicationContext {
private Class configClass;
// 存储 BeanDefinition 对象的映射,用于管理 bean 的定义信息
private Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();
// 存储单例对象的映射,用于管理单例 bean 的实例
private Map<String, Object> singletonObjects = new HashMap<>();
// 存储 BeanPostProcessor 的列表,用于后置处理 bean,,,spring用的LinkList
private List<BeanPostProcessor> beanPostProcessorList = new ArrayList<>();
// 构造方法,在创建 ApplicationContext 时传入配置类
public BubbleApplicationContext(Class configClass) {
this.configClass = configClass;
// 扫描配置类并初始化 beanDefinitionMap,,beanPostProcessorList
scan(configClass);
// 遍历 beanDefinitionMap,创建并初始化单例对象,并存入 singletonObjects
for (Map.Entry<String, BeanDefinition> entry : beanDefinitionMap.entrySet()) {
String beanName = entry.getKey();
BeanDefinition beanDefinition = entry.getValue();
if (beanDefinition.getScope().equals("singleton")) {
Object bean = createBean(beanName, beanDefinition);
singletonObjects.put(beanName, bean);
}
}
}
// 创建 bean 对象的方法,包括依赖注入、后置处理等逻辑
private Object createBean(String beanName, BeanDefinition beanDefinition) {
Class clazz = beanDefinition.getType();//com.bubble.service.UserService
Object instance = null;
try {
instance = clazz.getConstructor().newInstance(); // 使用反射创建实例
for (Field field : clazz.getDeclaredFields()) {
// 对带有 Autowired 注解的字段进行依赖注入
if (field.isAnnotationPresent(Autowired.class)) {
field.setAccessible(true);
field.set(instance, getBeen(field.getName()));
}
}
// 若实现了 BeanNameAware 接口,设置 bean 的名称
if (instance instanceof BeanNameAware) {
((BeanNameAware) instance).setBeanName(beanName);
}
// 执行 BeanPostProcessor 的前置处理逻辑
for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
instance = beanPostProcessor.postProcessBeforeInitialization(instance, beanName);
}
// 若实现了 InitializingBean 接口,执行初始化逻辑
if (instance instanceof InitializingBean) {
((InitializingBean)instance).afterPropertiesSet();
}
// 执行 BeanPostProcessor 的后置处理逻辑
for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
instance = beanPostProcessor.postProcessAfterInitialization(instance, beanName);
}
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
return instance;
}
// 获取 bean 对象的方法,支持单例和原型两种作用域
public Object getBeen(String beanName) {
// 如果beanDefinitionMap中不包含beanName,说明传入的bean是不存在的
if (!beanDefinitionMap.containsKey(beanName)) {
throw new NullPointerException();
}
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
if (beanDefinition.getScope().equals("singleton")) {
Object singletonBean = singletonObjects.get(beanName);
if (singletonBean == null) {
singletonBean = createBean(beanName, beanDefinition);
singletonObjects.put(beanName, singletonBean);
}
return singletonBean;
} else {
// 原型(多例)
Object prototypeBean = createBean(beanName, beanDefinition);
return prototypeBean;
}
}
/**
* 扫描指定配置类,解析其中的 ComponentScan 注解,根据注解配置的扫描路径
* 查找并解析带有 Component 注解的类,初始化对应的 BeanDefinition。
*
* @param configClass 配置类,用于查找 ComponentScan 注解
*/
private void scan(Class configClass) {
// 检查配置类是否标注了 ComponentScan 注解
if(configClass.isAnnotationPresent(ComponentScan.class)) {
// 获取 ComponentScan 注解实例
ComponentScan componentScanAnnotation = (ComponentScan) configClass.getAnnotation(ComponentScan.class);
// 获取扫描路径,并将包名中的点替换为斜线,以便在类加载器中定位资源
String path = componentScanAnnotation.value();
path = path.replace(".","/");// com/bubble/service
// 获取类加载器,用于加载类和资源
ClassLoader classLoader = BubbleApplicationContext.class.getClassLoader();
URL resource = classLoader.getResource(path);// 根据扫描路径获取资源 URL
File file = new File(resource.getFile());// 将 URL 转换为文件对象,以便遍历目录和文件
// 判断是否为目录,如果是目录则遍历其中的文件
if(file.isDirectory()){
for (File f : file.listFiles()) {
// 获取文件的绝对路径
String absolutePath = f.getAbsolutePath();//E:\Dev\Spring\bubble-spring\target\classes\com\bubble\service\UserService.class
// 提取类路径部分,去除文件扩展名
absolutePath = absolutePath.substring(absolutePath.indexOf("com"), absolutePath.indexOf(".class"));//com\bubble\service\UserService
// 将文件路径中的斜线替换为点,得到完整的类名
absolutePath = absolutePath.replace("\\", ".");//com.bubble.service.UserService
try {
// 使用类加载器加载类
Class<?> clazz = classLoader.loadClass(absolutePath);
// 判断类是否标注了 Component 注解,表示为一个需要管理的 bean
if (clazz.isAnnotationPresent(Component.class)) {
// 如果类实现了 BeanPostProcessor 接口,将其实例化并加入 beanPostProcessorList
if (BeanPostProcessor.class.isAssignableFrom(clazz)) {
BeanPostProcessor instance = (BeanPostProcessor) clazz.getConstructor().newInstance();
beanPostProcessorList.add(instance);
}
// 获取 Component 注解实例
Component componentAnnotation = clazz.getAnnotation(Component.class);
// 获取 bean 的名称,如果未指定,则使用类名的首字母小写作为默认名称
String beanName = componentAnnotation.value();
if ("".equals(beanName)) {
beanName = Introspector.decapitalize(clazz.getSimpleName());
}
// 创建并初始化 BeanDefinition 对象
BeanDefinition beanDefinition = new BeanDefinition();
beanDefinition.setType(clazz);
// 判断类是否标注了 Scope 注解,设置 bean 的作用域
if (clazz.isAnnotationPresent(Scope.class)) {
Scope scopeAnnotation = clazz.getAnnotation(Scope.class);
String value = scopeAnnotation.value();
beanDefinition.setScope(value);
} else {
// 默认作用域为 singleton
beanDefinition.setScope("singleton");
}
// 将 BeanDefinition 添加到 beanDefinitionMap 中,以便后续使用
beanDefinitionMap.put(beanName, beanDefinition);
}
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
}
}
}
}
package com.spring;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Autowired {
}
package com.spring;
public class BeanDefinition {
private Class type;
private String scope;
private boolean isLazy;
public Class getType() {
return type;
}
public void setType(Class type) {
this.type = type;
}
public String getScope() {
return scope;
}
public void setScope(String scope) {
this.scope = scope;
}
public boolean isLazy() {
return isLazy;
}
public void setLazy(boolean lazy) {
isLazy = lazy;
}
}
public interface BeanNameAware {
void setBeanName(String name);
}
public interface BeanPostProcessor {
default Object postProcessBeforeInitialization(Object bean, String beanName) {
return bean;
}
default Object postProcessAfterInitialization(Object bean, String beanName) {
return bean;
}
}
package com.spring;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Component {
String value() default "";
}
package com.spring;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ComponentScan {
String value() default "";
}
public interface InitializingBean {
void afterPropertiesSet();
}
package com.spring;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Scope {
String value() default "";
}
package com.bubble.service;
import com.spring.BeanPostProcessor;
import com.spring.Component;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//自定义 Bean 后置处理器,用于在 Bean 初始化之后,对特定的 Bean 进行切面逻辑的处理。
@Component
public class BubbleBeanPostProcessor implements BeanPostProcessor {
//在 Bean 初始化之后,对特定的 Bean 进行切面逻辑处理。
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
// 判断是否是特定的 Bean,这里以 "userService" 为例
if (beanName.equals("userService")) {
// 创建动态代理对象,用于在原始方法调用前后添加切面逻辑
Object proxyInstance = Proxy.newProxyInstance(BubbleBeanPostProcessor.class.getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 切面
System.out.println("切面逻辑");
return method.invoke(bean, args);
}
});
// 返回代理对象,即添加了切面逻辑的 Bean 实例
return proxyInstance;
}
//对于其他 Bean,保持原样返回,不添加切面逻辑
return bean;
}
}
package com.bubble.service;
import com.spring.BeanPostProcessor;
import com.spring.Component;
import java.lang.reflect.Field;
//自定义 Bean 后置处理器,用于在 Bean 初始化之前,根据 BubbleValue 注解为特定的字段赋值。
@Component("userService")
public class BubbleValueBeanPostProcessor implements BeanPostProcessor {
//在 Bean 初始化之前,根据 BubbleValue 注解为特定的字段赋值。
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
for (Field field : bean.getClass().getDeclaredFields()) {
// 检查字段是否标注了 BubbleValue 注解
if (field.isAnnotationPresent(BubbleValue.class)) {
field.setAccessible(true);// 设置字段的访问权限,允许反射访问私有字段
try {
field.set(bean, field.getAnnotation(BubbleValue.class).value());
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
// bean
return bean;
}
}
package com.bubble.service;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface BubbleValue {
String value() default "";
}
package com.bubble.service;
import com.spring.Component;
@Component
public class OrderService {
public void test() {
System.out.println("test->OrderService");
}
}
public interface UserInterface {
public void test();
}
package com.bubble.service;
import com.spring.Autowired;
import com.spring.BeanNameAware;
import com.spring.Component;
@Component("userService")
public class UserService implements UserInterface, BeanNameAware {
@Autowired
private OrderService orderService;
@BubbleValue("bubble")
private String test;
private String beanName;
@Override
public void setBeanName(String name) {
this.beanName = name;
}
// public void test() {
// System.out.println("test");
// }
@Override
public void test() {
System.out.println(beanName);
System.out.println(test);
}
}
package com.bubble;
import com.spring.ComponentScan;
@ComponentScan("com.bubble.service")
public class AppConfig {
}
程序调用测试
public class Test {
public static void main(String[] args) {
//扫描-->创建单例bean BeanDefinition BeanPostPRocess
BubbleApplicationContext applicationContext = new BubbleApplicationContext(AppConfig.class);
//UserService userService = (UserService)applicationContext.getBeen("userService");
UserInterface userService = (UserInterface) applicationContext.getBeen("userService");
userService.test();
}
}