3.0 Spring生命周期源码解析

Spring最核心的功能之一就是创建对象(IOC)

Bean的生命周期指:在spring中,一个Bean的生成和销毁的过程

  1. 启动ApplicationContext
  2. 创建BeanFactory
  3. 初始化BeanFactory
  4. 执行BeanFactory后置处理器
  5. 进行扫描
  6. 生成BeanDefinition
  7. 合并BeanDefinition
  8. 加载类
  9. 实例化前
  10. 推断构造方法
  11. 实例化
  12. BeanDefinition的后置处理
  13. 实例化后
  14. 填充属性
  15. 填充属性后
  16. 执行Aware
  17. 初始化前
  18. 初始化
  19. 初始化后

1. 生成BeanDefinition

Spring启动先进行扫描,调用

org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider#scanCandidateComponents(String basePackage)

扫描路径,得到BeanDefinition的Set集合

1.1扫描的流程

  1. 首先,通过ResourcePatternResolver获得指定包路径下的所有 .class 文件(Spring源码中将 此文件包装成了Resource对象)
  2. 遍历每个Resource对象
  3. 利用MetadataReaderFactory解析Resource对象得到MetadataReader(在Spring源码中 MetadataReaderFactory具体的实现类为CachingMetadataReaderFactoryMetadataReader的具体实现类为SimpleMetadataReader
  4. 利用MetadataReader进行excludeFiltersincludeFilters,以及条件注解@Conditional的筛选 (条件注解并不能理解:某个类上是否存在@Conditional注解,如果存在则调用注解中所指定 的类的match方法进行匹配,匹配成功则通过筛选,匹配失败则pass掉。)
  5. 筛选通过后,基于metadataReader生成ScannedGenericBeanDefinition
  6. 再基于metadataReader判断是不是对应的类是不是接口或抽象类
  7. 如果筛选通过,那么就表示扫描到了一个Bean,将ScannedGenericBeanDefinition加入结果集

MetadataReader表示类的元数据读取器,主要包含了一个AnnotationMetadata,功能有:

  1. 获取类的名字
  2. 获取父类的名字
  3. 获取所实现的所有接口名
  4. 获取所有内部类的名字
  5. 判断是不是抽象类
  6. 判断是不是接口
  7. 判断是不是一个注解
  8. 获取拥有某个注解的方法集合
  9. 获取类上添加的所有注解信息
  10. 获取类上添加的所有注解类型集合

CachingMetadataReaderFactory解析某个.class文件得到MetadataReader对象是 利用的ASM技术,并没有加载这个类到JVM。并且,最终得到的ScannedGenericBeanDefinition对 象,beanClass属性存储的是当前类的名字,而不是class对象。(beanClass属性的类型是Object, 它即可以存储类的名字,也可以存储class对象)

另外还可以通过直接定义BeanDefinition,或 解析spring.xml文件的,或者@Bean注解得到BeanDefinition对象。

1.2 合并BeanDefinition

Spring中支持父子BeanDefinition

// child是单例Bean
<bean id="parent" class="com.zhouyu.service.Parent" scope="prototype"/>
<bean id="child" class="com.zhouyu.service.Child"/>

// child就是原型Bean
// child的父BeanDefinition是parent,所以会继承parent上所定义的scope属性
<bean id="parent" class="com.zhouyu.service.Parent" scope="prototype"/>
<bean id="child" class="com.zhouyu.service.Child" parent="parent"/>

根据child来生成Bean对象之前,需要进行BeanDefinition的合并,得到完整的child的 BeanDefinition。

1.3 加载类

根据合并之后的BeanDefinition对象加载对应的class文件,

AbstractAutowireCapableBeanFactory#createBean加载

Class<?> resolvedClass = resolveBeanClass(mbd, beanName);

if (mbd.hasBeanClass()) {
	return mbd.getBeanClass();
}
if (System.getSecurityManager() != null) {
	return AccessController.doPrivileged((PrivilegedExceptionAction<Class<?>>) () ‐>
	doResolveBeanClass(mbd, typesToMatch), getAccessControlContext());
}else {
	return doResolveBeanClass(mbd, typesToMatch);
}

public boolean hasBeanClass() {
	return (this.beanClass instanceof Class);
}

beanClass属性的类型是Class,那么就直接返回,如果不是,则会根据类名进行加载 (doResolveBeanClass方法所做的事情)

利用BeanFactory所设置的类加载器来加载类,如果没有设置,则默认使用 ClassUtils.getDefaultClassLoader()所返回的类加载器来加载

  1. 优先返回当前线程中的ClassLoader
  2. 线程中类加载器为null的情况下,返回ClassUtils类的类加载器
  3. 如果ClassUtils类的类加载器为空,那么则表示是Bootstrap类加载器加载的ClassUtils类,那么 则返回系统类加载器

1.4 实例化前

在Spring中,实例化对象之前,Spring提供了一个扩展点,允许用户来控制是否在某个或某些Bean 实例化之前做一些启动动作。这个扩展点叫 InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()

@Component
public class CustomBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
	@Override
	public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
		if ("userService".equals(beanName)) {
		System.out.println("实例化之前");
		return new UserService();
		}
		return null;
	}
}

