主要方向
- 了解Spring底层源码的启动过程
- 了解BeanDefinition、BeanPostProcessor的概念
- 了解Spring解析配置类等底层源码工作流程
- 了解依赖注入、Aware回调等底层源码工作流程
-
大致实现生命周期
类通过无参构造实例化
- 依赖注入
- Aware接口回调
- 初始化前: 实现BeanPostProcessor.postProcessBeforeInitialization
- 初始化前: 调用@PostConstruct注解的方法
- 初始化: 实现InitializingBean.afterPropertiesSet
- 初始化后: 实现BeanPostProcessor.postProcessAfterInitialization
- 初始化后: BeanPostProcessor(Aop—>代理对象)
-
手写模拟Spring
前期准备
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Component {
String name() default "";
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ComponentScan {
String[] basePackages() default {};
}
@Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD, ElementType.METHOD}) public @interface Autowired { }
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface Scope { String value() default "singleton"; }
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface PostConstruct { }
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface Value { String value() default ""; }
```java public class BeanDefinition {
private Class<?> clazz; /**
- 作用域: singleton
- prototype */ private String scope;
public Class<?> getClazz() {
return clazz;
}
public void setClazz(Class<?> clazz) {
this.clazz = clazz;
}
public String getScope() {
return scope;
}
public void setScope(String scope) {
this.scope = scope;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
BeanDefinition that = (BeanDefinition) o;
return Objects.equals(clazz, that.clazz) && Objects.equals(scope, that.scope);
}
@Override
public int hashCode() {
return Objects.hash(clazz, scope);
}
}
```java
public interface BeanPostProcessor {
/**
* 该方法在bean实例化完毕(且已经注入完毕),在afterPropertiesSet或自定义init方法执行之前
*/
default Object postProcessBeforeInitialization(Object bean, String beanName) {
return bean;
}
/**
* 在afterPropertiesSet或自定义init方法执行之后
*/
default Object postProcessAfterInitialization(Object bean, String beanName) {
return bean;
}
}
public interface InitializingBean {
void afterPropertiesSet();
}
public interface BeanNameAware {
void setBeanName(String beanName);
}
实现包扫描逻辑
public class AnnotationConfigApplicationContext {
/**
* 配置类
*/
private final Class<?> configClass;
/**
* key:beanName, value:BeanDefinition
* 专门用来存储扫描到的BeanDefinition
*/
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
/**
* 继承了BeanPostProcessor的类
*/
private final List<BeanPostProcessor> beanPostProcessorList = new ArrayList<>();
/**
* 扫描到的class文件
*/
private final List<File> scannedFiles = new ArrayList<>();
/**
* 单例池
*/
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
public AnnotationConfigApplicationContext(Class<?> configClass) {
this.configClass = configClass;
// 进行包扫描
scan(configClass);
}
/**
* 扫描包路径下加了@Component注解的放到beanDefinitionMap
*/
private void scan(Class<?> configClass) {
// 如果配置类加上了@ComponentScan
if (configClass.isAnnotationPresent(ComponentScan.class)) {
// 从注解上拿到需要扫描的包路径basePackages
ComponentScan componentScan = configClass.getAnnotation(ComponentScan.class);
String[] basePackages = componentScan.basePackages();
// 遍历包路径,通过io去拿到所有class文件
for (String basePackage : basePackages) {
// 扫描包
// 找到包路径下的所有class,解析class得到BeanDefinition
scanCandidateComponents(basePackage);
}
}
}
/**
* 扫描包路径下的class文件并且解析,如果有@Component就进行解析成BeanDefinition
*/
private void scanCandidateComponents(String basePackage) {
// 获取包路径下的文件
// 判断当前是否是目录,如果是目录就递归去获取class文件,这里我们需要把这些扫描到的class文件保存下来
listPackageFiles(getPackageFile(basePackage));
// 遍历扫描到的文件找出class文件,判断class文件中有没有@Component,如果有就看是单例还是原型的
composeBeanDefinition(scannedFiles);
}
/**
* 构建BeanDefinition
*/
private void composeBeanDefinition(List<File> scannedFiles) {
// 遍历扫描到的文件找出class文件
for (File f : scannedFiles) {
// 获取f的绝对路径
String absolutePath = f.getAbsolutePath();
// 判断是否是class文件
if (absolutePath.contains(".class")) {
// 根据不同操作系统,获取指定的二进制名称
String binaryName = getBinaryName(absolutePath);
try {
// 通过当前类加载器加载二进制名称
Class<?> clazz = this.getClass().getClassLoader().loadClass(binaryName);
// 判断该类是否有@Component
if (clazz.isAnnotationPresent(Component.class)) {
// 这里我们要考虑判断有没有继承BeanPostProcessor,如果有那么就把这些类放到beanPostProcessorList里缓存下来
if (BeanPostProcessor.class.isAssignableFrom(clazz)) {
BeanPostProcessor beanPostProcessor = (BeanPostProcessor) clazz.getConstructor().newInstance();
beanPostProcessorList.add(beanPostProcessor);
}
// 拿到当前类的@Component的注解信息beanName
Component component = clazz.getAnnotation(Component.class);
String beanName = component.name();
// 如果beanName不填写,就默认用类名生成小写
if ("".equals(beanName)) {
beanName = Introspector.decapitalize(clazz.getSimpleName());
}
BeanDefinition beanDefinition = new BeanDefinition();
beanDefinition.setClazz(clazz);
// 判断bean是否是单例的,如果有值就按照传递的否则按照单例默认值进行
if (clazz.isAnnotationPresent(Scope.class)) {
Scope scope = clazz.getAnnotation(Scope.class);
beanDefinition.setScope(scope.value());
} else {
// 默认使用singleton
beanDefinition.setScope("singleton");
}
// 将beanDefinition放入beanDefinitionMap
beanDefinitionMap.put(beanName, beanDefinition);
}
} catch (ClassNotFoundException | NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
/**
* 根据不同操作系统,获取指定的二进制名称
*/
private String getBinaryName(String absolutePath, boolean isMaven) {
String os = System.getProperty("os.name");
String path;
if (isMaven) {
if (os.startsWith("Windows")) {
path = "target\\classes";
absolutePath = absolutePath.substring(absolutePath.indexOf(path) + path.length() + 1, absolutePath.indexOf(".class"));
absolutePath = absolutePath.replace("\\", ".");
} else {
path = "target/classes";
absolutePath = absolutePath.substring(absolutePath.indexOf(path) + path.length() + 1, absolutePath.indexOf(".class"));
absolutePath = absolutePath.replace("/", ".");
}
} else {
// gradle
if (os.startsWith("Windows")) {
path = "out\\production\\classes";
absolutePath = absolutePath.substring(absolutePath.indexOf(path) + path.length() + 1, absolutePath.indexOf(".class"));
absolutePath = absolutePath.replace("\\", ".");
} else {
path = "out/production/classes";
absolutePath = absolutePath.substring(absolutePath.indexOf(path) + path.length() + 1, absolutePath.indexOf(".class"));
absolutePath = absolutePath.replace("/", ".");
}
}
return absolutePath;
}
/**
* 列举出file下的所有class文件
*/
private void listPackageFiles(File file) {
// 判断当前是否是目录
if (file.isDirectory()) {
File[] files = file.listFiles();
assert files != null;
if (files.length == 0) {
return;
}
for (File f : files) {
scannedFiles.add(f);
// 判断当前是否是目录
if (f.isDirectory()) {
// 继续递归获取f下的class文件
listPackageFiles(f);
}
}
}
}
/**
* 获取包路径下的文件
*/
private File getPackageFile(String basePackage) {
// 这里想到我们指定的路径linc.cool,我们要转变成linc/cool,所以需要替换
String path = basePackage.replace(".", "/");
// 通过类加载器去获取path路径下的文件
URL resource = this.getClass().getClassLoader().getResource(path);
assert resource != null;
return new File(resource.getFile());
}
}
实现创建Bean
/**
* 获取Bean
*/
public Object getBean(String beanName) {
// 判断这个beanName在beanDefinitionMap中是否存在
if (!beanDefinitionMap.containsKey(beanName)) {
throw new NullPointerException(String.format("%s不存在", beanName));
}
// 存在就拿出beanDefinition
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
// 如果是单例就返回单例池中的对象,否则返回新的实例
if ("singleton".equals(beanDefinition.getScope())) {
Object singletonBean = singletonObjects.get(beanName);
// 如果没有就进行创建单例Bean
if (singletonBean == null) {
singletonBean = createBean(beanName, beanDefinition);
singletonObjects.put(beanName, singletonBean);
}
return singletonBean;
}
// 原型Bean就直接创建
return createBean(beanName, beanDefinition);
}
/**
* 创建Bean
*/
private Object createBean(String beanName, BeanDefinition beanDefinition) {
Class<?> beanClass = beanDefinition.getClazz();
try {
Object bean = beanClass.getConstructor().newInstance();
// 如果对象有属性加了@Autowired注解的,就给它进行赋值
for (Field f : beanClass.getDeclaredFields()) {
if (f.isAnnotationPresent(Autowired.class)) {
f.setAccessible(true);
// 去单例池中找Bean,如果没有就创建
f.set(bean, getBean(f.getName()));
}
}
// Aware回调接口
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
// 初始化前: 实现BeanPostProcessor.postProcessBeforeInitialization
for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
bean = beanPostProcessor.postProcessBeforeInitialization(bean, beanName);
}
// 初始化前: 调用@PostConstruct注解的方法
for (Method method : beanClass.getDeclaredMethods()) {
if (method.isAnnotationPresent(PostConstruct.class)) {
method.setAccessible(true);
method.invoke(bean);
}
}
// 初始化: 实现InitializingBean.afterPropertiesSet
if (bean instanceof InitializingBean) {
((InitializingBean) bean).afterPropertiesSet();
}
// 初始化后: 实现BeanPostProcessor.postProcessAfterInitialization
for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
bean = beanPostProcessor.postProcessAfterInitialization(bean, beanName);
}
// 初始化后: BeanPostProcessor(Aop-->代理对象)
return bean;
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
/**
* 注册单例beanDefinition到单例池
*/
private void registerBean() {
for (Map.Entry<String, BeanDefinition> entry : beanDefinitionMap.entrySet()) {
String beanName = entry.getKey();
BeanDefinition beanDefinition = entry.getValue();
// 如果是单例我们就创建bean,放到单例池
if ("singleton".equals(beanDefinition.getScope())) {
singletonObjects.put(beanName, createBean(beanName, beanDefinition));
}
}
}
实现@Value的填充功能
@Component
public class ValueAnnotationBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
// 遍历所有field,判断是否加了@Value,有就进行填充
Stream.of(bean.getClass().getDeclaredFields()).forEach(field -> {
if (field.isAnnotationPresent(Value.class)) {
String value = field.getAnnotation(Value.class).value();
// 如果是字符串,就进行填充
if (!"".equals(value)) {
try {
field.setAccessible(true);
field.set(bean, field.getAnnotation(Value.class).value());
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
});
return bean;
}
}
目前我们只是实现了填充字符串的功能,怎么实现@Value的依赖注入的功能呢? 这部分逻辑和@Autowired实现很相似
// 如果对象有属性加了@Autowired注解的,就给它进行赋值
for (Field f : beanClass.getDeclaredFields()) {
if (f.isAnnotationPresent(Autowired.class)) {
f.setAccessible(true);
// 去单例池中找Bean,如果没有就创建
f.set(bean, getBean(f.getName()));
} else if (f.isAnnotationPresent(Value.class)) {
String value = f.getAnnotation(Value.class).value();
if ("".equals(value)) {
f.setAccessible(true);
// 去单例池中找Bean,如果没有就创建
f.set(bean, getBean(f.getName()));
}
}
}