Spring源码:Bean生命周期(四)

宁睿  金牌会员 | 2023-5-15 18:52:55 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 570|帖子 570|积分 1718

前言

在之前的文章中,我们介绍了 Bean 的核心概念、Bean 定义的解析过程以及 Bean 创建的准备工作。在今天的文章中,我们将深入探讨 Bean 的创建过程,并主要讲解 createBean 方法的实现。在这个过程中,我们将了解 Bean 的实例化、属性注入、初始化和销毁等步骤,以及各个步骤的具体实现细节。通过本文的学习,读者将能够更深入地理解 Spring 框架中 Bean 的创建过程,从而为后续的学习和实践打下坚实的基础。好了,我们开始!
createBean

前面我们说过,最开始的bean定义(合并后的),解析类的元数据时,用到的是ASM技术并不会真正开始解析class文件,所以也只是提取出来bean的name值作为beanClass属性,知道这个前提,那么这一步就好说了,下面是他的源码:
  1.         @Override
  2.         protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
  3.                         throws BeanCreationException {
  4.                 RootBeanDefinition mbdToUse = mbd;
  5.                
  6.                 // 马上就要实例化Bean了,确保beanClass被加载了
  7.                 Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
  8.                 if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
  9.                         mbdToUse = new RootBeanDefinition(mbd);
  10.                         mbdToUse.setBeanClass(resolvedClass);
  11.                 }
  12.                 // Prepare method overrides.
  13.                 try {
  14.                         mbdToUse.prepareMethodOverrides();
  15.                 }
  16.                 try {
  17.                         // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
  18.                         // 实例化前
  19.                         Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
  20.                         if (bean != null) {
  21.                                 return bean;
  22.                         }
  23.                 }
  24.                 try {
  25.                         Object beanInstance = doCreateBean(beanName, mbdToUse, args);
  26.                         ......
  27.                         return beanInstance;
  28.                 }
  29.         }
复制代码

  • resolveBeanClass:真正的开始加载bean。
  • mbdToUse.prepareMethodOverrides();和@lookUp注解有关系,不看
  • resolveBeforeInstantiation:实例化前的BeanPostProcessors,如果初始化了那么就返回了,不走其他创建逻辑了。
  • doCreateBean:正常开始实例化、初始化bean。
resolveBeanClass

如果当前bean被加载了,那么直接返回了,如果没加载那么开始解析当前bean
  1.         @Nullable
  2.         protected Class<?> resolveBeanClass(RootBeanDefinition mbd, String beanName, Class<?>... typesToMatch)
  3.                         throws CannotLoadBeanClassException {
  4.                 try {
  5.                         // 如果beanClass被加载了
  6.                         if (mbd.hasBeanClass()) {
  7.                                 return mbd.getBeanClass();
  8.                         }
  9.                         // 如果beanClass没有被加载
  10.                         if (System.getSecurityManager() != null) {
  11.                                 return AccessController.doPrivileged((PrivilegedExceptionAction<Class<?>>)
  12.                                                 () -> doResolveBeanClass(mbd, typesToMatch), getAccessControlContext());
  13.                         }
  14.                         else {
  15.                                 return doResolveBeanClass(mbd, typesToMatch);
  16.                         }
  17.                 }
  18.         }
复制代码
通过这一步也可以看出bean定义中最初的beanClass属性,都是String类型的beanname
resolveBeforeInstantiation

这一步走的是实例化前的工作,当然如果你想在这一步中直接返回实体类也可,而且最离谱的是Spring并没有校验你返回的类是否是当前beanname的类,可以看下源码:
  1. public boolean hasBeanClass() {
  2.                 return (this.beanClass instanceof Class);
  3.         }
复制代码

  • hasInstantiationAwareBeanPostProcessors:直接从缓存list中获取有关实例化的BeanPostProcessors,这里是一个优化,要不然每次获取有关实例化的BeanPostProcessors都是遍历整个BeanPostProcessors再加个校验
  • determineTargetType:获取类
  • applyBeanPostProcessorsBeforeInstantiation:执行InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation的方法,该方法可以返回bean。
  • postProcessAfterInstantiation:执行BeanPostProcessor的postProcessAfterInstantiation的方法,正常我们的bean不会走到这里,因为实例化前根本没有创建出来bean,所以也就是bean != null一直为false
