接上一篇[探究spring的底层实现原理1
上一篇从理论到源码讲到了以下四点
BeanFactory
Bean的整个生命周期
Bean的属性填充
依赖注入
这节就切合上一篇,手写一个简易版spring的小demo,看看我是怎样去实现的java
<谨供参考>
- 应用程序上下文(启动类)
1
2
3ClassPathXmlApplicationContext:xml配置文件方式
AH8q3dGK2f2vLZVgbRfLTjQPySe2yRaJHs:注解方式
SpringApplication:SpringBoot方式
模拟注解方式启动
配置类,指定"spring"需要扫描的限定包路径
1
2
3
public class AppConfig {
}标注@Component的类则是需要被spring管理的
1
2
3
4
5
public [ ](https://my.oschina.net/u/996807) Component {
String value() default "";
}配置该Bean为单例/prototype
1
2
3
4
5
6
7
8
9/**
* @author 小五
*/
public Scope {
Mode value() default Mode.SINGLETON;
}BeanDefinition 描述了一个 Bean 实例,实例包含属性值、构造方法参数值以及更多实现信息.这里我放了俩参数,scope和claszz
1
2
3
4
5
6
7
8
9
10/**
* 同spring的BeanDefinition
* BeanDefinition 描述了一个 Bean 实例,实例包含属性值、构造方法参数值以及更多实现信息
*/
public class BeanDefinition {
private Class clazz;
private Mode scope;
}等同spring的BeanPostProcessor.在初始化bean前后使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28/**
* @author 小五
* @date 2021/4/18 21:24
*/
public class BeanPostProcessorImpl implements BeanPostProcessor {
public Object postProcessBeforeInitialization(Object bean, String beanName) {
if (beanName.equals("userService")){
((UserService)bean).setName("我是小五");
}
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName) {
if (beanName.equals("userService")) {
// jdk动态代理方式实现aop
Object proxyInstance = Proxy.newProxyInstance(BeanPostProcessorImpl.class.getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return method.invoke(bean,args);
}
});
return proxyInstance;
}
return bean;
}
}等同spring的InitializingBean
1
2
3
4
5
6
7
8/**
* @author 小五
* @description: 同spring的InitializingBean
* @date 2021/4/18 20:03
*/
public interface InitializingBean {
void afterPropertiesSet();
}主要代码代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126/**
* @author 小五
*/
public class AH8q3dGK2f2vLZVgbRfLTjQPySe2yRaJHs {
private Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(16);
// 单例池
private Map<String, Object> singleTonMap = new ConcurrentHashMap<>(16);
private List<BeanPostProcessor> beanPostProcessors = new ArrayList<>(16);
public AH8q3dGK2f2vLZVgbRfLTjQPySe2yRaJHs(Class configClazz) throws Exception {
/**
* 1. 获取AppConfig上ComponentScan的value值(路径)
* 2. 用classlocader获取路径下所有类
* 3. 遍历所有类,判断哪些是被@Component标注(即需被注入容器)
* 4. 判断当前bean是否是单例的,如果是,创建完放到singleTonMap中(单例池)
*/
if (configClazz.isAnnotationPresent(ComponentScan.class)) {
ComponentScan componentScan = (ComponentScan) configClazz.getDeclaredAnnotation(ComponentScan.class);
String path = componentScan.value();
ClassLoader classLoader = AH8q3dGK2f2vLZVgbRfLTjQPySe2yRaJHs.class.getClassLoader();
String filePath = StrUtil.replace(path, ".", "/");
// 绝对路径
URL url = classLoader.getResource(filePath);
List<String> recursiveFiles = new ArrayList<>();
// 递归查找该路径下所有类文件
RecursiveFileUtils.recursiveFiles(url.getFile(),recursiveFiles);
// 获取@Component的扫描路径
for (String absolutePath : recursiveFiles) {
String subPath = StrUtil.sub(absolutePath, absolutePath.indexOf(path), absolutePath.lastIndexOf(".class"));
Class<?> aClass = classLoader.loadClass(subPath);
// 判读是否标注@Component(是否需要被咱们"spring"管理)
if (aClass.isAnnotationPresent(Component.class)) {
// 如果BeanPostProcessor与aClass表示的类或接口相同,或者是参数aClass表示的类或接口的父类,则返回true。
if (BeanPostProcessor.class.isAssignableFrom(aClass)){
// todo 此创建BeanPostProcessor的方法不严谨,待改善
BeanPostProcessor beanPostProcessor = (BeanPostProcessor) aClass.getDeclaredConstructor().newInstance();
beanPostProcessors.add(beanPostProcessor);
}
Component componentAnnotation = aClass.getDeclaredAnnotation(Component.class);
// value为空则取类名作为beanName
String beanName = StrUtil.isEmpty(componentAnnotation.value()) ? StrUtil.lowerFirst(aClass.getSimpleName()) : componentAnnotation.value();
BeanDefinition beanDefinition = new BeanDefinition();
beanDefinition.setClazz(aClass);
// 判断是单例还是原型,默认是单例的
if (aClass.isAnnotationPresent(Scope.class)) {
Scope scopeAnnotation = aClass.getDeclaredAnnotation(Scope.class);
beanDefinition.setScope(scopeAnnotation.value());
} else {
beanDefinition.setScope(Mode.SINGLETON);
}
beanDefinitionMap.put(beanName, beanDefinition);
}
}
// 判断是否需要放到单例池
for (String beanName : beanDefinitionMap.keySet()) {
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
if (beanDefinition.getScope() == Mode.SINGLETON) {
// 二次判断,如果单例池已经有了,说明该bean有被其他bean依赖
Object bean = singleTonMap.get(beanName);
if (!Optional.ofNullable(bean).isPresent()){
bean = createBean(beanName,beanDefinition);
singleTonMap.put(beanName, bean);
}
}
}
} else {
throw new RuntimeException("未被标注");
}
}
private Object createBean(String beanName,BeanDefinition beanDefinition) {
try {
// 实例化
Class clazz = beanDefinition.getClazz();
Object newInstance = clazz.getDeclaredConstructor().newInstance();
// 属性填充
// todo 遍历当前bean的所有依赖对象,并判断是byname还是bytype等,这里先基于byname
for (Field declaredField : clazz.getDeclaredFields()) {
if (declaredField.isAnnotationPresent(Autowired.class)) {
Object bean = getBean(declaredField.getName());
if (!Optional.ofNullable(bean).isPresent()){
throw new RuntimeException("getBean "+beanName+" 错误");
}
declaredField.setAccessible(true);
declaredField.set(newInstance, bean);
}
}
// todo 一堆Aware接口方法
// 初始化bean之前
for (BeanPostProcessor beanPostProcessor : beanPostProcessors) {
beanPostProcessor.postProcessBeforeInitialization(newInstance,beanName);
}
// 初始化bean
if (newInstance instanceof InitializingBean){
((InitializingBean)newInstance).afterPropertiesSet();
}
// 初始化bean之后
for (BeanPostProcessor beanPostProcessor : beanPostProcessors) {
beanPostProcessor.postProcessAfterInitialization(newInstance,beanName);
}
singleTonMap.put(beanName, newInstance);
return newInstance;
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
e.printStackTrace();
}
return null;
}
public Object getBean(String beanName) {
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
if (beanDefinition != null) {
if (beanDefinition.getScope() == Mode.SINGLETON) {
Object bean = singleTonMap.get(beanName);
return Optional.ofNullable(bean).isPresent()?bean:createBean(beanName,beanDefinition);
} else {
return createBean(beanName,beanDefinition);
}
}
throw new RuntimeException("未找到当前bean对象");
}
}
测试一下看看
1 | /** |
源码仓库地址: 简易版spring demo
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 小五的个人杂货铺!