前言
在前两期Spring知识储备后,我们终于来到了Bean的实操部分,这一篇不会像上一篇那么枯燥无聊,只是了解下Spring的功能,这一篇带着大家理解Bean的生命周期,还会带着大家看Spring的源码。可以说,是非常有趣的。
Bean的生成过程
毋庸置疑,在生成Bean之前,我们需要让Spring来知道那些是Bean,各种Bean的属性,是单例Bean还是原型Bean,Bean的各种属性等,这些都现需要进行扫描来让Spring来知道
org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider#scanCandidateComponents(String basePackage)
这是扫描某个包路径,其中basePackage就是我们要扫描的包路径。
生成BeanDefinition
什么是BeanDefinition?这在我的上一篇文章中有说到,可以说是很重要的内容。想知道的可以看看我的上一篇文章。
接下来就来说下扫描的逻辑和过程。
-
通过ResourcePatternResolve来指定包路径下的所有.class文件,并且文件包装成Resource对象
-
遍历每个Resource对象
3.接下来就是获得Resource对象中的属性了。Spring利用MetadataReaderFactory来读取Resource对象重点属性得到MetadataReder。
4.利用MetadataReader进行@excludeFilters和@includeFilter以及条件注解@Condition的筛选。
5.待筛选通过后,基于metadataReader来生成ScannedGenericBeanDefinition
6.基于metadataReader判断是否是接口或者是抽象类,接口和抽象类不能被实例化。
7.筛选通过后,表示扫描到了一个Bean,将ScannedGenericBeanDefinition加入结果集。
MetadataReader
MetadataReader是一个元数据读取器,可以读取类上的元数据,主要包含了AnnotationMetadata,功能有:
1. 获取类的名字
2. 获取父类的名字
3. 获取所实现的所有接口名
4. 获取所有内部类的名字
5. 判断是不是抽象类
6. 判断是不是接口
7. 判断是不是一个注解
8. 获取拥有某个注解的方法集合
9. 获取类上添加的所有注解信息
10. 获取类上添加的所有注解类型集合
值得注意的是,在MetadaReader里面读取元数据的CachingMetadataReaderFactory解析某个.class文件使用的是ASM技术,说明文件并没有去到JVM虚拟机就已经被解析出来了各种属性。
最终得到的ScannedGenericBeanDefinition中,beanClass存储的是当前类的名字,并不是class对象(beanClass是Object类型,既可以存储名字也可以存储class对象)
合并BeanDefinition
在得到每个Resource对象的BeanDefinition之后,就应该进行合并了,方便创建Bean对象。
父子BeanDefinition
在Spring中存在父子BeanDefinition,但是Bean是没有父子关系的,只有BeanDefinition有父子关系,和Java中的父子有关系,但是又大相径庭。 例子:
<!-- 定义一个名为 parent 的 Bean,其作用域为 prototype -->
<!-- 每次从容器中获取该 Bean 时,都会创建一个新的实例 -->
<!-- 对应的类为 com.zhouyu.service.Parent -->
<bean id="parent" class="com.zhouyu.service.Parent" scope="prototype"/>
<!-- 定义一个名为 child 的 Bean,默认作用域为 singleton -->
<!-- 整个应用程序中只会创建一个该 Bean 的实例 -->
<!-- 对应的类为 com.zhouyu.service.Child -->
<bean id="child" class="com.zhouyu.service.Child"/>
这种定义下就是单例Bean。因为它并没有设置父子关系
大家看这个例子:
<!-- 定义一个名为 parent 的 Bean,其作用域为 prototype -->
<!-- 意味着每次从 Spring 容器中获取该 Bean 时,都会创建一个新的实例 -->
<!-- 对应的类为 com.zhouyu.service.Parent -->
<bean id="parent" class="com.zhouyu.service.Parent" scope="prototype"/>
<!-- 定义一个名为 child 的 Bean,它继承自 parent Bean -->
<!-- 继承意味着 child Bean 会默认拥有 parent Bean 的一些配置,如属性、方法等 -->
<!-- 对应的类为 com.zhouyu.service.Child -->
<bean id="child" class="com.zhouyu.service.Child" parent="parent"/>
在这种设置了Child的父母是parent的情况,并且parent是原型的情况,Child就是原型Bean了。
解释:
就和Java中的一样,其实就是子类继承了父类的属性,在Spring中就是继承了父类的Scope属性,而在根据child来生成Bean对象之前,需要进行对BeanDefinition的合并,得到完整的child属性。也就是child完整的BeanDefinition
加载类
加载类不是一个类,他是一个过程,用来加载通过bean生成的类。在生成并且合并完BeanDefinition后,就可以进行bean的加载了,然而创建类的过程无非就是Spring实例化对象的过程,而实例化就是加载当前BeanDefinition对应的class,在AbstractAutowiredCapableFactory中createBean()方法, 在这个方法中会调用方法:
Class resolvedClass = resolveBeanClass(mbd, beanName);
resolveBeanClass:
// 检查 BeanDefinition 对象 mbd 是否已经包含了 Class 对象
if (mbd.hasBeanClass()) {
// 若包含,则直接返回该 Class 对象
return mbd.getBeanClass();
}
// 检查系统是否设置了安全管理器
if (System.getSecurityManager() != null) {
// 若设置了安全管理器,使用特权操作来解析 Bean 类
return AccessController.doPrivileged((PrivilegedExceptionAction<Class<?>>) () ->
doResolveBeanClass(mbd, typesToMatch), getAccessControlContext());
} else {
// 若未设置安全管理器,直接解析 Bean 类
return doResolveBeanClass(mbd, typesToMatch);
}
/**
* 检查当前 BeanDefinition 对象是否已经明确指定了 Bean 类
* @return 如果 beanClass 字段是 Class 类型的实例,返回 true;否则返回 false
*/
public boolean hasBeanClass() {
return (this.beanClass instanceof Class);
}
这里面有几个判断逻辑 第一个:如果是Class类,那么直接返回这个类 第二个:如果不是Class类,那么就进行解析
大家都知道是要类加载器才可以进行加载类,那么Spring使用哪个类加载器呢? *类加载器: *BootstrapClassLoader:加载Java的核心类库 *ExtensionClassLoader:加载Java中的JDK扩展类 *ApplicationClassLoader:加载编译后的应用程序 *CustomClassLoader:自定义加载器
介绍了上面加载器,大家能猜出来是用哪个加载器吗? 其实使用的是当前线程中的ClassLoader,就是自定义类加载器,如果在线程中的类加载器为null时,那么就返回ClassUtils类的类加载器。如果还是null,那么就返回BootstrapClassLoader。
那么有人就要问了,为什么是这样?
在我们使用Spring时,大多数都要进行网页交互吧,就拿Tomcat举例子,Tomcat中有自己的类加载器,就是自定义类加载器,当我们的jar包在Tomcat服务器中跑的时候,肯定是直接拿Tomcat线程的类加载器,更加方便,也更节约资源。
实例化前
在确定哪个类加载器加载类之后,就可以实例化对象了,那么我们在第一篇中讲到过,bean需要进行实例化前的操作,在实例化前,Spring提供了一个拓展点,可以让用户在这个对象实例化前来实现自己定义的方法,这个拓展点叫做InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()。 比如:
@Component
public class ZhouyuBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName)
throws BeansException {
if ("userService".equals(beanName)) {
System.out.println("实例化前");
}
return null;
}
}
这段代码表示如果一个Bean的名字是userService,那么就会打印“实例化前”这四个字。
实例化
在这里Spring会根据BeanDefinition来创建对象。
Sipplier创建对象
先判断BeanDefinition中是否设置了Supplier,设置了就调用Supplier的get方法来获得对象。
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
beanDefinition.setInstanceSupplier(new Supplier<Object>() {
@Override
public Object get() {
return new UserService();
}
});
context.registerBeanDefinition("userService", beanDefinition);
工厂方法创建对象
如果没有设置Supplier,那么就检查BeanDefinition中是否设置了factoryMethod,也就是工厂方法。
方式一设置工厂方法:
<bean id="userService" class="com.zhouyu.service.UserService" factory-method="createUserService"/>
方式二设置工厂方法:
<bean id="commonService" class="com.zhouyu.service.CommonService"/>
<bean id="userService1" factory-bean="commonService" factory-method="createUserService"/>
对应的CommonService为:
public class CommonService {
public UserService createUserService() {
return new UserService();
}
}
推断构造方法
这部分内容会在后面章节中细讲
BeanDefinition后置处理
在给对象赋值之前,Spring有提供了一个拓展点MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition()用来给BeanDefinition进行加工,里面可以执行自己实现的方法:
@Component
public class ZhouyuMergedBeanDefinitionPostProcessor implements MergedBeanDefinitionPostProcessor {
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
if ("userService".equals(beanName)) {
beanDefinition.getPropertyValues().add("orderService", new OrderService());
}
}
}
实例化后
Spring还是搞了一个拓展点,用来对实例化对象进行处理的:
@Component
public class ZhouyuInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
if ("userService".equals(beanName)) {
UserService userService = (UserService) bean;
userService.test();
}
return true;
}
}
自动注入
这里指的是Spring的自动注入。
处理属性
所谓的处理属性就是在注解中写入我们想写入的值,然后通过注解中的值来写入实例化对象的某个属性。其中注解有@Autowired,@Resource,@Value等,他们是通过InstantiationAwareBeanPostProcessor.postProcessProperties()这个拓展点实现的。我们也可以自己实现自动注入功能:
@Component
public class ZhouyuInstantiationAwareBeanPostProcessor 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(ZhouyuInject.class)) {
field.setAccessible(true);
try {
field.set(bean, "123");
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
return pvs;
}
}
执行Aware
完成了属性赋值之后,Spring会执行一些回调 1.BeanNameAware:回传beanName给bean对象。 2.BeanClassLoaderAware:回传classLoader给bean对象。 3.BeanFactoryAware:回传beanFactory给对象。
初始化阶段
在我们第一篇提到,bean的创建过程最后是初始化阶段,分别有初始化前,初始化,初始化后。
初始化前
也是Spring提供的拓展点BeanPostProcessor.postProcessBeforeInitialization()
@Component
public class ZhouyuBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if ("userService".equals(beanName)) {
System.out.println("初始化前");
}
return bean;
}
}
可以对这个注入点来执行我们自己写的方法,Spring大部分都是这样。
初始化
1. 查看当前Bean对象是否实现了InitializingBean接口,如果实现了就调用其afterPropertiesSet()方法
2. 执行BeanDefinition中指定的初始化方法
初始化后
这是Bean创建生命周期中的最后一个步骤,也是Spring提供的一个扩展点: BeanPostProcessor.postProcessAfterInitialization(),比如:
@Component
public class ZhouyuBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if ("userService".equals(beanName)) {
System.out.println("初始化后");
}
return bean;
}
}
可以在这个步骤中,对Bean最终进行处理,Spring中的AOP就是基于初始化后实现的,初始化后返 回的对象才是最终的Bean对象。
总结
1. InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation() 2. 实例化 3. MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition() 4. InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation() 5. 自动注入 6. InstantiationAwareBeanPostProcessor.postProcessProperties() 7. Aware对象 8. BeanPostProcessor.postProcessBeforeInitialization() 9. 初始化 10. BeanPostProcessor.postProcessAfterInitialization()