通过手写模拟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用的LinkListprivate List<BeanPostProcessor> beanPostProcessorList = new ArrayList<>();// 构造方法,在创建 ApplicationContext 时传入配置类public BubbleApplicationContext(Class configClass) {this.configClass = configClass;// 扫描配置类并初始化 beanDefinitionMap,,beanPostProcessorListscan(configClass);// 遍历 beanDefinitionMap,创建并初始化单例对象,并存入 singletonObjectsfor (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.UserServiceObject 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);// 根据扫描路径获取资源 URLFile 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.UserServicetry {// 使用类加载器加载类Class<?> clazz = classLoader.loadClass(absolutePath);// 判断类是否标注了 Component 注解,表示为一个需要管理的 beanif (clazz.isAnnotationPresent(Component.class)) {// 如果类实现了 BeanPostProcessor 接口,将其实例化并加入 beanPostProcessorListif (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 {// 默认作用域为 singletonbeanDefinition.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 进行切面逻辑处理。@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) {// 判断是否是特定的 Bean,这里以 "userService" 为例if (beanName.equals("userService")) {// 创建动态代理对象,用于在原始方法调用前后添加切面逻辑Object proxyInstance = Proxy.newProxyInstance(BubbleBeanPostProcessor.class.getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() {@Overridepublic 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 注解为特定的字段赋值。@Overridepublic 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();}}}// beanreturn 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 {@Autowiredprivate OrderService orderService;@BubbleValue("bubble")private String test;private String beanName;@Overridepublic void setBeanName(String name) {this.beanName = name;}// public void test() {
// System.out.println("test");
// }@Overridepublic 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 BeanPostPRocessBubbleApplicationContext applicationContext = new BubbleApplicationContext(AppConfig.class);//UserService userService = (UserService)applicationContext.getBeen("userService");UserInterface userService = (UserInterface) applicationContext.getBeen("userService");userService.test();}
}