• bean的生命周期分析(四)


    二、全流程梳理

    2.7 bean的实例化

    2.7.1 doCreateBean

    在对于不是实现代理类是通过调用 doCreateBean 方法来创建对象的:

    protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
    			throws BeanCreationException {
    
    	// Instantiate the bean.
    	// 首先实例化一个bean
    	BeanWrapper instanceWrapper = null;
    	if (mbd.isSingleton()) {
    		// 从三级缓存删除,factoryBeanInstanceCache存的是beanName对应的FactoryBean实例对象
    		// 有可能在本Bean创建之前,就有其他Bean把当前Bean给创建出来(比如依赖注入过程中)
    		// 单例情况下清除缓存。这里保存的是 FactoryBean 和 BeanWrapper 的映射关系。
    		// factoryBeanInstanceCache是在创建其他bean的时候缓存了一下FactoryBean 。
    		instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    	}
    	// 如果没有缓存,则重新创建
    	if (instanceWrapper == null) {
    		// 1. 创建Bean实例:根据指定的bean使用对应的策略创建新的实例。如:工厂方法、构造函数自动注入,简单初始化
    		instanceWrapper = createBeanInstance(beanName, mbd, args);
    	}
    	final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
    	Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
    	mbd.resolvedTargetType = beanType;
    
    	// Allow post-processors to modify the merged bean definition.
    	// 见2.7.1.2 allpyMergedBeanDefinitionPostProcessors
    	synchronized (mbd.postProcessingLock) {
    		if (!mbd.postProcessed) {
    			try {
    				applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
    			}
    			catch (Throwable ex) {
    				throw new BeanCreationException(mbd.getResourceDescription(), beanName,
    						"Post-processing of merged bean definition failed", ex);
    			}
    			mbd.postProcessed = true;
    		}
    	}
    
    	// 用于解决循环依赖,详见2.7.1.3
    	// Eagerly cache singletons to be able to resolve circular references
    	// even when triggered by lifecycle interfaces like BeanFactoryAware.
    	boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
    			isSingletonCurrentlyInCreation(beanName));
    	if (earlySingletonExposure) {
    		if (logger.isDebugEnabled()) {
    			logger.debug("Eagerly caching bean '" + beanName +
    					"' to allow for resolving potential circular references");
    		}
    		addSingletonFactory(beanName, new ObjectFactory<Object>() {
    			@Override
    			public Object getObject() throws BeansException {
    				return getEarlyBeanReference(beanName, mbd, bean);
    			}
    		});
    	}
    
    	// Initialize the bean instance.
    	// 用于初始化bean,详见2.8.1
    	Object exposedObject = bean;
    	try {
    		populateBean(beanName, mbd, instanceWrapper);
    		if (exposedObject != null) {
    			exposedObject = initializeBean(beanName, exposedObject, mbd);
    		}
    	}
    	catch (Throwable ex) {
    		if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
    			throw (BeanCreationException) ex;
    		}
    		else {
    			throw new BeanCreationException(
    					mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
    		}
    	}
    	// 2.8.3 二级缓存检查
    	if (earlySingletonExposure) {
    		Object earlySingletonReference = getSingleton(beanName, false);
    		if (earlySingletonReference != null) {
    			if (exposedObject == bean) {
    				exposedObject = earlySingletonReference;
    			}
    			else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
    				String[] dependentBeans = getDependentBeans(beanName);
    				Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
    				for (String dependentBean : dependentBeans) {
    					if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
    						actualDependentBeans.add(dependentBean);
    					}
    				}
    				if (!actualDependentBeans.isEmpty()) {
    					throw new BeanCurrentlyInCreationException(beanName,
    							"Bean with name '" + beanName + "' has been injected into other beans [" +
    							StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
    							"] in its raw version as part of a circular reference, but has eventually been " +
    							"wrapped. This means that said other beans do not use the final version of the " +
    							"bean. This is often the result of over-eager type matching - consider using " +
    							"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
    				}
    			}
    		}
    	}
    	// 2.9 bean的销毁
    	// Register bean as disposable.
    	try {
    		registerDisposableBeanIfNecessary(beanName, bean, mbd);
    	}
    	catch (BeanDefinitionValidationException ex) {
    		throw new BeanCreationException(
    				mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
    	}
    
    	return exposedObject;
    }
    
    • 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
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    2.7.1.1 createBeanInstance
    protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
    	// Make sure bean class is actually resolved at this point.
    	// 确认需要创建的bean实例的类可以实例化
    	Class<?> beanClass = resolveBeanClass(mbd, beanName);
    
    	// 确保class不为空,并且访问权限是public
    	if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
    		throw new BeanCreationException(mbd.getResourceDescription(), beanName,
    				"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
    	}
    
    	// 判断当前beanDefinition中是否包含实例供应器,此处相当于一个回调方法,利用回调方法来创建bean
    	Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
    	if (instanceSupplier != null) {
    		return obtainFromSupplier(instanceSupplier, beanName);
    	}
    
    	// 如果工厂方法不为空则使用工厂方法初始化策略
    	if (mbd.getFactoryMethodName() != null) {
    		return instantiateUsingFactoryMethod(beanName, mbd, args);
    	}
    
    	// 一个类可能有多个构造器,所以Spring得根据参数个数、类型确定需要调用的构造器
    	// 在使用构造器创建实例后,Spring会将解析过后确定下来的构造器或工厂方法保存在缓存中,避免再次创建相同bean时再次解析
    
    	// Shortcut when re-creating the same bean...
    	// 标记下,防止重复创建同一个bean
    	boolean resolved = false;
    	// 是否需要自动装配
    	boolean autowireNecessary = false;
    	// 如果没有参数
    	if (args == null) {
    		synchronized (mbd.constructorArgumentLock) {
    			// 因为一个类可能由多个构造函数,所以需要根据配置文件中配置的参数或传入的参数来确定最终调用的构造函数。
    			// 因为判断过程会比较,所以spring会将解析、确定好的构造函数缓存到BeanDefinition中的resolvedConstructorOrFactoryMethod字段中。
    			// 在下次创建相同时直接从RootBeanDefinition中的属性resolvedConstructorOrFactoryMethod缓存的值获取,避免再次解析
    			if (mbd.resolvedConstructorOrFactoryMethod != null) {
    				resolved = true;
    				autowireNecessary = mbd.constructorArgumentsResolved;
    			}
    		}
    	}
    	// 有构造参数的或者工厂方法
    	if (resolved) {
    		// 构造器有参数
    		if (autowireNecessary) {
    			// 构造函数自动注入
    			return autowireConstructor(beanName, mbd, null, null);
    		}
    		else {
    			// 使用默认构造函数构造
    			return instantiateBean(beanName, mbd);
    		}
    	}
    
    	// Candidate constructors for autowiring?
    	// 从bean后置处理器中为自动装配寻找构造方法, 有且仅有一个有参构造或者有且仅有@Autowired注解构造
    	Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
    	// 以下情况符合其一即可进入
    	// 1、存在可选构造方法
    	// 2、自动装配模型为构造函数自动装配
    	// 3、给BeanDefinition中设置了构造参数值
    	// 4、有参与构造函数参数列表的参数
    	if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
    			mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
    		return autowireConstructor(beanName, mbd, ctors, args);
    	}
    
    	// Preferred constructors for default construction?
    	// 找出最合适的默认构造方法
    	ctors = mbd.getPreferredConstructors();
    	if (ctors != null) {
    		// 构造函数自动注入
    		return autowireConstructor(beanName, mbd, ctors, null);
    	}
    
    	// No special handling: simply use no-arg constructor.
    	// 使用默认无参构造函数创建对象,如果没有无参构造且存在多个有参构造且没有@AutoWired注解构造,会报错
    	return instantiateBean(beanName, mbd);
    }
    
    
    • 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
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81

    createBeanInstance() 方法是 spring 实例化 bean 的核心代码,它根据不同的情况会调用四种实例化方法

    • obtainFromSupplier() :通过 Supplier 实例化.
    • instantiateUsingFactoryMethod():通过工厂方法实例化
    • autowireConstructor():用合适的构造函数实例化
    • instantiateBean():用无参构造函数实例化
    2.7.1.1.1 obtainFromSupplier() :通过 Supplier 实例化

    Supplier 是 Java8 的一个函数式接口。该接口中就一个 get() 方法。

    从上述代码可以看到 Spring 是从 mbd中得到的 Supplier 。既然可以得到那就可以进行设置。instanceSupplier属性是属于 AbstractBeanDefinition 抽象类的。

    • set方法 进行设置
    public void setInstanceSupplier(@Nullable Supplier<?> instanceSupplier) {
    	this.instanceSupplier = instanceSupplier;
    }
    
    • 1
    • 2
    • 3
    • 构造方法进行设置
    public <T> RootBeanDefinition(@Nullable Class<T> beanClass, @Nullable Supplier<T> instanceSupplier) {
    	super();
    	setBeanClass(beanClass);
    	setInstanceSupplier(instanceSupplier);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 直接进行注册
    AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
            ctx.registerBean(Person.class, new Supplier<Person>() {
                @Override
                public Person get() {
                    return new Person("gongj");
                }
            });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    2.7.1.1.2 instantiateUsingFactoryMethod():通过工厂方法实例化

    如果 RootBeanDefinition 类中存在 factoryMethodName 属性,或者在配置文件中配置了 factory-method 或 factory-bean 标签,spring 会尝试使用 instantiateUsingFactoryMethod() 方法进行 bean 的实例化

    • 在 xml 文件配置中,可以使用 factory-bean 和 factory-method 两个标签可以指定一个类中的方法,spring 会将这个指定的方法的返回值作为 bean 返回(如果方法是静态方法,则可以不创建 factory-bean 就直接调用,否则需要先将 factory-bean 注入到 spring 容器中)
    • 对 @Bean 注解的解析。在 ConfigurationClassPostProcessor 后处理器中,会对被 @Bean 注解修饰的方法进行解析,生成一个 ConfigurationClassBeanDefinition 的 BeanDefinition。此时 BeanDefinition 的 factoryMethodName 正是 @Bean 修饰的方法本身。所以这里会调用 instantiateUsingFactoryMethod() 方法。通过回调的方式调用 @Bean 修饰的方法,并将返回结果注入到 spring 容器中
    • 通过静态工厂实例化 bean 示例
    public class UserFactory {
    	
    	// 静态方法
    	public static User getUser1() {
    		return new User();
    	}
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    xml配置文件

    <!-- 使用静态工厂实例化 user -->
    <bean id="user1" class="ioc.service.UserFactory" factory-method="getUser1"></bean>
    
    • 1
    • 2
    • 通过实例工厂实例化 bean 示例
    public class UserFactory {
    	
    	// 普通方法
    	public User getUser2() {
    		return new User();
    	}
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    xml配置文件

    <!-- 使用实例工厂实例化 user -->
    <bean id="userFactory" class="ioc.service.UserFactory"></bean>
    <bean id="user2" factory-bean="userFactory" factory-method="getUser2"></bean>
    
    • 1
    • 2
    • 3
    • @Bean 方式实例化 bean 示例
    @Bean
    public ShiroDialect getShiroDialect() {
    
    	return new ShiroDialect();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    2.7.1.1.3 autowireConstructor() 用合适的构造函数实例化

    简单来说,就是根据传入的参数列表,来匹配合适的有参构造器进行 bean 的实例化
    不赘述了。

    2.7.1.1.4 instantiateBean() 用无参构造函数实例化

    这里的逻辑一句话概括 : 是否有方法被覆盖(是否使用 replace 或 lookup 进行配置),有则使用 cglib 动态代理,增强方法,否则直接通过反射实例化 bean。这一块判断方法是否被重写,不是为了事务或者 aop,因为解析还没到那一步,这里是为了 lookup-method 和 replaced-method 标签

    2.7.1.1.5 createBeanInstance() 方法小结

    该方法处于 spring 创建 bean 的入口阶段,会使用各种方法来尝试完成 bean 的实例化。对于具体使用那种方式进行实例化,spring 会使用类 RootBeanDefinition 去解析 xml 和注解类型的配置文件

    • 第一步:尝试使用 Supplier 方式实例化
    • 第二步:尝试使用工厂方法实例化;会使用类 RootBeanDefinition 去解析factory-method,factory-bean 标签和 @Bean 注解,如果没有解析到,就不会使用这种方式实例化
    • 第三步:尝试使用用合适的有参构造器实例化;会使用类 RootBeanDefinition 去解析构造器参数,找寻最合适的有参构造器用来实例化;如果没有,就不会使用这种方式实例化
    • 最后:使用无参构造器实例化

    但是并未完成属性填充、接口特性实现(如 Aware)、标签设置(如 inti-method)的设置。在后续的 AbstractAutowireCapableBeanFactory#populateBean() 方法中完成了属性的填充

    2.7.1.2 applyMergedBeanDefinitionPostProcessors

    Bean对象实例化出来之后,接下来就应该给对象的属性赋值了。在真正给属性赋值之前,Spring又提供了一个扩展点MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition(),可以对此时的BeanDefinition进行加工,

    synchronized (mbd.postProcessingLock) {
    if (!mbd.postProcessed) {
    	try {
    		applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
    	}
    	catch (Throwable ex) {
    		throw new BeanCreationException(mbd.getResourceDescription(), beanName,
    				"Post-processing of merged bean definition failed", ex);
    	}
    	mbd.postProcessed = true;
    }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    此处还有一个 应用增强器 applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName)根据名称可以知道这是一个操作BeanDefinition的增强器,可以去修改BeanDefinition中的属性,但是注意这个的执行时机,是在 bean 实例化之后在执行的,所以说现在修改 BeanDefiniton的有些属性是无效的,比如beanClss属性,因为bean已经创建了。

    此处的 PostProcessor的类型为:MergedBeanDefinitionPostProcessor。

    protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
    	for (BeanPostProcessor bp : getBeanPostProcessors()) {
    		if (bp instanceof MergedBeanDefinitionPostProcessor) {
    			MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
    			bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    此处的逻辑很简单,就是执行该类型的后置处理器的后置处理方法。
    我们点进去MergedBenDefinitionPostProcess类
    在这里插入图片描述
    从源码中可以看到,接口MergedBeanDefinitionPostProcessor中定义了两个方法:

    • postProcessMergedBeanDefinition()
    • resetBeanDefinition()

    postProcessMergedBeanDefinition()方法是Spring用于找出正在创建的bean中所有需要注入的字段并同时做缓存的,resetBeanDefinition()方法是在BeanDefinition被修改后清除容器的缓存的。

    我们点击向下 图标查看下postProcessMergedBeanDefinition()方法的实现类,可以发现这些实现类中几乎都包含"AnnotationBeanPostProcessor",所以他们其实都是注解相关的BPP,各自有负责处理的注解
    (比如CommonAnnotationBeanPostProcessor、AutowiredAnnotationBeanPostProcessor)
    在这里插入图片描述

    2.7.1.3 解决循环依赖问题
    // 此处用于解决循环依赖问题
    // Eagerly cache singletons to be able to resolve circular references
    // even when triggered by lifecycle interfaces like BeanFactoryAware.
    boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
    		isSingletonCurrentlyInCreation(beanName));
    if (earlySingletonExposure) {
    	if (logger.isDebugEnabled()) {
    		logger.debug("Eagerly caching bean '" + beanName +
    				"' to allow for resolving potential circular references");
    	}
    	addSingletonFactory(beanName, new ObjectFactory<Object>() {
    		@Override
    		public Object getObject() throws BeansException {
    			return getEarlyBeanReference(beanName, mbd, bean);
    		}
    	});
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    循环依赖的问题背景:
    https://zhuanlan.zhihu.com/p/462247516
    https://blog.csdn.net/ywl470812087/article/details/127725977

    earlySingletonExposure表示是否提前暴露,是的话就执行addSingletonFactory方法,将该bean暴露到第三级缓存,这样就可以解决特定场景的循环依赖问题。而getEarlyBeanReference就是返回这个bean的一个直接引用。为什么是个引用啊?很明显,现在的bean还是不完整的,别的bean,起个名字叫B,如果依赖咱们的A,那么就会从三级缓存中拿到A的直接引用,但是咱们说了A是不完整的,所以拿个引用,后续A完整了,那么B中依赖的bean不就完整了吗。。

    2.8 属性填充和bean的初始化

    2.8.1 populateBean

    下面就是初始化bean的过程了。populateBean的主要作用就是填充bean中的属性。因为源码比较长,主要讲解都放到注释中了。

    protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
         if (bw == null) {
             if (mbd.hasPropertyValues()) {
                 throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
             }
         } else {
    	     // 下面的注释讲解的很到位,给到任何一个InstantiationAwareBeanPostProcessors一个机会去修改bean的属性。
    		// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
    		// state of the bean before properties are set. This can be used, for example,
    		// to support styles of field injection.
    		/*
    			这一段代码是Spring用来提供给程序员扩展使用的, 如果我们不希望一个bean参与到属性注入, 自动装配的流
    		  程中, 那么就可以创建一个InstantiationAwareBeanPostProcessor后置处理器的实现类, 重写其
    		  postProcessAfterInstantiation方法, 如果该方法返回false, 那么continueWithPropertyPopulation
    		  这个变量会被置为false, 而这个变量被置为false, 在下面我们可以看到直接就return了, 从而Spring就不
    		  会对属性进行注入
    		  */
             if (!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {
                 Iterator var4 = this.getBeanPostProcessors().iterator();
    
                 while(var4.hasNext()) {
                     BeanPostProcessor bp = (BeanPostProcessor)var4.next();
                     if (bp instanceof InstantiationAwareBeanPostProcessor) {
                         InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor)bp;
                         if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                             return;
                         }
                     }
                 }
             }
    		/* 
    			这一段代码是当我们手动设置了注入模型为byType/byName的时候, Spring就会利用Java的内省机制拿到所有的
    		set方法, 如果一个set方法有参数, Spring就会将其封装成一个PropertyValue, 然后放入到新创建的newPvs
    		中, 最终用这个newPvs来替换原来的pvs, 这里有一个注意点, 在获取pvs的时候, 如果程序员没有提供, pvs
    		被设置成了null, 因为 mbd.getPropertyValues()这段代码始终是能拿到一个集合对象的, 只是这个集合对象
    		中没有PropertyValue而已
    	     */
    		// 下面是两种注入方法,分别是byName和byType。
             PropertyValues pvs = mbd.hasPropertyValues() ? mbd.getPropertyValues() : null;
             int resolvedAutowireMode = mbd.getResolvedAutowireMode();
             if (resolvedAutowireMode == 1 || resolvedAutowireMode == 2) {
                 MutablePropertyValues newPvs = new MutablePropertyValues((PropertyValues)pvs);
                 //在populateBean方法中,有两种注入方法,分别为byName和byType。将所有符合的bean统一存到了PropertyValues中。
                 if (resolvedAutowireMode == 1) {
                     this.autowireByName(beanName, mbd, bw, newPvs);
                 }
    
                 if (resolvedAutowireMode == 2) {
                     this.autowireByType(beanName, mbd, bw, newPvs);
                 }
    
                 pvs = newPvs;
             }
    
             boolean hasInstAwareBpps = this.hasInstantiationAwareBeanPostProcessors();
             boolean needsDepCheck = mbd.getDependencyCheck() != 0;
             PropertyDescriptor[] filteredPds = null;
    	     /* 分析: 在这段代码中, 如果pvs == null, Spring就获取beanDefinition中的集合对象了, 如果pvs == null,
    		我们也可以推断出, 程序员没有提供PropertyValue, 同时, 该beanDefinition也不是byName/byType的, 之后
    		Spring会调用InstantiationAwareBeanPostProcessor.postProcessProperties方法, 在之前我们分析
    		applyMergedBeanDefinitionPostProcessor的时候, 有讲解到, Spring会将所有需要被注入的属性/方法封装
    		成一个InjectedElement, 然后放入到InjectionMetadata中, 而这个InjectionMetada是位于后置处理器中的,
    		这是一个策略模式的应用, 不同的后置处理器处理不同的注入类型, 而在当前这一步, 就是遍历这些不同的后置
    		处理器, 开始将它们中的InjectionMetadata拿出来, 取出一个个InjectedElement完成注入
    		*/
             if (hasInstAwareBpps) {
                 if (pvs == null) {
                     pvs = mbd.getPropertyValues();
                 }
    
                 Iterator var9 = this.getBeanPostProcessors().iterator();
    
                 while(var9.hasNext()) {
                     BeanPostProcessor bp = (BeanPostProcessor)var9.next();
                     if (bp instanceof InstantiationAwareBeanPostProcessor) {
                         InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor)bp;
                         PropertyValues pvsToUse = ibp.postProcessProperties((PropertyValues)pvs, bw.getWrappedInstance(), beanName);
                         if (pvsToUse == null) {
                             if (filteredPds == null) {
                                 filteredPds = this.filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
                             }
    
                             pvsToUse = ibp.postProcessPropertyValues((PropertyValues)pvs, filteredPds, bw.getWrappedInstance(), beanName);
                             if (pvsToUse == null) {
                                 return;
                             }
                         }
    
                         pvs = pvsToUse;
                     }
                 }
             }
    
             if (needsDepCheck) {
                 if (filteredPds == null) {
                     filteredPds = this.filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
                 }
    
                 this.checkDependencies(beanName, mbd, filteredPds, (PropertyValues)pvs);
             }
    		/*
    	  如果pvs不为null, Spring就会开始遍历里面的一个个PropertyValue, 通过反射调用setXXX方法来完成注入,
    	  所以这就很好理解为什么当注入模型为byName/byType的时候, Spring能完成自动注入了*/
             if (pvs != null) {
                 this.applyPropertyValues(beanName, mbd, bw, (PropertyValues)pvs);
             }
    
         }
     }
    
    • 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
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    2.8.1.1 postProcessAfterInstantiation方法

    InstantiationAwareBeanPostProcessor的后置处理器postProcessAfterInstantiation,实现这个接口的在这里都会调用后置处理器。
    在这里插入图片描述
    可以看出,如果后置方法返回false那就直接return了,不会走后面的postProcessProperties方法了。在这里插入图片描述

    2.8.1.2 postProcessProperties

    在这里插入图片描述
    进行属性填充,Autowired注解就是通过上面第二个来进行属性注入的。

    2.8.2 initializeBean方法

    protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged(() -> {
                // 2.8.2.1 
                this.invokeAwareMethods(beanName, bean);
                return null;
            }, this.getAccessControlContext());
        } else {
            this.invokeAwareMethods(beanName, bean);
        }
    
        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
        }
    
        try {
            this.invokeInitMethods(beanName, wrappedBean, mbd);
        } catch (Throwable var6) {
            throw new BeanCreationException(mbd != null ? mbd.getResourceDescription() : null, beanName, "Invocation of init method failed", var6);
        }
    
        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }
    
        return wrappedBean;
    }
    
    • 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
    2.8.2.1 invokeAwareMethods方法
    private void invokeAwareMethods(String beanName, Object bean) {
        if (bean instanceof Aware) {
            if (bean instanceof BeanNameAware) {
                ((BeanNameAware)bean).setBeanName(beanName);
            }
    
            if (bean instanceof BeanClassLoaderAware) {
                ClassLoader bcl = this.getBeanClassLoader();
                if (bcl != null) {
                    ((BeanClassLoaderAware)bean).setBeanClassLoader(bcl);
                }
            }
    
            if (bean instanceof BeanFactoryAware) {
                ((BeanFactoryAware)bean).setBeanFactory(this);
            }
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    如果Bean实现BeanNameAware接口,调用setBeanName设置名字
    如果Bean实现BeanFactoryAware接口,调用setBeanFactoryAware设置BeanFactory

    2.8.2.2 applyBeanPostProcessorsBeforeInitialization方法
    public interface BeanPostProcessor {
        @Nullable
        default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            return bean;
        }
    
        @Nullable
        default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            return bean;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    实现BeanPostProcessor接口,定义该前置方法就可以做初始化前的操作。

    2.8.2.3 invokeInitMethods方法
    protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
                throws Throwable {
    
        // 首先先检查是否是InitializingBean,如果是,则需要调用afterPropertiesSet()
         boolean isInitializingBean = (bean instanceof InitializingBean);
         if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
             if (logger.isDebugEnabled()) {
                 logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
             }
             // 安全模式
             if (System.getSecurityManager() != null) {
                 try {
                     AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
                         ((InitializingBean) bean).afterPropertiesSet();
                         return null;
                     }, getAccessControlContext());
                 } catch (PrivilegedActionException pae) {
                     throw pae.getException();
                 }
             } else {
                 // 属性初始化处理
                 ((InitializingBean) bean).afterPropertiesSet();
             }
         }
    
         if (mbd != null && bean.getClass() != NullBean.class) {
             String initMethodName = mbd.getInitMethodName();
             if (StringUtils.hasLength(initMethodName) &&
                     !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
                     !mbd.isExternallyManagedInitMethod(initMethodName)) {
                 // 激活用户自定义的初始化方法
                 invokeCustomInitMethod(beanName, bean, mbd);
             }
         }
     }
    
    • 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

    分析:

    • 首先检查当前bean是否实现了InitializingBean接口,如果实现了,则调用其afterPropertiesSet方法。
    • 然后再检查是否指定了init-method,如果指定了init-method方法,则通过反射进行调用。

    从invokeInitMethods方法中,我们知道init-method指定的方法会在afterPropertiesSet方法后执行,如果afterPropertiesSet方法执行过程中出现异常,init-method方法是不会执行的。使用init-method使其对业务代码的侵入降低,虽然init-method是基于xml配置文件的,但我们也可以通过@PostConstruct注解的形式来进行替换

    invokeCustomInitMethod是执行用户可以自定义初始化方法,比如用xml的init-method或者@Bean指定的方法。同时跟afterPropertiesSet不冲突。可以看到,上面源码,先执行afterPropertiesSet方法,然后执行invokeCustomInitMethod。

    其实@PostConstruct就是在一个BeanPostProcessor的实现类的postProcessBeforeInitialization方法中被调用的,这个类就是InitDestroyAnnotationBeanPostProcessor类。
    在这里插入图片描述
    在这里插入图片描述

    2.8.2.3.1 afterPropertiesSet方法

    在spring的bean的生命周期中,实例化->生成对象->属性填充后会进行afterPropertiesSet方法,这个方法可以用在一些特殊情况中,也就是某个对象的某个属性需要经过外界得到,比如说查询数据库等方式,这时候可以用到spring的该特性,只需要实现InitializingBean即可:

    @Component("a")
    public class A implements InitializingBean {
        private B b;
    
        public A(B b) {
            this.b = b;
        }
    
        @Override
        public void afterPropertiesSet() throws Exception {
    
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    这样可以在afterPropertiesSet方法中进行你的额外操作。

    2.8.2.4 applyBeanPostProcessorsAfterInitialization方法

    实现BeanPostProcessor接口,定义该后置方法就可以做初始化后的操作。

    2.8.3 二级缓存检查

    bean初始化完成之后,后面还有一步去检查:第二级缓存是否存在, 代理对象和原始对象是否相等。
    下面是继续执行docreatebean的代码

    if (earlySingletonExposure) {
    	Object earlySingletonReference = getSingleton(beanName, false);
    	if (earlySingletonReference != null) {
    		if (exposedObject == bean) {
    			exposedObject = earlySingletonReference;
    		}
    		else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
    			String[] dependentBeans = getDependentBeans(beanName);
    			Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
    			for (String dependentBean : dependentBeans) {
    				if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
    					actualDependentBeans.add(dependentBean);
    				}
    			}
    			if (!actualDependentBeans.isEmpty()) {
    				throw new BeanCurrentlyInCreationException(beanName,
    						"Bean with name '" + beanName + "' has been injected into other beans [" +
    						StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
    						"] in its raw version as part of a circular reference, but has eventually been " +
    						"wrapped. This means that said other beans do not use the final version of the " +
    						"bean. This is often the result of over-eager type matching - consider using " +
    						"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
    			}
    		}
    	}
    }
    
    • 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

    2.9 bean的销毁

    // Register bean as disposable.
    try {
    	registerDisposableBeanIfNecessary(beanName, bean, mbd);
    }
    catch (BeanDefinitionValidationException ex) {
    	throw new BeanCreationException(
    			mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
    }
    
    return exposedObject;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    2.9.1 registerDisposableBeanIfNecessary

    protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
    	AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
    	// 当前 bean 的作用域不是 Prototype && requiresDestruction 返回 true
    	if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
    		// bean 的作用域是单例的
    		if (mbd.isSingleton()) {
    			// Register a DisposableBean implementation that performs all destruction
    			// work for the given bean: DestructionAwareBeanPostProcessors,
    			// DisposableBean interface, custom destroy method.
    			registerDisposableBean(beanName,
    					new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
    		}
    		else {
    			// A bean with a custom scope...
    			Scope scope = this.scopes.get(mbd.getScope());
    			if (scope == null) {
    				throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
    			}
    			scope.registerDestructionCallback(beanName,
    					new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    2.9.1.1 requiresDestruction
    protected boolean requiresDestruction(Object bean, RootBeanDefinition mbd) {
    	return (bean.getClass() != NullBean.class &&
    			(DisposableBeanAdapter.hasDestroyMethod(bean, mbd) || (hasDestructionAwareBeanPostProcessors() &&
    					DisposableBeanAdapter.hasApplicableProcessors(bean, getBeanPostProcessors()))));
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    可以看到 requiresDestruction() 方法只要满足下面任意一个即可

    • hasDestroyMethod():检查给定 bean 是否有任何类型的 destroy 销毁的方法可调用。怎么检查呢?
      • 它会去判断我们的 bean实体类有没有去实现接口 DisposableBean或者 AutoCloseable, 如果实现了这两个接口, 那么直接返回true, 代表着这个 bean有销毁方法。
      • 否则呢,执行了一个方法 inferDestroyMethodIfNecessary, 并将其返回,
      • 该方法简单讲解:通过 BeanDefinition取出指定的销毁方法名字
      • 如果没有指定
        • 在通过 BeanDefinition.getDestroyMethodName取一次
        • 如果获取到的 destroyMethodName == inferred
        • 就会去判断有没有实现 DisposableBean 接口
        • 肯定是没有实现的, 之前就已经判断过了
        • 获取当前 bean对应 类的close方法, 就把这个方法当做销毁方法
        • 如果没有找到, 就去找 shutdown方法, 把这个方法当做销毁方法
      • 最后就是两个三元运算符, 这个没什么好说的了
    • hasApplicableProcessors():
      在这里插入图片描述
      检查是否有 DestructionAwareBeanPostProcessor 的实现类,并且 requiresDestruction() 方法返回 true。判断当前Bean的类有没有加上 @PreDestory注解, 如果有就返回 true, 就证明了, 是通过注解的方式实现了销毁方法。
      @PreDestroy注解的初始化方法执行也是通过CommonAnnotationBeanPostProcessor的父类InitDestroyAnnotationBeanPostProcessor实现的DestructionAwareBeanPostProcessor方法注册销毁方法的。

    总结一下,requiresDestruction方法就是看一下有没有实现销毁方法,包括注解实现、Beadefinition中指定、当前bean的close方法和shutdown方法。如果确定有销毁方法,那就进行下一步,
    在这里插入图片描述

    • 在此之前,先梳理一下可以自定义销毁方法的地方
    • 1、如果使用XML配置文件的方式配置bean的话,那么可以在标签destroy-method中指定bean的初始化和销毁方法,如下所示
    <bean id="person" class="com.meimeixia.bean.Person" init-method="init" destroy-method="destroy">
        <property name="age" value="18"></property>
        <property name="name" value="liayun"></property>
    </bean>
    
    • 1
    • 2
    • 3
    • 4
    • 2、@Bean注解的initMethod和destroyMethod树形来指定bean的初始化方法和销毁方法。
    package com.meimeixia.config;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    import com.meimeixia.bean.Car;
    
    @Configuration
    public class MainConfigOfLifeCycle {
    
    	@Bean(initMethod="init", destroyMethod="destroy")
    	public Car car() {
    		return new Car();
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 3、@PreDestroy注解
      @PreDestroy注解用于在bean被销毁时需要执行的方法上,它是被用在bean对应的类中定义的方法,而且一个类中只能有一个方法被标记@PreDestroy注解。
    package com.xk.spring.init;
     
    import org.springframework.beans.factory.DisposableBean;
    import org.springframework.beans.factory.InitializingBean;
     
    import javax.annotation.PostConstruct;
    import javax.annotation.PreDestroy;
     
    /**
     * 用于如何配置讲解bean的初始化方法
     * @author xk
     * @since 2023.04.30 15:26
     */
    public class RedisService implements InitializingBean, DisposableBean {
     
        public RedisService(){
            System.out.println("这是RedisService构造方法");
        }
     
        public void initMethod(){
            System.out.println("(1)这是一个@Bean initMethod初始化方法");
        }
     
        @PostConstruct
        private void initMethod2(){
            System.out.println("(2)这是一个@PostConstruct初始化方法");
        }
     
        @Override
        public void afterPropertiesSet() throws Exception {
            System.out.println("(3)这是一个InitializingBean初始化方法");
        }
     
        public void destroyMethod(){
            System.out.println("(1)这是一个@Bean destroyMethod销毁方法");
        }
     
        @PreDestroy
        public void destroyMethod2() {
            System.out.println("(2)这是一个@PreDestroy销毁方法");
        }
     
    }
    
    • 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
    • 4、实现DisposableBean接口
      DisposableBean接口只有一个destroy方法,假如一个bean对应的类实现了该接口,spring在bean(或容器)销毁时就会调用destroy方法。
    package com.xk.spring.init;
     
    import org.springframework.beans.factory.DisposableBean;
    import org.springframework.beans.factory.InitializingBean;
     
    import javax.annotation.PostConstruct;
    import javax.annotation.PreDestroy;
     
    /**
     * 用于如何配置讲解bean的初始化方法
     * @author xk
     * @since 2023.04.30 15:26
     */
    public class RedisService implements InitializingBean, DisposableBean {
     
        public RedisService(){
            System.out.println("这是RedisService构造方法");
        }
     
        public void initMethod(){
            System.out.println("(1)这是一个@Bean initMethod初始化方法");
        }
     
        @PostConstruct
        private void initMethod2(){
            System.out.println("(2)这是一个@PostConstruct初始化方法");
        }
     
        @Override
        public void afterPropertiesSet() throws Exception {
            System.out.println("(3)这是一个InitializingBean初始化方法");
        }
     
        public void destroyMethod(){
            System.out.println("(1)这是一个@Bean destroyMethod销毁方法");
        }
     
        @PreDestroy
        public void destroyMethod2() {
            System.out.println("(2)这是一个@PreDestroy销毁方法");
        }
     
        @Override
        public void destroy() throws Exception {
            System.out.println("(3)这是一个DisposableBean销毁方法");
        }
    }
    
    • 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
    • 都存在的情况下的执行顺序
    package com.xk.spring.init;
     
    import org.springframework.beans.factory.DisposableBean;
    import org.springframework.beans.factory.InitializingBean;
     
    import javax.annotation.PostConstruct;
    import javax.annotation.PreDestroy;
     
    /**
     * 用于如何配置讲解bean的初始化方法
     * @author xk
     * @since 2023.04.30 15:26
     */
    public class RedisService implements InitializingBean, DisposableBean {
     
        public RedisService(){
            System.out.println("这是RedisService构造方法");
        }
     
        public void initMethod(){
            System.out.println("(1)这是一个@Bean initMethod初始化方法");
        }
     
        @PostConstruct
        private void initMethod2(){
            System.out.println("(2)这是一个@PostConstruct初始化方法");
        }
     
        @Override
        public void afterPropertiesSet() throws Exception {
            System.out.println("(3)这是一个InitializingBean初始化方法");
        }
     
        public void destroyMethod(){
            System.out.println("(1)这是一个@Bean destroyMethod销毁方法");
        }
     
        @PreDestroy
        public void destroyMethod2() {
            System.out.println("(2)这是一个@PreDestroy销毁方法");
        }
     
        @Override
        public void destroy() throws Exception {
            System.out.println("(3)这是一个DisposableBean销毁方法");
        }
    }
    
    • 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

    这是RedisService构造方法
    (2)这是一个@PostConstruct初始化方法
    (3)这是一个InitializingBean初始化方法
    (1)这是一个@Bean initMethod初始化方法
    (2)这是一个@PreDestroy销毁方法
    (3)这是一个DisposableBean销毁方法
    (1)这是一个@Bean destroyMethod销毁方法

    @PreDestroy指定的方法–>DisposableBean接口的destroy方法–>@Bean的destroyMethod属性指定的方法(或者是xml定义的)

    同理,其实@PreDestroy也是在一个BeanPostProcessor的实现类的postProcessBeforeInitialization方法中被调用的,这个类依然是InitDestroyAnnotationBeanPostProcessor类。这个类是DestructionAwareBeanPostProcessor的实现类,所以可以制定销毁的前置方法postProcessBeforeDestruction,而@PreDestroy就在这里通过反射起作用。
    在这里插入图片描述
    在这里插入图片描述

    2.9.1.2 registerDisposableBean

    就如同注释说的
    // Register a DisposableBean implementation that performs all destruction
    // work for the given bean: DestructionAwareBeanPostProcessors,
    // DisposableBean interface, custom destroy method.

    • bean的销毁分单例和多例的,感兴趣可以https://developer.aliyun.com/article/1118223,具体不分析了,比较底层了。
    • 只需要知道registerDisposableBean,当bean为单例的情况下,会由DisposableBeanAdapter进行销毁前置处理,所以这里将DisposableBeanAdapter注册进去。

    而 DisposableBeanAdapter:org.springframework.beans.factory.support.DisposableBeanAdapter#destroy方法

    public void destroy() {
        if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
            Iterator var1 = this.beanPostProcessors.iterator();
    
            while(var1.hasNext()) {
                DestructionAwareBeanPostProcessor processor = (DestructionAwareBeanPostProcessor)var1.next();
                // 至关重要的!
                processor.postProcessBeforeDestruction(this.bean, this.beanName);
            }
        }
    
        if (this.invokeDisposableBean) {
            if (logger.isTraceEnabled()) {
                logger.trace("Invoking destroy() on bean with name '" + this.beanName + "'");
            }
    
            try {
                if (System.getSecurityManager() != null) {
                    AccessController.doPrivileged(() -> {
                        ((DisposableBean)this.bean).destroy();
                        return null;
                    }, this.acc);
                } else {
                    ((DisposableBean)this.bean).destroy();
                }
            } catch (Throwable var3) {
                String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'";
                if (logger.isDebugEnabled()) {
                    logger.warn(msg, var3);
                } else {
                    logger.warn(msg + ": " + var3);
                }
            }
        }
    
        if (this.destroyMethod != null) {
            this.invokeCustomDestroyMethod(this.destroyMethod);
        } else if (this.destroyMethodName != null) {
            Method methodToInvoke = this.determineDestroyMethod(this.destroyMethodName);
            if (methodToInvoke != null) {
                this.invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(methodToInvoke));
            }
        }
    
    }
    
    • 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

    这里postProcessBeforeDestruction是一个beanPostProcessor类的拓展点,会调用bean销毁的前置方法。

    public interface DestructionAwareBeanPostProcessor extends BeanPostProcessor {
        void postProcessBeforeDestruction(Object var1, String var2) throws BeansException;
    
        default boolean requiresDestruction(Object bean) {
            return true;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    可以自己实现postProcessBeforeDestruction方法,作为销毁类前的拓展点。

    还有总结梳理见下一篇

  • 相关阅读:
    ​软考-高级-信息系统项目管理师教程 第四版【第16章-项目采购管理-思维导图】​
    事件绑定-回调函数
    java计算机毕业设计扶贫信息管理系统源码+系统+lw文档+mysql数据库+部署
    聚酰胺-胺(PAMAM)树形聚合物-硫化铋复合纳米粒子|硫化铋修饰Gd‑DTPA‑OA配体|科研实验用
    git使用---本地目录初始化关联远程仓库
    DOM—节点操作
    五种常见的IO模型
    Electron App 安装包定制 -- Inno Setup 脚本 Pascal Scripting 初探
    【实用工具】谷歌浏览器插件开发指南
    VuePress的简单使用
  • 原文地址:https://blog.csdn.net/qq_41076797/article/details/131146358