banner
不断学习,不断进步

spring框架源码学习

Scroll down

spring框架源码学习

spring源码模仿

创建spring容器准备工作

创建spring容器,用创建spring容器里的api

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class MockKingJayApplication {

private Class configClass;

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

//解析配置类
}

public Object getBean(String beanName){
return null;
}
}

定义ComponentScan注解

1
2
3
4
5
6
7
8
9
//@Retention是用来修饰注解的,它定义了该注解被保留时间的长短,是注解的注解,是JAVA元注解之一。(在.class被装载时将被读取,在程序运行期间,将一直保留。)
@Retention(RetentionPolicy.RUNTIME)
//@Target说明了Annotation所修饰的对象范围
@Target(ElementType.TYPE)
public @interface ComponentScan {

String value();
}

定义Component注解

1
2
3
4
5
6
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Component {

String value() default "";
}

测试类创建

  • Uservice

    1
    2
    3
    4
    @Component("userService")
    public class UserService {

    }
  • AppConfig

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    /**
    * @author mockingjay
    * @date 2023/4/29 - 23:48
    * 模拟spring配置文件
    */
    @ComponentScan("com.mockingjay.service")
    public class AppConfig {


    }
  • Test

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public class Test {


    public static void main(String[] args) {

    MockKingJayApplication mockKingJayApplication=new MockKingJayApplication(AppConfig.class);

    Object userService = mockKingJayApplication.getBean("userService");

    }
    }

扫描逻辑模拟实现

要判断是否有ComponentScan注解

1
2
//判断是否有ComponentScan注解
ComponentScan componentScan=(ComponentScan) configClass.getDeclaredAnnotation(ComponentScan.class);

扫描路径(这里为com.mockingjay.service)

1
String path=componentScan.value();