当然除非你自己写一个InstantiationAwareBeanPostProcessors,其实真没看见这么玩的,主要是没有啥意义,比如这样:
  1.         @Nullable
  2.         private Class<?> doResolveBeanClass(RootBeanDefinition mbd, Class<?>... typesToMatch)
  3.                         throws ClassNotFoundException {
  4.                 ClassLoader beanClassLoader = getBeanClassLoader();
  5.                 ClassLoader dynamicLoader = beanClassLoader;
  6.                 boolean freshResolve = false;
  7.                 if (!ObjectUtils.isEmpty(typesToMatch)) {
  8.                         // When just doing type checks (i.e. not creating an actual instance yet),
  9.                         // use the specified temporary class loader (e.g. in a weaving scenario).
  10.                         ClassLoader tempClassLoader = getTempClassLoader();
  11.                         if (tempClassLoader != null) {
  12.                                 dynamicLoader = tempClassLoader;
  13.                                 freshResolve = true;
  14.                                 if (tempClassLoader instanceof DecoratingClassLoader) {
  15.                                         DecoratingClassLoader dcl = (DecoratingClassLoader) tempClassLoader;
  16.                                         for (Class<?> typeToMatch : typesToMatch) {
  17.                                                 dcl.excludeClass(typeToMatch.getName());
  18.                                         }
  19.                                 }
  20.                         }
  21.                 }
  22.                 String className = mbd.getBeanClassName();
  23.                 if (className != null) {
  24.                         // 解析Spring表达式,有可能直接返回了一个Class对象
  25.                         Object evaluated = evaluateBeanDefinitionString(className, mbd);
  26.                         if (!className.equals(evaluated)) {
  27.                                 // A dynamically resolved expression, supported as of 4.2...
  28.                                 if (evaluated instanceof Class) {
  29.                                         return (Class<?>) evaluated;
  30.                                 }
  31.                                 else if (evaluated instanceof String) {
  32.                                         className = (String) evaluated;
  33.                                         freshResolve = true;
  34.                                 }
  35.                                 else {
  36.                                         throw new IllegalStateException("Invalid class name expression result: " + evaluated);
  37.                                 }
  38.                         }
  39.                         if (freshResolve) {
  40.                                 // When resolving against a temporary class loader, exit early in order
  41.                                 // to avoid storing the resolved Class in the bean definition.
  42.                                 if (dynamicLoader != null) {
  43.                                         try {
  44.                                                 return dynamicLoader.loadClass(className);
  45.                                         }
  46.                                         catch (ClassNotFoundException ex) {
  47.                                                 if (logger.isTraceEnabled()) {
  48.                                                         logger.trace("Could not load class [" + className + "] from " + dynamicLoader + ": " + ex);
  49.                                                 }
  50.                                         }
  51.                                 }
  52.                                 return ClassUtils.forName(className, dynamicLoader);
  53.                         }
  54.                 }
  55.                 // Resolve regularly, caching the result in the BeanDefinition...
  56.                 return mbd.resolveBeanClass(beanClassLoader);
  57.         }
复制代码
再坚持一下,让我把实例化过程先讲完!

现在的逻辑已经走完了实例化前的postProcessBeforeInstantiation方法,那么现在我们的bean要进行实例化了,
  1.         @Nullable
  2.         public static ClassLoader getDefaultClassLoader() {
  3.                 ClassLoader cl = null;
  4.                 // 优先获取线程中的类加载器
  5.                 try {
  6.                         cl = Thread.currentThread().getContextClassLoader();
  7.                 }
  8.                 catch (Throwable ex) {
  9.                         // Cannot access thread context ClassLoader - falling back...
  10.                 }
  11.                 // 线程中类加载器为null的情况下,获取加载ClassUtils类的类加载器
  12.                 if (cl == null) {
  13.                         // No thread context class loader -> use class loader of this class.
  14.                         cl = ClassUtils.class.getClassLoader();
  15.                         if (cl == null) {
  16.                                 // getClassLoader() returning null indicates the bootstrap ClassLoader
  17.                                 // 加入ClassUtils是被Bootstrap类加载器加载的,则获取系统类加载器
  18.                                 try {
  19.                                         cl = ClassLoader.getSystemClassLoader();
  20.                                 }
  21.                                 catch (Throwable ex) {
  22.                                         // Cannot access system ClassLoader - oh well, maybe the caller can live with null...
  23.                                 }
  24.                         }
  25.                 }
  26.                 return cl;
  27.         }
