宁睿 发表于 2023-5-15 18:52:55

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

前言

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

前面我们说过,最开始的bean定义(合并后的),解析类的元数据时,用到的是ASM技术并不会真正开始解析class文件,所以也只是提取出来bean的name值作为beanClass属性,知道这个前提,那么这一步就好说了,下面是他的源码:
        @Override
        protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
                        throws BeanCreationException {

                RootBeanDefinition mbdToUse = mbd;
               
                // 马上就要实例化Bean了,确保beanClass被加载了
                Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
                if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
                        mbdToUse = new RootBeanDefinition(mbd);
                        mbdToUse.setBeanClass(resolvedClass);
                }

                // Prepare method overrides.
                try {
                        mbdToUse.prepareMethodOverrides();
                }

                try {
                        // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
                        // 实例化前
                        Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
                        if (bean != null) {
                                return bean;
                        }
                }

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

如果当前bean被加载了,那么直接返回了,如果没加载那么开始解析当前bean
        @Nullable
        protected Class<?> resolveBeanClass(RootBeanDefinition mbd, String beanName, Class<?>... typesToMatch)
                        throws CannotLoadBeanClassException {

                try {
                        // 如果beanClass被加载了
                        if (mbd.hasBeanClass()) {
                                return mbd.getBeanClass();
                        }

                        // 如果beanClass没有被加载
                        if (System.getSecurityManager() != null) {
                                return AccessController.doPrivileged((PrivilegedExceptionAction<Class<?>>)
                                                () -> doResolveBeanClass(mbd, typesToMatch), getAccessControlContext());
                        }
                        else {
                                return doResolveBeanClass(mbd, typesToMatch);
                        }
                }
        }通过这一步也可以看出bean定义中最初的beanClass属性,都是String类型的beanname
resolveBeforeInstantiation

这一步走的是实例化前的工作,当然如果你想在这一步中直接返回实体类也可,而且最离谱的是Spring并没有校验你返回的类是否是当前beanname的类,可以看下源码:
public boolean hasBeanClass() {
                return (this.beanClass instanceof Class);
        }
[*]hasInstantiationAwareBeanPostProcessors:直接从缓存list中获取有关实例化的BeanPostProcessors,这里是一个优化,要不然每次获取有关实例化的BeanPostProcessors都是遍历整个BeanPostProcessors再加个校验
[*]determineTargetType:获取类
[*]applyBeanPostProcessorsBeforeInstantiation:执行InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation的方法,该方法可以返回bean。
[*]postProcessAfterInstantiation:执行BeanPostProcessor的postProcessAfterInstantiation的方法,正常我们的bean不会走到这里,因为实例化前根本没有创建出来bean,所以也就是bean != null一直为false
当然除非你自己写一个InstantiationAwareBeanPostProcessors,其实真没看见这么玩的,主要是没有啥意义,比如这样:
        @Nullable
        private Class<?> doResolveBeanClass(RootBeanDefinition mbd, Class<?>... typesToMatch)
                        throws ClassNotFoundException {

                ClassLoader beanClassLoader = getBeanClassLoader();
                ClassLoader dynamicLoader = beanClassLoader;
                boolean freshResolve = false;

                if (!ObjectUtils.isEmpty(typesToMatch)) {
                        // When just doing type checks (i.e. not creating an actual instance yet),
                        // use the specified temporary class loader (e.g. in a weaving scenario).
                        ClassLoader tempClassLoader = getTempClassLoader();
                        if (tempClassLoader != null) {
                                dynamicLoader = tempClassLoader;
                                freshResolve = true;
                                if (tempClassLoader instanceof DecoratingClassLoader) {
                                        DecoratingClassLoader dcl = (DecoratingClassLoader) tempClassLoader;
                                        for (Class<?> typeToMatch : typesToMatch) {
                                                dcl.excludeClass(typeToMatch.getName());
                                        }
                                }
                        }
                }

                String className = mbd.getBeanClassName();
                if (className != null) {
                        // 解析Spring表达式,有可能直接返回了一个Class对象
                        Object evaluated = evaluateBeanDefinitionString(className, mbd);
                        if (!className.equals(evaluated)) {
                                // A dynamically resolved expression, supported as of 4.2...
                                if (evaluated instanceof Class) {
                                        return (Class<?>) evaluated;
                                }
                                else if (evaluated instanceof String) {
                                        className = (String) evaluated;
                                        freshResolve = true;
                                }
                                else {
                                        throw new IllegalStateException("Invalid class name expression result: " + evaluated);
                                }
                        }
                        if (freshResolve) {
                                // When resolving against a temporary class loader, exit early in order
                                // to avoid storing the resolved Class in the bean definition.
                                if (dynamicLoader != null) {
                                        try {
                                                return dynamicLoader.loadClass(className);
                                        }
                                        catch (ClassNotFoundException ex) {
                                                if (logger.isTraceEnabled()) {
                                                        logger.trace("Could not load class [" + className + "] from " + dynamicLoader + ": " + ex);
                                                }
                                        }
                                }
                                return ClassUtils.forName(className, dynamicLoader);
                        }
                }

                // Resolve regularly, caching the result in the BeanDefinition...
                return mbd.resolveBeanClass(beanClassLoader);
        }再坚持一下,让我把实例化过程先讲完!