扫描该路径下所有带component注解的类,如果有,则说明该类是一个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
29
30
31
32
33
34
35
36
37
public MockKingJayApplication(Class configClass){
this.configClass=configClass;

//1.解析配置类
//ComponentScan注解-->扫描路径-->扫描
//判断是否有ComponentScan注解
ComponentScan componentScan=(ComponentScan) configClass.getDeclaredAnnotation(ComponentScan.class);
//扫描路径
String path=componentScan.value();
//扫描
//类加载器
//1.bootstrap-->jre/-lib 2.ext-->jre/ext/lib 3.app-->classpath
ClassLoader classLoader=MockKingJayApplication.class.getClassLoader();
URL resource = classLoader.getResource(path.replace(".","/"));
File file=new File(resource.getFile());
if(file.isDirectory()){
File[] files = file.listFiles();
for (File f : files) {

String fileName=f.getAbsolutePath();
if(fileName.endsWith(".class")){
String packageName=fileName.substring(fileName.indexOf("com"),fileName.indexOf(".class")).
replace("\\" ,".");
Class<?> clazz = null;
try {
clazz = classLoader.loadClass(packageName);
if(clazz.isAnnotationPresent(Component.class)){
//表示当前的类是一个bean
//todo
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
}

创建scope注解(模仿spring单例bean和原型bean)

1
2
3
4
5
6
7
8
9
10
11
12
/**
* @author mockingjay
* @date 2023/5/2 - 23:49
* 模仿单例bean还是原型bean
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Scope {

String value();
}

beanDefinition过程(spring重要概念):

解析类 – >beanDefinition(bean的一些属性 )

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class BeanDefinition {

private Class clazz;

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

创建单例池和beanDefinition池(单例bean不是单例模式,一个容器中可能有多个该类型的bean(使用bean注解)):

1
2
3
//单例池
private ConcurrentHashMap<String,Object> singletonObjectsMap=new ConcurrentHashMap<>();
private ConcurrentHashMap<String,BeanDefinition> beanDefinitionObjectsMap=new ConcurrentHashMap<>();

逻辑实现如下(扫描路径下所有带component注解,如果有这个注解,说明这是一个bean,之后创建BeanDefinition对象,如果该对象没有scope注解,则为单例(创建一次不会创建第二次),如果有则获取scope注解里的值放入beanDefiniton对象中,之后将创建好的beanDefiniton放入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
33
34
if(file.isDirectory()){
File[] files = file.listFiles();
for (File f : files) {

String fileName=f.getAbsolutePath();
if(fileName.endsWith(".class")){
String packageName=fileName.substring(fileName.indexOf("com"),fileName.indexOf(".class")).
replace("\\" ,".");
Class<?> clazz = null;
try {
clazz = classLoader.loadClass(packageName);
if(clazz.isAnnotationPresent(Component.class)){
//表示当前的类是一个bean
//解析bean,判断当前bean是单例bean,还是prototype bean
BeanDefinition beanDefinition=new BeanDefinition();

Component ComponentAnnotation = clazz.getDeclaredAnnotation(Component.class);
String beanName=ComponentAnnotation.value();

if(clazz.isAnnotationPresent(Scope.class)){
Scope scopeAnnotation=clazz.getDeclaredAnnotation(Scope.class);
beanDefinition.setScope(scopeAnnotation.value());
}else {
beanDefinition.setScope("singleton");
}
beanDefinition.setClazz(clazz);
beanDefinitionObjectsMap.put(beanName,beanDefinition);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}

将扫描方法提取成一个方法

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
private void scan(Class configClass) {
//ComponentScan注解-->扫描路径-->扫描-->beanDefinition-->beanDefinitionObjectsMap
//判断是否有ComponentScan注解
ComponentScan componentScan=(ComponentScan) configClass.getDeclaredAnnotation(ComponentScan.class);
//扫描路径
String path=componentScan.value();
//扫描
//类加载器
//1.bootstrap-->jre/-lib 2.ext-->jre/ext/lib 3.app-->classpath
ClassLoader classLoader=MockKingJayApplication.class.getClassLoader();
URL resource = classLoader.getResource(path.replace(".","/"));
File file=new File(resource.getFile());
if(file.isDirectory()){
File[] files = file.listFiles();
for (File f : files) {

String fileName=f.getAbsolutePath();
if(fileName.endsWith(".class")){
String packageName=fileName.substring(fileName.indexOf("com"),fileName.indexOf(".class")).
replace("\\" ,".");
Class<?> clazz = null;
try {
clazz = classLoader.loadClass(packageName);
if(clazz.isAnnotationPresent(Component.class)){
//表示当前的类是一个bean
//解析bean,判断当前bean是单例bean,还是prototype bean
BeanDefinition beanDefinition=new BeanDefinition();

Component ComponentAnnotation = clazz.getDeclaredAnnotation(Component.class);
String beanName=ComponentAnnotation.value();

if(clazz.isAnnotationPresent(Scope.class)){
Scope scopeAnnotation=clazz.getDeclaredAnnotation(Scope.class);
beanDefinition.setScope(scopeAnnotation.value());
}else {
beanDefinition.setScope("singleton");
}
beanDefinition.setClazz(clazz);
beanDefinitionObjectsMap.put(beanName,beanDefinition);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
}

构造方法(先扫描,在从beanDefinitionObjectsMap找到单例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
29
30
31
32
33
34
public MockKingJayApplication(Class configClass){
this.configClass=configClass;

//1.解析配置类
scan(configClass);

// 2.找到单例bean放到单例池中
for(Map.Entry<String,BeanDefinition> entry:beanDefinitionObjectsMap.entrySet()){
String beanName=entry.getKey();
BeanDefinition beanDefinition=entry.getValue();
if(beanDefinition.getScope().equals("singleton")){
Object bean=createBean(beanDefinition);
singletonObjectsMap.put(beanName,bean);
}
}
}

public Object createBean(BeanDefinition beanDefinition){

Class clazz = beanDefinition.getClazz();
try {
Object o = clazz.getDeclaredConstructor().newInstance();
return o;
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return null;
}

getbean方法实现(如果是单例,则在单例池中找到该bean对象,如果不是,调用createBean重写创建一个新的bean)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public Object getBean(String beanName){
if (beanDefinitionObjectsMap.containsKey(beanName)){
BeanDefinition beanDefinition=beanDefinitionObjectsMap.get(beanName);
if(beanDefinition.getScope().equals("singleton")){
Object o=singletonObjectsMap.get(beanName);
return o;
}else {
//创建bean对象(不是单例)
Object bean= createBean(beanDefinition);
return bean;
}
}else{
//不存在对应的bean
throw new NullPointerException();
}
}

creatbean方法实现

准备工作

创建Autowired注解

1
2
3
4
5
6
7
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.FIELD})
public @interface AutoWired {

String value() default "";
}

创建orderService

1
2
3
4
5
@Component("orderService")
public class OrderService {


}

在userService中创建方法,并注入orderservice

1
2
3
4
5
6
7
8
9
10
11
@Component("userService")

public class UserService {

@AutoWired
OrderService orderService;

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

在测试中输出:

1
2
3
4
5
6
7
8
9
10
11
12
public class Test {


public static void main(String[] args) {

MockKingJayApplication mockKingJayApplication=new MockKingJayApplication(AppConfig.class);

UserService userService = (UserService) mockKingJayApplication.getBean("userService");

userService.test();
}
}

createBean方法简单实现(根据属性名注入)

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
public Object createBean(BeanDefinition beanDefinition){

Class clazz = beanDefinition.getClazz();
try {
Object o = clazz.getDeclaredConstructor().newInstance();

//依赖注入
for (Field declaredField : clazz.getDeclaredFields()) {
if(declaredField.isAnnotationPresent(AutoWired.class)){
Object bean=getBean(declaredField.getName());
if(bean==null){
return new NullPointerException();
}
declaredField.setAccessible(true);
declaredField.set(o,bean);
}
}


return o;
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return null;
}

Aware回调模拟

spring在创建一个bean之后想要获取该bean的名字等:

创建BeanNameAware接口:

1
2
3
4
5
public interface BeanNameAware {

void setBeanName(String name);
}

在userService实现该接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Component("userService")
public class UserService implements BeanNameAware {

@AutoWired
OrderService orderService;

String beanName;

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

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

在createBean中加入该逻辑

1
2
3
4
//是否实现该接口
if(o instanceof BeanNameAware){
((BeanNameAware) o).setBeanName(beanName);
}

createBean初始化

创建InitializingBean接口

1
2
3
4
5
public interface InitializingBean {

void afterPropertiesSet() throws Exception;
}

修改userservice(afterPropertiesSet中的执行内容可以自己修改)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Component("userService")
public class UserService implements InitializingBean {

@AutoWired
OrderService orderService;


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


@Override
public void afterPropertiesSet() throws Exception {
System.out.println("初始化");
}
}

在createBean中加入该逻辑

1
2
3
4
5
6
7
8
//初始化
if(o instanceof InitializingBean){
try {
((InitializingBean) o).afterPropertiesSet();
} catch (Exception e) {
e.printStackTrace();
}
}

beanPostProcessor(bean的后置处理器)

定义接口

1
2
3
4
5
6
7
8
9
10
11
public interface BeanPostProcessor {

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

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

}

创建类去模拟后置处理器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Component("BeanPostProcessorTest")
public class BeanPostProcessorTest implements BeanPostProcessor {


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

if(beanName.equals("userService")){
((UserService)bean).setName("mockingjay is good");
}

return bean;
}

@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
System.out.println("初始化后 ");
return bean;
}
}

在userservice中去模拟

1
2
3
4
5
String name;

public void setName(String name) {
this.name = name;
}

在扫描容器加入如下判断逻辑

1
2
3
4
5
//如果是beanPostProcessor(判断是否实现了该接口)
if(BeanPostProcessor.class.isAssignableFrom(clazz)){
BeanPostProcessor instance = (BeanPostProcessor) clazz.getDeclaredConstructor().newInstance();
beanPostProcessorList.add(instance);
}

在createBean下初始化前后加入bean后置处理器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//初始化前调用
for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
beanPostProcessor.postProcessBeforeInitialization(o,beanName);
}

//初始化
if(o instanceof InitializingBean){
try {
((InitializingBean) o).afterPropertiesSet();
} catch (Exception e) {
e.printStackTrace();
}
}

//初始化后调用
for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
beanPostProcessor.postProcessAfterInitialization(o,beanName);
}

spring AOP 模拟

创建productService和productServiceImpl

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public interface ProductService {

void test();


}

@Component("productService")
public class ProductServiceImpl implements ProductService{


@AutoWired
OrderService orderService;

@Override
public void test() {
System.out.println("hello world");
System.out.println(orderService);
}
}

该过程在beanPostProcessor的postProcessAfterInitialization后进行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
    @Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
//匹配
System.out.println(beanName);
if(beanName.equals("productService")){
// 生成代理类
Object proxyInstance=Proxy.newProxyInstance(BeanPostProcessorTest.class.getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

System.out.println("代理逻辑");
method.invoke(bean,args);
return null;
}
});
return proxyInstance;
}
return bean;
}
}

spring的bean生命周期

  • 创建

    class(userServicve.class)–> 推断构造方法(如果有一个有参或者是多个有参但有一个无参,不会报错,其中有参构造器会通过byType(先)和byName 去从spring容器中获取)–> 实例化 –> 对象 –> 属性填充(依赖注入) –> 初始化 afterPropertiesSet() (是否实现InitializingBean)–>(AOP–>代理对象(这个代理对象中没有实例化对象里的属性值,比如userService中注入了orderService,但是这个代理对象没有orderService,而代理对象中target中有属性值) –>(前提是否有AOP操作))–> bean对象

    AOP : 1. 把所有的切面找出来,之后放入缓存中(下次直接可以从缓存中找到切面bean)

    ​ 2. 匹配传入的切点(两步都匹配上,说明使用了AOP)

  • 销毁

spring的事务

两个注解:

1
2
3
@Configuration //(没有事务则无法使用)
//开启事务
@EnableTransactionManagement

在使用事务的方法或者类上加入 @Transactional

出现错误场景:

如果一个类中两个方法,都加上事务,且第二个事务的传播级别为Never(如果有存在事务还存在事务,则会抛出异常),第一方法中调用第二个方法后,执行不会报错。

为什么:因为spring底层会创建代理对像,但执行这两个方法确是被代理对象(target)去执行,被代理对象不会管你是不是加入@Transactional注解,第二个事务则会失效。

如何解决:让代理对象去执行该方法,自己注入自己(这里注入的是代理对象,而不是该类型的bean对象)

其他文章