- 前言
- 目前已实现
- 1 简单校验
- 2 扫描配置
- 3 根据扫描到的配置组装 BeanDefinition
- 4 根据 BeanDefinition 创建非懒加载、并且是单例的bean,存储到单例池
- 5 增加 BeanNameAware 接口
- 6 增加 InitializingBean 接口
- 7 增加 BeanPostProcessor 接口
- 延伸阅读
- 手写 Spring的代码
- ApplicationContext
- Autowird
- BeanDefinition
- BeanFactory
- BeanNameAware
- BeanPostProcessor
- Component
- ComponentScan
- Configuration
- DefaultAnnotationApplicationContext
- InitializingBean
- Lazy
- Scope
最近项目里有大量的 “长的很像的代码”。这类代码,用到了工厂模式、建造者模式,但是最终由于业务复杂,而且功能上是对接平台的,因此会有上百个这种类,每个都不一样。
出于对其优化的目的,我重学了下 Spring 框架,看看从框架层面,能不能有什么突破点。
后来,在对 Spring 的 Bean 的生命周期的学习中,看中了 BeanPostProcessor 这个前置和后置处理器。发现这框架还是得好好研究下,可能能让我们目前的项目代码能更加灵活、易懂。甚至达到开闭原则。
也正是这种想法,那对于简单的学习框架的使用,已经不能满足了,得从源码学起。而学习源码的第一课就是【写一个简易版的 Spring 框架】,用以熟悉框架中的思想。
我的简易版的代码位于这个仓库中:
https://gitee.com/fengsoshuai/demo-spring
主要是对 Configuration 注解和 ComponentScan 注解的校验,要求配置类上要有这俩注解。
2 扫描配置根据启动时传入的配置类,获取配置类上的注解 ComponentScan 中的参数,即包名。 根据包名扫描该包下的所有的 .class 文件,包的深度现在设置的是20,应该是够用了。
将扫描到的 .class 文件名,使用字符串截取的方式,组装出要用的类的全限定名。
3 根据扫描到的配置组装 BeanDefinition根据第2步获取到的类名,加载到类。得到 Class。 再根据Class解析Class上是否带有 Component注解。
如果带有 Component 注解,将该注解上的属性进行解析,作为 bean 的名称。如果没有指定名称默认使用类名小写第一个字母作为bean的名称。
BeanDefinition 中有 以下属性:
private Class<?> beanClass;
private String scope;
private boolean isLazy;
其中 beanClass 是bean对应的 Class 就是根据第2步获得的类的完整名称加载出来的。 scope 用来表示是单例bean还是多例bean。 isLazy表示当前生成bean是否是懒加载。
最终存储时,使用 beanName 作为 key,BeanDefinition 作为 value存储到一个Map中。
4 根据 BeanDefinition 创建非懒加载、并且是单例的bean,存储到单例池这一步是根据 BeanDefinition 中的 beanClass,获取到该类的无参数构造器,在根据这个无参数构造器生成一个bean,同时将该bean存储到单例池中。
5 增加 BeanNameAware 接口BeanNameAware 当类中需要使用 beanName时,实现此接口。 在初始化设置属性之后,对beanName 进行赋值。
6 增加 InitializingBean 接口当对实例需要做属性设置值之后,再进行 *** 作。 常用于对实例的属性值进行校验。
7 增加 BeanPostProcessor 接口bean的后置处理器: 常用于扩展,在Bean初始化,设置属性值之后执行。或在刚刚通过构造器创建实例后执行(设置属性之前)。
延伸阅读测试&包文件说明
在org.feng.demo包下,有一个Test类,目前暂时在里边使用 main方法进行测试。 至于 org.feng.framework,就是模拟spring框架的注解,接口,类的定义的位置。
其中各个注解的具体实现逻辑,基本都在DefaultAnnotationApplicationContext类内。
手写 Spring的代码
所有的代码就是这红框中的内容了。至于 org.feng.demo,是为了测试这个框架好不好用写的测试。
package org.feng.framework;
/**
* 应用上下文
*
* @version v1.0
* @author: fengjinsong
* @date: 2022年04月09日 14时40分
*/
public interface ApplicationContext extends BeanFactory {
}
Autowird
package org.feng.framework;
import java.lang.annotation.*;
/**
* 自动注入
*
* @version v1.0
* @author: fengjinsong
* @date: 2022年04月09日 14时47分
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Autowird {
}
BeanDefinition
package org.feng.framework;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
/**
* bean描述
*
* @version v1.0
* @author: fengjinsong
* @date: 2022年04月09日 16时45分
*/
@ToString
@Data
@AllArgsConstructor
@NoArgsConstructor
public class BeanDefinition {
private Class<?> beanClass;
private String scope;
private boolean isLazy;
}
BeanFactory
package org.feng.framework;
/**
* 获取Bean的工厂类
*
* @version v1.0
* @author: fengjinsong
* @date: 2022年04月09日 14时43分
*/
public interface BeanFactory {
Object getBean(String name);
<T>T getBean(String name, Class<T> clazz);
}
BeanNameAware
package org.feng.framework;
/**
* 设置bean名称:当想在该类中使用spring的beanName时,实现这个接口
*
* @version v1.0
* @author: fengjinsong
* @date: 2022年04月09日 18时17分
*/
public interface BeanNameAware {
void setBeanName(String name);
}
BeanPostProcessor
package org.feng.framework;
/**
* Bean的后置处理器
*
* @version v1.0
* @author: fengjinsong
* @date: 2022年04月09日 18时53分
*/
public interface BeanPostProcessor {
default Object postProcessBeforeInitialization(Object bean, String beanName){
return bean;
};
default Object postProcessAfterInitialization(Object bean, String beanName){
return bean;
};
}
Component
package org.feng.framework;
import java.lang.annotation.*;
/**
* 组件注解
*
* @version v1.0
* @author: fengjinsong
* @date: 2022年04月09日 14时39分
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Component {
/**
* 对组件命名
*
* @return 存进容器时的名称
*/
String value() default "";
}
ComponentScan
package org.feng.framework;
import java.lang.annotation.*;
/**
* 组件扫描路径
*
* @version v1.0
* @author: fengjinsong
* @date: 2022年04月09日 14时49分
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ComponentScan {
String value();
}
Configuration
package org.feng.framework;
import java.lang.annotation.*;
/**
* 配置类的注解
*
* @version v1.0
* @author: fengjinsong
* @date: 2022年04月09日 14时56分
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Configuration {
}
DefaultAnnotationApplicationContext
package org.feng.framework;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
/**
* 应用上下文实现
*
* @version v1.0
* @author: fengjinsong
* @date: 2022年04月09日 14时41分
*/
public class DefaultAnnotationApplicationContext implements ApplicationContext {
/**
* 配置类
*/
private final Class<?> configClass;
private static final String PROTOTYPE = "prototype";
private static final String SINGLETON = "singleton";
/**
* beanName 和 bean 定义的映射
*/
private static final Map<String, BeanDefinition> BEAN_DEFINITION_MAP = new HashMap<>(32);
/**
* 单例池
*/
private static final Map<String, Object> SINGLETON_MAP = new ConcurrentHashMap<>();
/**
* 后置处理器
*/
private static final List<BeanPostProcessor> BEAN_POST_PROCESSORS = new ArrayList<>();
public DefaultAnnotationApplicationContext(Class<?> configClass) {
this.configClass = configClass;
// 校验配置、注解使用是否正常
check(configClass);
// 扫描包,获得bean定义
scanConfig();
// 非懒加载、单例bean生成实例
createNonLazySingletonBean();
}
@Override
public Object getBean(String name) {
BeanDefinition beanDefinition = BEAN_DEFINITION_MAP.get(name);
if (beanDefinition != null) {
// 单例bean
if (SINGLETON.equals(beanDefinition.getScope())) {
// 处理懒加载
if (beanDefinition.isLazy()) {
if (SINGLETON_MAP.containsKey(name)) {
return SINGLETON_MAP.get(name);
}
Object instance = creatInstance(name, beanDefinition);
SINGLETON_MAP.put(name, instance);
return instance;
}
// 非懒加载从单例池中取
return SINGLETON_MAP.get(name);
}
// 多例bean
if (PROTOTYPE.equals(beanDefinition.getScope())) {
return creatInstance(name, beanDefinition);
}
}
return null;
}
@Override
public <T> T getBean(String name, Class<T> clazz) {
BeanDefinition beanDefinition = BEAN_DEFINITION_MAP.get(name);
if (beanDefinition != null) {
// 单例bean
if (SINGLETON.equals(beanDefinition.getScope()) && clazz == beanDefinition.getBeanClass()) {
// 处理懒加载
if (beanDefinition.isLazy()) {
if (SINGLETON_MAP.containsKey(name)) {
return (T) SINGLETON_MAP.get(name);
}
Object instance = creatInstance(name, beanDefinition);
SINGLETON_MAP.put(name, instance);
return (T) instance;
}
// 非懒加载从单例池中取
return (T) SINGLETON_MAP.get(name);
}
// 多例bean
if (PROTOTYPE.equals(beanDefinition.getScope()) && clazz == beanDefinition.getBeanClass()) {
return (T) creatInstance(name, beanDefinition);
}
}
return null;
}
/**
* 扫描配置并注册bean定义
*/
private void scanConfig() {
// 获取要扫描的包名
ComponentScan componentScan = configClass.getAnnotation(ComponentScan.class);
String packageName = componentScan.value();
// 获取包名下的完整类名
List<String> fullClassNameList = parsePackageToFullClassNameList(packageName);
for (String className : fullClassNameList) {
try {
// 通过类名加载类
Class<?> aClass = DefaultAnnotationApplicationContext.class.getClassLoader().loadClass(className);
// 该类使用了 Component 注解
if (aClass.isAnnotationPresent(Component.class)) {
BeanDefinition beanDefinition = new BeanDefinition();
// 设置bean对应的类
beanDefinition.setBeanClass(aClass);
// 当前bean是后置处理器的实现类:当实现了BeanPostProcessor接口时
if (BeanPostProcessor.class.isAssignableFrom(aClass)) {
BEAN_POST_PROCESSORS.add((BeanPostProcessor) aClass.getDeclaredConstructor().newInstance());
}
// 懒加载
if (aClass.isAnnotationPresent(Lazy.class)) {
beanDefinition.setLazy(true);
}
// 判断是多例bean还是单例bean
if (aClass.isAnnotationPresent(Scope.class)) {
Scope scope = aClass.getAnnotation(Scope.class);
String scopeValue = scope.value();
if (scopeValue == null || "".equals(scopeValue) || SINGLETON.equals(scopeValue)) {
beanDefinition.setScope(SINGLETON);
}
// 多例bean
if (PROTOTYPE.equals(scopeValue)) {
beanDefinition.setScope(PROTOTYPE);
}
} else {
// 单例bean
beanDefinition.setScope(SINGLETON);
}
// 将 key=beanName,value=beanDefinition的映射存储到容器中
Component component = aClass.getAnnotation(Component.class);
String beanName = fixBeanName(component.value(), aClass);
BEAN_DEFINITION_MAP.put(beanName, beanDefinition);
}
} catch (ClassNotFoundException | NoSuchMethodException | InvocationTargetException | IllegalAccessException | InstantiationException e) {
e.printStackTrace();
}
}
}
/**
* 非懒加载、单例bean生成实例,注册到容器
*/
private void createNonLazySingletonBean() {
BEAN_DEFINITION_MAP.forEach((beanName, beanDefinition) -> {
// 非懒加载 并且是单例bean
if (!beanDefinition.isLazy() && SINGLETON.equals(beanDefinition.getScope())) {
Object instance = creatInstance(beanName, beanDefinition);
SINGLETON_MAP.put(beanName, instance);
}
});
}
/**
* 创建Bean
*
* @param beanDefinition bean定义
* @param beanName bean名称
* @return 实例bean
*/
private Object creatInstance(String beanName, BeanDefinition beanDefinition) {
Object instance = null;
Class<?> beanClass = beanDefinition.getBeanClass();
try {
instance = beanClass.getDeclaredConstructor().newInstance();
// 属性赋值之前处理
for (BeanPostProcessor beanPostProcessor : BEAN_POST_PROCESSORS) {
beanPostProcessor.postProcessBeforeInitialization(instance, beanName);
}
// 属性填充
Field[] declaredFields = beanClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
if (declaredField.isAnnotationPresent(Autowird.class)) {
Object fieldBean = getBean(declaredField.getName());
declaredField.setAccessible(true);
declaredField.set(instance, fieldBean);
}
}
// 设置beanName
if (instance instanceof BeanNameAware) {
((BeanNameAware) instance).setBeanName(beanName);
}
// 属性设置后,增加的 *** 作
if (instance instanceof InitializingBean) {
((InitializingBean) instance).afterPropertiesSet();
}
// bean后置处理里
for (BeanPostProcessor beanPostProcessor : BEAN_POST_PROCESSORS) {
beanPostProcessor.postProcessAfterInitialization(instance, beanName);
}
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
e.printStackTrace();
}
return instance;
}
/**
* 解析传入的包名,获取其下的所有的类名(包深度是20)
*
* @param packageName 包名
* @return 包名下的完整类名
*/
private List<String> parsePackageToFullClassNameList(String packageName) {
ClassLoader classLoader = DefaultAnnotationApplicationContext.class.getClassLoader();
// 获取资源文件路径
String path = packageName.replaceAll("\.", "/");
URL resource = classLoader.getResource(path);
// 解析当前的类路径
assert resource != null;
try {
// 获取包下的完整类名,文件深度为20
return Files.walk(Path.of(resource.toURI()), 20)
.map(Path::toFile)
.filter(file -> file.getName().endsWith(".class"))
.map(File::getAbsolutePath)
.map(filePath -> filePath.replaceAll("\\", "/"))
.map(filePath -> filePath.substring(filePath.indexOf(path), filePath.indexOf(".class")))
.map(filePath -> filePath.replaceAll("/", "."))
.collect(Collectors.toList());
} catch (IOException | URISyntaxException e) {
e.printStackTrace();
}
return Collections.emptyList();
}
/**
* 将类名首字母小写作为beanName的默认值
*
* @param beanName 实例在容器中的名称,可能为空
* @param aClass 当前实例的类
* @return 修正过的实例在容器中的名称
*/
private String fixBeanName(String beanName, Class<?> aClass) {
if (beanName == null || "".equals(beanName)) {
String simpleName = aClass.getSimpleName();
String firstLetter = simpleName.substring(0, 1);
return firstLetter.toLowerCase(Locale.ROOT) + simpleName.substring(1);
}
return beanName;
}
/**
* 校验注解 Configuration、ComponentScan 是否有在使用
*
* @param configClass 配置类
*/
private void check(Class<?> configClass) {
// 当前配置类必须有 Configuration注解
boolean isConfigClass = configClass.isAnnotationPresent(Configuration.class);
if (!isConfigClass) {
throw new RuntimeException("请给配置类上加 Configuration 注解");
}
// 当前配置类必须有 ComponentScan注解
boolean hasComponentScan = configClass.isAnnotationPresent(ComponentScan.class);
if (!hasComponentScan) {
throw new RuntimeException("请给配置类上加 ComponentScan 注解");
}
}
}
InitializingBean
package org.feng.framework;
/**
* 初始化bean,在给bean属性赋值之后,执行方法。
*
使用场景:在初始化后要做一些 *** 作时。多用于属性校验检查
*
* @version v1.0
* @author: fengjinsong
* @date: 2022年04月09日 18时26分
*/
public interface InitializingBean {
/**
* 在属性设置之后执行
*/
void afterPropertiesSet();
}
Lazy
package org.feng.framework;
import java.lang.annotation.*;
/**
* 标注一个懒加载的类
*
* @version v1.0
* @author: fengjinsong
* @date: 2022年04月09日 16时25分
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Lazy {
}
Scope
package org.feng.framework;
import java.lang.annotation.*;
/**
* 定义类在容器中是多例bean、单例bean
* 默认单例bean,标注value=prototype时,表示是一个多例bean
*
* @version v1.0
* @author: fengjinsong
* @date: 2022年04月09日 16时26分
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Scope {
String value() default "";
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)