02-手写模拟Spring底层原理

注意包名 看哪些是属于Spring源码中(package com.spring;) 哪些是应用spring的(package com.zhouyu;)

程序入口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.zhouyu;

import com.spring.ZhouyuApplicationContext;
import com.zhouyu.service.UserInterface;
import com.zhouyu.service.UserService;

public class Test {

public static void main(String[] args) {

// 扫描--->创建单例Bean BeanDefinition BeanPostPRocess
ZhouyuApplicationContext applicationContext = new ZhouyuApplicationContext(AppConfig.class); //创建 spring容器

UserInterface userService = (UserInterface) applicationContext.getBean("userService");
userService.test();
}
}

AppConfig.class 所需要传入配置文件

1
2
3
4
5
6
7
8
package com.zhouyu;

import com.spring.ComponentScan;


@ComponentScan("com.zhouyu.service")
public class AppConfig {
}

ComponentScan注解

1
2
3
4
5
6
7
8
9
10
11
12
13
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 "";
}

注解@Target和@Retention可以用来修饰注解,是注解的注解,称为元注解。

@Target : Target翻译中文为目标,即该注解可以声明在哪些目标元素之前,也可理解为注释类型的程序元素的种类。

ElementType.TYPE:该注解只能声明在一个类前。

ElementType.METHOD:该注解只能声明在一个类的方法前。

ElementType.FIELD:该注解只能声明在一个类的字段前。

@Retention :Retention 翻译成中文为保留,可以理解为如何保留,即告诉编译程序如何处理,也可理解为注解类的生命周期。

RetentionPolicy.SOURCE : 注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃;

RetentionPolicy.CLASS : 注解被保留到class文件,但jvm加载class文件时候被遗弃,这是默认的生命周期;

RetentionPolicy.RUNTIME : 注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在;

这3个生命周期分别对应于:Java源文件(.java文件) —> .class文件 —> 内存中的字节码。
那怎么来选择合适的注解生命周期呢?
首先要明确生命周期长度 SOURCE < CLASS < RUNTIME ,所以前者能作用的地方后者一定也能作用。

ApplicationContext

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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
package com.spring;