现在的逻辑已经走完了实例化前的postProcessBeforeInstantiation方法,那么现在我们的bean要进行实例化了,
        @Nullable
        public static ClassLoader getDefaultClassLoader() {
                ClassLoader cl = null;

                // 优先获取线程中的类加载器
                try {
                        cl = Thread.currentThread().getContextClassLoader();
                }
                catch (Throwable ex) {
                        // Cannot access thread context ClassLoader - falling back...
                }

                // 线程中类加载器为null的情况下,获取加载ClassUtils类的类加载器
                if (cl == null) {
                        // No thread context class loader -> use class loader of this class.
                        cl = ClassUtils.class.getClassLoader();
                        if (cl == null) {
                                // getClassLoader() returning null indicates the bootstrap ClassLoader
                                // 加入ClassUtils是被Bootstrap类加载器加载的,则获取系统类加载器
                                try {
                                        cl = ClassLoader.getSystemClassLoader();
                                }
                                catch (Throwable ex) {
                                        // Cannot access system ClassLoader - oh well, maybe the caller can live with null...
                                }
                        }
                }
                return cl;
        }跟这篇无关的内容能删除的都删除了,主要有这几步我们需要注意下:

[*]createBeanInstance:创建实例,前提是之前没有创建过
[*]applyMergedBeanDefinitionPostProcessors:找到注入点,比如AutowiredAnnotationBeanPostProcessor(@Autowired、@Value、@Inject)和CommonAnnotationBeanPostProcessor(@Resource),这在实例化前和实例化后方法中间夹了一个处理合并bean定义的逻辑,注意一下
[*]addSingletonFactory:添加缓存,用来解决循环依赖,以后单独讲解
[*]populateBean:这一方法主要是属性填充也就是依赖注入的,但是官方把实例化后的PostProcessors方法写到这里了,所以也得贴出来,但是我们只看实例化相关的。
createBeanInstance

        public Class<?> resolveBeanClass(@Nullable ClassLoader classLoader) throws ClassNotFoundException {
                String className = getBeanClassName();
                if (className == null) {
                        return null;
                }
                Class<?> resolvedClass = ClassUtils.forName(className, classLoader);
                this.beanClass = resolvedClass;
                return resolvedClass;
        }
[*]resolveBeanClass:之前讲解过了,不重复讲了,就是拿到class
[*]obtainFromSupplier:通过Supplier函数获取bean,前提是你得声明bean定义
[*]instantiateUsingFactoryMethod:这种是使用@Bean方法实例化对象,
[*]后面省略了推断构造方法进行实例化对象,以后单独讲解推断构造方法
obtainFromSupplier

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

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

这里关于MergedBeanDefinitionPostProcessors的实现类不全讲解了,主要讲解下工作常用的注解AutowiredAnnotationBeanPostProcessor,他是用来解析@Autowired、@Value、@Inject,看下他的默认源码:
public AutowiredAnnotationBeanPostProcessor() {                this.autowiredAnnotationTypes.add(Autowired.class);                this.autowiredAnnotationTypes.add(Value.class);                try {                        this.autowiredAnnotationTypes.add((Class
页: [1]
查看完整版本: Spring源码:Bean生命周期(四)