这个方法有返回值,如果像上述的实现则表示不需要spring 来实例化,并且后续spring依赖注入等步骤也不会进行,直接执行初始化后这一步了

1.5 实例化

根据Beandefinition创建对象

1.5.1 Supplier创建对象

首先会判断BeanDefinition中是否设置了Supplier,如果是则调用Supplier.get()得到对象

// 使用BeanDefinition对象来设置Supplier
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
beanDefinition.setInstanceSupplier(new Supplier<Object>() {
	@Override
	public Object get() {
		return new UserService();
	}
});
context.registerBeanDefinition("userService", beanDefinition);

1.5.2 工厂方法创建对象

接着会检查是否设置了factoryMethod

//设置factoryMethod有两种方式
// 方式一
<bean id="userService" class="com.zhouyu.service.UserService" factory‐method="createUserService" />
//对应得类方式
public class UserService {
	public static UserService createUserService() {
		System.out.println("执行createUserService()");
		UserService userService = new UserService();
		return userService;
	}
	public void test() {
		System.out.println("test");
	}
}

//方式二
<bean id="commonService" class="com.zhouyu.service.CommonService"/>
<bean id="userService1" factory‐bean="commonService" factory‐method="createUserService"
/>
//对应得类方式
public class CommonService {
	public UserService createUserService() {
		return new UserService();
	}
}

需要注意的是,我们通过@Bean所定义的BeanDefinition,是存在factoryMethodfactoryBean 的,也就是和上面的方式二非常类似,@Bean所注解的方法就是factoryMethod,AppConfig对象 就是factoryBean。如果@Bean所所注解的方法是static的,那么对应的就是方式一。

1.5.3 推断构造方法

在推断构造方法中除了选择构造方法和查找入参对象以外,还会判断是否在对应类中使用Lookup注解的方法,如果存在就会将该方法封装为lookupOverride对象添加到BeanDefinition

在实例化时如果没有LookupOverride对象会直接用构造方法反射生成实例对象,如果存在则生成一个代理对象

// @Lookup注解就是方法注入
@Component
public class UserService {
	private OrderService orderService;
	public void test() {
		OrderService orderService = createOrderService();
		System.out.println(orderService);
	}
	@Lookup("orderService")
	public OrderService createOrderService() {
		return null;
	}
}

1.6 BeanDefinition的后置处理

Bean对象实例化之后就该给对象赋值了,在赋值之前,spring有提供了一个扩展点,可以对BeanDefinition加工

MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition()

@Component
public class CustomMergedBeanDefinitionPostProcessor implements MergedBeanDefinitionPostProcessor {
	@Override
	public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition,Class<?> beanType, String beanName) {
		if ("userService".equals(beanName)) {
			beanDefinition.getPropertyValues().add("orderService", new OrderService());
		}
	}
}

应用:

在Spring源码中,AutowiredAnnotationBeanPostProcessor就是一个 MergedBeanDefinitionPostProcessor,它的postProcessMergedBeanDefinition()中会去查找注 入点,并缓存在AutowiredAnnotationBeanPostProcessor对象的一个Map中 (injectionMetadataCache

1.7 实例化后

在处理完BeanDefinition后,Spring又设计了一个扩展点,对所实例化出来的对象进行处理。InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()

@Component
public class CustomInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
	@Override
	public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
		if ("userService".equals(beanName)) {
			UserService userService = (UserService) bean;
			userService.test();
		}
		return true;
	}
}

1.8 自动注入

spring的自动注入,依赖注入部分详解

1.9 处理属性

这个步骤中,就会处理@Autowired、@Resource、@Value等注解,也是通过 InstantiationAwareBeanPostProcessor.postProcessProperties()扩展点来实现的,比如我们 甚至可以实现一个自己的自动注入功能,比如

// @CustomInject自定义注解标识的字段设置值
@Component
public class CustomInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
	@Override
	public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
		if ("userService".equals(beanName)) {
			for (Field field : bean.getClass().getFields()) {
				if (field.isAnnotationPresent(.class)) {
					field.setAccessible(true);
					try {
						field.set(bean, "123");
					} catch (IllegalAccessException e) {
						e.printStackTrace();
					}
				}
			}	
        }
		return pvs;
	}
}

1.10 执行Aware

完成了属性赋值之后,Spring会执行一些回调,包括:

  • BeanNameAware:回传beanName给bean对象。
  • BeanClassLoaderAware:回传classLoader给bean对象。
  • BeanFactoryAware:回传beanFactory给对象。