import com.zhouyu.service.ZhouyuBeanPostProcessor;

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 ZhouyuApplicationContext {

private Class configClass;
private Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>(); //scan扫描里
private Map<String, Object> singletonObjects = new HashMap<>(); //创建bean 放入单例池
private List<BeanPostProcessor> beanPostProcessorList = new ArrayList<>();

public ZhouyuApplicationContext(Class configClass) {
this.configClass = configClass;

// 扫描
scan(configClass);

for (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();

Object instance = null;
try {

instance = clazz.getConstructor().newInstance();

for (Field field : clazz.getDeclaredFields()) {
if (field.isAnnotationPresent(Autowired.class)) {

field.setAccessible(true);

field.set(instance, getBean(field.getName())); //依赖注入 注入bean
}
}

if (instance instanceof BeanNameAware) { //aware回调
((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;
}



public Object getBean(String beanName) {

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;
}

}


private void scan(Class configClass) {
if (configClass.isAnnotationPresent(ComponentScan.class)) { //configClass类上是否有componentscan注解
ComponentScan componentScanAnnotation = (ComponentScan) configClass.getAnnotation(ComponentScan.class); //获取这个注解类
String path = componentScanAnnotation.value(); //拿到注解类中的值 即扫描路径
path = path.replace(".", "/"); // com/zhouyu/service

ClassLoader classLoader = ZhouyuApplicationContext.class.getClassLoader();
//其中classLoader为类加载器对象,在java种类加载器分为3大类,根类加载器、扩展类加载器、应用类加载器,每一个类加载 都有自己对应的ucp变量,该变量存储了类的路径。
//根类加载器的ucp变量,存储了 java/jre/lib下的jar包路径
//扩展类加载器 ,存储了java/jre/lib/ext 下的jar包路径
//应用类加载器,存储了编译后的class路径以及引用的jar包路径 此处是应用类加载器
URL resource = classLoader.getResource(path);
File file = new File(resource.getFile());

if (file.isDirectory()) {
for (File f : file.listFiles()) {
String absolutePath = f.getAbsolutePath();

absolutePath = absolutePath.substring(absolutePath.indexOf("com"), absolutePath.indexOf(".class"));
absolutePath = absolutePath.replace("\\", ".");


try {
Class<?> clazz = classLoader.loadClass(absolutePath); //加载类

if (clazz.isAnnotationPresent(Component.class)) {

if (BeanPostProcessor.class.isAssignableFrom(clazz)) {
//是否实现BeanPostProcessor接口
BeanPostProcessor instance = (BeanPostProcessor) clazz.getConstructor().newInstance();
beanPostProcessorList.add(instance);
}

Component componentAnnotation = clazz.getAnnotation(Component.class);
String beanName = componentAnnotation.value();
if ("".equals(beanName)) {
beanName = Introspector.decapitalize(clazz.getSimpleName());
//设置默认bean的名字
}

BeanDefinition beanDefinition = new BeanDefinition(); //bean定义
beanDefinition.setType(clazz);

if (clazz.isAnnotationPresent(Scope.class)) {
Scope scopeAnnotation = clazz.getAnnotation(Scope.class);
String value = scopeAnnotation.value();
beanDefinition.setScope(value);
} else {
beanDefinition.setScope("singleton");
}

beanDefinitionMap.put(beanName, beanDefinition);
}
} catch (ClassNotFoundException | NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}


}
}



}
}
}

Autowired注解

1
2
3
4
5
6
7
8
9
10
11
12
13
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 {


}

Component注解

1
2
3
4
5
6
7
8
9
10
11
12
13
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 "";
}

BeanPostProcessor 后置处理器接口

1
2
3
4
5
6
7
8
9
10
11
12
package com.spring;

public interface BeanPostProcessor {

default Object postProcessBeforeInitialization(Object bean, String beanName) {
return bean;
}

default Object postProcessAfterInitialization(Object bean, String beanName) {
return bean;
}
}

BeanDefinition类

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
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;
}
}

InitializingBean接口

1
2
3
4
5
package com.spring;

public interface InitializingBean {
void afterPropertiesSet();
}

Scope注解

1
2
3
4
5
6
7
8
9
10
11
12
13
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 "";
}

BeanNameAware Aware回调接口

1
2
3
4
5
6
package com.spring;

public interface BeanNameAware {

void setBeanName(String name);
}

应用所写spring

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
package com.zhouyu.service;

import com.spring.*;

@Component
public class UserService implements UserInterface, BeanNameAware {

@Autowired
private OrderService orderService;

@ZhouyuValue("xxx")
private String test;


private String beanName;

@Override
public void setBeanName(String name) {
this.beanName = name;
}

public void test() {
System.out.println(beanName);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
package com.zhouyu.service;

import com.spring.Component;


@Component
public class OrderService {

public void test() {
System.out.println("test");
}
}

jdk动态代理需要

1
2
3
4
5
6
package com.zhouyu.service;

public interface UserInterface {

public void test();
}

实现AOP

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
package com.zhouyu.service;

import com.spring.BeanPostProcessor;
import com.spring.Component;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

@Component
public class ZhouyuBeanPostProcessor implements BeanPostProcessor {

@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {

if (beanName.equals("userService")) {
Object proxyInstance = Proxy.newProxyInstance(ZhouyuBeanPostProcessor.class.getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 切面
System.out.println("切面逻辑");

return method.invoke(bean, args);
}
});

return proxyInstance;
}

// bean
return bean;
}
}

自定义注解

1
2
3
4
5
6
7
8
9
10
11
12
13
package com.zhouyu.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 ZhouyuValue {

String value() default "";
}

应用自定义注解

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
package com.zhouyu.service;

import com.spring.BeanPostProcessor;
import com.spring.Component;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

@Component
public class ZhouyuValueBeanPostProcessor implements BeanPostProcessor {

@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {

for (Field field : bean.getClass().getDeclaredFields()) {
if (field.isAnnotationPresent(ZhouyuValue.class)) {
field.setAccessible(true);
try {
field.set(bean, field.getAnnotation(ZhouyuValue.class).value());
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}

// bean
return bean;
}
}