Spring系列文章目录
第一章 手写Spring
前言
本篇文章是围绕AnnotationConfigApplicationContext加载的spring当中bean的生命周期过程,所有注解,类都可以在Spring当中找到对应的类。
一、代码主体结构
二、spring代码
- pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.lotus</groupId>
<artifactId>handle-write-spring</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
</plugins>
</build>
<name>Maven</name>
<inceptionYear>2001</inceptionYear>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
- Autowired
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 {
}
- Component
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 "";
}
- ComponentScan
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 "";
}
- Scope
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 "";
}
- BeanNameAware
public interface BeanNameAware {
void setBeanName(String name);
}
- BeanPostProcessor
public interface BeanPostProcessor {
default Object postProcessBeforeInitialization(Object bean, String beanName) {
return bean;
}
default Object postProcessAfterInitialization(Object bean, String beanName) {
return bean;
}
}
- InitializingBean
public interface InitializingBean {
void afterPropertiesSet();
}
- AppConfig
/**
* 声明扫描
**/
@ComponentScan("com.lotus.demo")
public class AppConfig {
}
- BeanDefinition
public class BeanDefinition {
private Class<?> type;
private String scope;
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;
}
}
- AnnotationConfigApplicationContext
import java.beans.Introspector;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* 模拟spring 注解启动上下文
**/
public class AnnotationConfigApplicationContext {
private Class<?> appConfig;
private ConcurrentHashMap<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>();
private ConcurrentHashMap<String, Object> singletonObjects = new ConcurrentHashMap<>();
private List<BeanPostProcessor> beanPostProcessorList = new ArrayList<>();
public AnnotationConfigApplicationContext(Class<?> appConfig) {
this.appConfig = appConfig;
scanConfig(appConfig);
// 将扫描到的BeanDefinition判断属性是否放入到单例
for (Map.Entry<String, BeanDefinition> definitionEntry : beanDefinitionMap.entrySet()) {
String beanName = definitionEntry.getKey();
BeanDefinition definition = definitionEntry.getValue();
if (definition.getScope().equals("singleton")) {
singletonObjects.put(beanName, createBean(beanName, definition));
}
}
}
/**
* 扫描配置的包路径
**/
private void scanConfig(Class<?> appConfig) {
if (appConfig.isAnnotationPresent(ComponentScan.class)) {
ComponentScan componentScan = appConfig.getAnnotation(ComponentScan.class);
String componentScanVal = componentScan.value();
System.out.println("spring 获取ComponentScan定义扫描路径: " + componentScanVal);
ClassLoader classLoader = AnnotationConfigApplicationContext.class.getClassLoader();
componentScanVal = componentScanVal.replace(".", "/");
URL resource = classLoader.getResource(componentScanVal);
File file = new File(resource.getFile());
loadFile(classLoader, file);
}
}
/**
* 加载文件
**/
private void loadFile(ClassLoader classLoader, File file) {
if (file.isDirectory()) {
for (File listFile : file.listFiles()) {
// 如果为文件夹则递归
if (listFile.isDirectory()) {
loadFile(classLoader, listFile);
}
String absolutePath = listFile.getAbsolutePath();
if (absolutePath.lastIndexOf(".class") == -1) {
continue;
}
absolutePath = absolutePath.substring(absolutePath.indexOf("com"), absolutePath.indexOf(".class")).replace("\\", ".");
try {
Class<?> loadClass = classLoader.loadClass(absolutePath);
// 查看类上是否有注解 标明这是一个bean
if (loadClass.isAnnotationPresent(Component.class)) {
// 对于通过实现BeanPostProcessor的bean单独放到一个list当中保存
if (BeanPostProcessor.class.isAssignableFrom(loadClass)) {
BeanPostProcessor instance = (BeanPostProcessor) loadClass.getConstructor().newInstance();
beanPostProcessorList.add(instance);
}
Component component = loadClass.getAnnotation(Component.class);
String beanName = component.value();
// 获取bean的名称 如果赋值则取赋值的名称,否则取类名第一个单词小写的名称
beanName = beanName == null || "".equals(beanName) ? Introspector.decapitalize(loadClass.getSimpleName()) : beanName;
// 构造beanDefinition后续加载bean
BeanDefinition beanDefinition = new BeanDefinition();
beanDefinition.setType(loadClass);
if (loadClass.isAnnotationPresent(Scope.class)) {
Scope scope = loadClass.getAnnotation(Scope.class);
String scopeVal = scope.value();
beanDefinition.setScope(scopeVal);
} else {
beanDefinition.setScope("singleton");
}
beanDefinitionMap.put(beanName, beanDefinition);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
}
}
/**
* 从 beanDefinitionMap 获取单例bean 或者 原型bean
**/
public Object getBean(String beanName) {
if (!beanDefinitionMap.containsKey(beanName)) {
throw new NullPointerException();
}
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
String scope = beanDefinition.getScope();
Object singletonBean = null;
if ("singleton".equals(scope)) {
singletonBean = singletonObjects.get(beanName);
singletonObjects.put(beanName, singletonBean);
} else {
singletonBean = createBean(beanName, beanDefinition);
}
return singletonBean;
}
/**
* 通过beanDefinition创建bean实例,同时加载bean的生命周期
**/
private Object createBean(String beanName, BeanDefinition beanDefinition) {
Object instance = null;
Class<?> clazz = beanDefinition.getType();
try {
instance = clazz.getConstructor().newInstance();
for (Field field : clazz.getDeclaredFields()) {
if (field.isAnnotationPresent(Autowired.class)) {
field.setAccessible(true);
field.set(instance, getBean(beanName));
}
}
if (instance instanceof BeanNameAware) {
((BeanNameAware) instance).setBeanName(beanName);
}
for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
instance = beanPostProcessor.postProcessBeforeInitialization(instance, beanName);
}
if (instance instanceof InitializingBean) {
((InitializingBean) instance).afterPropertiesSet();
}
for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
instance = beanPostProcessor.postProcessAfterInitialization(instance, beanName);
}
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return instance;
}
}
三、测试代码
- UserService
public interface UserService {
void test();
}
- OrderService
import com.lotus.spring.BeanNameAware;
import com.lotus.spring.BeanPostProcessor;
import com.lotus.spring.Component;
import com.lotus.spring.InitializingBean;
@Component
public class OrderService implements BeanNameAware, BeanPostProcessor, InitializingBean {
private String beanName;
@Override
public void setBeanName(String name) {
System.out.println("spring-->初始化前优先设置bean名称" + name);
this.beanName = name;
}
@Override
public void afterPropertiesSet() {
System.out.println("spring-->初始化bean,此时bean的名称:" + beanName);
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
System.out.println("spring-->初始化bean之前,做的事" + beanName);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
System.out.println("spring-->初始化bean之后,做的事" + beanName);
return bean;
}
}
- UserServiceImpl
@Component
public class UserServiceImpl implements UserService {
public void test() {
System.out.println("==============");
}
}
四、测试类
- DemoTest
import com.lotus.demo.service.impl.UserServiceImpl;
import com.lotus.spring.AnnotationConfigApplicationContext;
import com.lotus.spring.AppConfig;
public class DemoTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
UserServiceImpl userServiceImpl = (UserServiceImpl) applicationContext.getBean("userServiceImpl");
userServiceImpl.test();
}
}
- 执行结果如图所示
源码地址:https://gitee.com/zengzheng-pro/handle-write-spring.git
总结
以上就是简单实现手写Spring的过程,主要包含了扫描包路径,创建单例bean和原型bean,bean生命周期较为重要的几个阶段。