复制代码
跟这篇无关的内容能删除的都删除了,主要有这几步我们需要注意下:

  • createBeanInstance:创建实例,前提是之前没有创建过
  • applyMergedBeanDefinitionPostProcessors:找到注入点,比如AutowiredAnnotationBeanPostProcessor(@Autowired、@Value、@Inject)和CommonAnnotationBeanPostProcessor(@Resource),这在实例化前和实例化后方法中间夹了一个处理合并bean定义的逻辑,注意一下
  • addSingletonFactory:添加缓存,用来解决循环依赖,以后单独讲解
  • populateBean:这一方法主要是属性填充也就是依赖注入的,但是官方把实例化后的PostProcessors方法写到这里了,所以也得贴出来,但是我们只看实例化相关的。
createBeanInstance
  1.         public Class<?> resolveBeanClass(@Nullable ClassLoader classLoader) throws ClassNotFoundException {
  2.                 String className = getBeanClassName();
  3.                 if (className == null) {
  4.                         return null;
  5.                 }
  6.                 Class<?> resolvedClass = ClassUtils.forName(className, classLoader);
  7.                 this.beanClass = resolvedClass;
  8.                 return resolvedClass;
  9.         }
复制代码

  • resolveBeanClass:之前讲解过了,不重复讲了,就是拿到class
  • obtainFromSupplier:通过Supplier函数获取bean,前提是你得声明bean定义
  • instantiateUsingFactoryMethod:这种是使用@Bean方法实例化对象,
  • 后面省略了推断构造方法进行实例化对象,以后单独讲解推断构造方法
obtainFromSupplier

这一步其实我们用到的很少,主要是考虑到Spring自动注入的开销,我们自己可以就行实例化而已,比如我们这样写照样可以获取bean,但是不会由Spring帮我们注入,得靠自己了:
  1.         public String getBeanClassName() {
  2.                 Object beanClassObject = this.beanClass;
  3.                 if (beanClassObject instanceof Class) {
  4.                         return ((Class<?>) beanClassObject).getName();
  5.                 }
  6.                 else {
  7.                         return (String) beanClassObject;
  8.                 }
  9.         }
复制代码
其实用法和@bean注解相似,除了减少Spring自动注入的开销,实在没想到有啥用
instantiateUsingFactoryMethod

该方法内部逻辑很多,为了更加直观的展现,只贴出关键代码:
  1.         @Nullable
  2.         protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
  3.                 Object bean = null;
  4.                 if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
  5.                         // Make sure bean class is actually resolved at this point.
  6.                         // synthetic表示合成,如果某些Bean式合成的,那么则不会经过BeanPostProcessor的处理
  7.                         if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
  8.                                 Class<?> targetType = determineTargetType(beanName, mbd);
  9.                                 if (targetType != null) {
  10.                                         bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
  11.                                         if (bean != null) {
  12.                                                 bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
  13.                                         }
  14.                                 }
  15.                         }
  16.                         mbd.beforeInstantiationResolved = (bean != null);
  17.                 }
  18.                 return bean;
  19.         }
复制代码
比如我们定义的配置类中有很多@Bean形式的方法,最终Spring会直接invoke调用被@Bean修饰的方法从而实现实例化对象。
applyMergedBeanDefinitionPostProcessors

这里关于MergedBeanDefinitionPostProcessors的实现类不全讲解了,主要讲解下工作常用的注解AutowiredAnnotationBeanPostProcessor,他是用来解析@Autowired、@Value、@Inject,看下他的默认源码:
[code]public AutowiredAnnotationBeanPostProcessor() {                this.autowiredAnnotationTypes.add(Autowired.class);                this.autowiredAnnotationTypes.add(Value.class);                try {                        this.autowiredAnnotationTypes.add((Class
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

宁睿

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表