1.11 初始化前

初始化前,也是Spring提供的一个扩展点: BeanPostProcessor.postProcessBeforeInitialization()

  @Component
public class CustomBeanPostProcessor implements BeanPostProcessor {
	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    	if ("userService".equals(beanName)) {
        	System.out.println("初始化前");
        }
            return bean;
        }
}

利用初始化前,可以对进行了依赖注入的Bean进行处理

在Spring源码中:

  • InitDestroyAnnotationBeanPostProcessor会在初始化前这个步骤中执行@PostConstruct的 方法,
  • ApplicationContextAwareProcessor会在初始化前这个步骤中进行其他Aware的回调:
    • EnvironmentAware:回传环境变量
    • EmbeddedValueResolverAware:回传占位符解析器
    • ResourceLoaderAware:回传资源加载器
    • ApplicationEventPublisherAware:回传事件发布器
    • MessageSourceAware:回传国际化资源
    • ApplicationStartupAware:回传应用其他监听对象,可忽略
    • ApplicationContextAware:回传Spring容器ApplicationContext

1.12 初始化

  • 查看当前Bean对象是否实现了InitializingBean接口,如果实现了就调用其afterPropertiesSet() 方法
  • 执行BeanDefinition中指定的初始化方法

1.13 初始化后

这是Bean创建生命周期中的最后一个步骤,也是Spring提供的一个扩展点: BeanPostProcessor.postProcessAfterInitialization()

可以在这个步骤中,对Bean最终进行处理,Spring中的AOP就是基于初始化后实现的,初始化后返 回的对象才是最终的Bean对象。

public static void main(String[] args) {
        @Component
        public class CustomBeanPostProcessor implements BeanPostProcessor {
            @Override
            public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
                if ("userService".equals(beanName)) {
                    System.out.println("初始化后");
                }
                return bean;
            }
        }
    }

1.14 总结BeanPostProcessor

  • InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()
  • 实例化
  • MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition()
  • InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()
  • 自动注入
  • InstantiationAwareBeanPostProcessor.postProcessProperties()
  • Aware对象
  • BeanPostProcessor.postProcessBeforeInitialization()
  • 初始化
  • BeanPostProcessor.postProcessAfterInitialization()

2.Bean的销毁过程

Bean销毁是发生在Spring容器关闭过程中

AnnotationConfigApplicationContext context = new
AnnotationConfigApplicationContext(AppConfig.class);
UserService userService = (UserService) context.getBean("userService");
userService.test();
// 容器关闭
context.close();

在Bean创建过程中,在最后(初始化之后),有一个步骤会去判断当前创建的Bean是不是 DisposableBean

  1. 当前Bean是否实现了DisposableBean接口

  2. 或者,当前Bean是否实现了AutoCloseable接口

  3. BeanDefinition中是否指定了destroyMethod

  4. 调用DestructionAwareBeanPostProcessor.requiresDestruction(bean)进行判断

    • ApplicationListenerDetector中直接使得ApplicationListenerDisposableBean

    • InitDestroyAnnotationBeanPostProcessor中使得拥有@PreDestroy注解了的方法就是DisposableBean

  5. 把符合上述任意一个条件的Bean适配成DisposableBeanAdapter对象,并存入 disposableBeans中(一个LinkedHashMap)

在spring容器关闭时:

  1. 首先发布ContextClosedEvent事件

  2. 调用lifecycleProcessoronCloese()方法

  3. 销毁单例Bean

    • 遍历disposableBeans

      • 把每个disposableBean从单例池中移除

      • 调用disposableBeandestroy()

      • 如果这个disposableBean还被其他Bean依赖了,那么也得销毁其他Bean

      • 如果这个disposableBean还包含了inner beans,将这些Bean从单例池中移除掉

        (inner bean参考链接)

    • 清空manualSingletonNames,是一个Set,存的是用户手动注册的单例Bean的 beanName

    • 清空allBeanNamesByType,是一个Map,key是bean类型,value是该类型所有的 beanName数组

    • 清空singletonBeanNamesByType,和allBeanNamesByType类似,只不过只存了单例 Bean

这里涉及到一个设计模式:适配器模式

在销毁时,Spring会找出实现了DisposableBean的Bean,有上述几类情况。

这些Bean在容器关闭时都要调用相应的销毁方法。 所以,这里就需要进行适配,将实现了DisposableBean接口、或者AutoCloseable接口等适配成实现了DisposableBean接口,所以就用到了DisposableBeanAdapter

会把实现了AutoCloseable接口的类封装成DisposableBeanAdapter,而DisposableBeanAdapter 实现了DisposableBean接口

posted @ 2022-10-11 16:53  浮沉丶随心  阅读(76)  评论(0编辑  收藏  举报