From 860e22171f98a6c9ed50969fabb0c7832eb1041e Mon Sep 17 00:00:00 2001 From: Christoph Dreis Date: Wed, 11 Mar 2020 19:30:17 +0100 Subject: [PATCH] Improve performance of AbstractAutowireCapableBeanFactory#predictBeanType --- ...ctBeanFactoryBasedTargetSourceCreator.java | 4 +- .../AbstractAutowireCapableBeanFactory.java | 42 ++++++++----------- .../factory/support/AbstractBeanFactory.java | 35 +++++++++++++++- .../support/ScriptFactoryPostProcessor.java | 4 +- 4 files changed, 58 insertions(+), 27 deletions(-) diff --git a/spring-aop/src/main/java/org/springframework/aop/framework/autoproxy/target/AbstractBeanFactoryBasedTargetSourceCreator.java b/spring-aop/src/main/java/org/springframework/aop/framework/autoproxy/target/AbstractBeanFactoryBasedTargetSourceCreator.java index 4fd173f2893e..c15593675641 100644 --- a/spring-aop/src/main/java/org/springframework/aop/framework/autoproxy/target/AbstractBeanFactoryBasedTargetSourceCreator.java +++ b/spring-aop/src/main/java/org/springframework/aop/framework/autoproxy/target/AbstractBeanFactoryBasedTargetSourceCreator.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -150,6 +150,8 @@ protected DefaultListableBeanFactory buildInternalBeanFactory(ConfigurableBeanFa // since those are only meant to apply to beans defined in the original factory. internalBeanFactory.getBeanPostProcessors().removeIf(beanPostProcessor -> beanPostProcessor instanceof AopInfrastructureBean); + internalBeanFactory.getSmartBeanPostProcessors().removeIf(beanPostProcessor -> + beanPostProcessor instanceof AopInfrastructureBean); return internalBeanFactory; } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java index 516cb180c86d..1a20ce06c7a9 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -649,16 +649,14 @@ protected Class predictBeanType(String beanName, RootBeanDefinition mbd, Clas Class targetType = determineTargetType(beanName, mbd, typesToMatch); // Apply SmartInstantiationAwareBeanPostProcessors to predict the // eventual type after a before-instantiation shortcut. - if (targetType != null && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { + if (targetType != null && !mbd.isSynthetic() && hasSmartInstantiationAwareBeanPostProcessors()) { boolean matchingOnlyFactoryBean = typesToMatch.length == 1 && typesToMatch[0] == FactoryBean.class; - for (BeanPostProcessor bp : getBeanPostProcessors()) { - if (bp instanceof SmartInstantiationAwareBeanPostProcessor) { - SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp; - Class predicted = ibp.predictBeanType(targetType, beanName); - if (predicted != null && - (!matchingOnlyFactoryBean || FactoryBean.class.isAssignableFrom(predicted))) { - return predicted; - } + for (BeanPostProcessor bp : getSmartBeanPostProcessors()) { + SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp; + Class predicted = ibp.predictBeanType(targetType, beanName); + if (predicted != null && + (!matchingOnlyFactoryBean || FactoryBean.class.isAssignableFrom(predicted))) { + return predicted; } } } @@ -958,12 +956,10 @@ protected Class getTypeForFactoryBean(String beanName, RootBeanDefinition mbd */ protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) { Object exposedObject = bean; - if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { - for (BeanPostProcessor bp : getBeanPostProcessors()) { - if (bp instanceof SmartInstantiationAwareBeanPostProcessor) { - SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp; - exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName); - } + if (!mbd.isSynthetic() && hasSmartInstantiationAwareBeanPostProcessors()) { + for (BeanPostProcessor bp : getSmartBeanPostProcessors()) { + SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp; + exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName); } } return exposedObject; @@ -1279,14 +1275,12 @@ protected Object getObjectForBeanInstance( protected Constructor[] determineConstructorsFromBeanPostProcessors(@Nullable Class beanClass, String beanName) throws BeansException { - if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) { - for (BeanPostProcessor bp : getBeanPostProcessors()) { - if (bp instanceof SmartInstantiationAwareBeanPostProcessor) { - SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp; - Constructor[] ctors = ibp.determineCandidateConstructors(beanClass, beanName); - if (ctors != null) { - return ctors; - } + if (beanClass != null && hasSmartInstantiationAwareBeanPostProcessors()) { + for (BeanPostProcessor bp : getSmartBeanPostProcessors()) { + SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp; + Constructor[] ctors = ibp.determineCandidateConstructors(beanClass, beanName); + if (ctors != null) { + return ctors; } } } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java index 3457d2bfe25b..7eaf64aa42ee 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java @@ -65,6 +65,7 @@ import org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor; import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor; import org.springframework.beans.factory.config.Scope; +import org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor; import org.springframework.core.AttributeAccessor; import org.springframework.core.DecoratingClassLoader; import org.springframework.core.NamedThreadLocal; @@ -153,9 +154,15 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp /** BeanPostProcessors to apply in createBean. */ private final List beanPostProcessors = new CopyOnWriteArrayList<>(); + /** Smart BeanPostProcessors to apply when predicting bean types. */ + private final List smartBeanPostProcessors = new CopyOnWriteArrayList<>(); + /** Indicates whether any InstantiationAwareBeanPostProcessors have been registered. */ private volatile boolean hasInstantiationAwareBeanPostProcessors; + /** Indicates whether any SmartInstantiationAwareBeanPostProcessor have been registered. */ + private volatile boolean hasSmartInstantiationAwareBeanPostProcessors; + /** Indicates whether any DestructionAwareBeanPostProcessors have been registered. */ private volatile boolean hasDestructionAwareBeanPostProcessors; @@ -923,6 +930,11 @@ public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) { if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) { this.hasInstantiationAwareBeanPostProcessors = true; } + if (beanPostProcessor instanceof SmartInstantiationAwareBeanPostProcessor) { + this.smartBeanPostProcessors.remove(beanPostProcessor); + this.hasSmartInstantiationAwareBeanPostProcessors = true; + this.smartBeanPostProcessors.add(beanPostProcessor); + } if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) { this.hasDestructionAwareBeanPostProcessors = true; } @@ -943,9 +955,17 @@ public List getBeanPostProcessors() { return this.beanPostProcessors; } + /** + * Return the list of smart BeanPostProcessors that will get applied + * to beans created with this factory. + */ + public List getSmartBeanPostProcessors() { + return this.smartBeanPostProcessors; + } + /** * Return whether this factory holds a InstantiationAwareBeanPostProcessor - * that will get applied to singleton beans on shutdown. + * that will get applied to singleton beans on creation. * @see #addBeanPostProcessor * @see org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor */ @@ -953,6 +973,16 @@ protected boolean hasInstantiationAwareBeanPostProcessors() { return this.hasInstantiationAwareBeanPostProcessors; } + /** + * Return whether this factory holds a SmartInstantiationAwareBeanPostProcessor + * that will get applied to singleton beans on creation. + * @see #addBeanPostProcessor + * @see org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor + */ + protected boolean hasSmartInstantiationAwareBeanPostProcessors() { + return this.hasSmartInstantiationAwareBeanPostProcessors; + } + /** * Return whether this factory holds a DestructionAwareBeanPostProcessor * that will get applied to singleton beans on shutdown. @@ -1028,8 +1058,11 @@ public void copyConfigurationFrom(ConfigurableBeanFactory otherFactory) { this.customEditors.putAll(otherAbstractFactory.customEditors); this.typeConverter = otherAbstractFactory.typeConverter; this.beanPostProcessors.addAll(otherAbstractFactory.beanPostProcessors); + this.smartBeanPostProcessors.addAll(otherAbstractFactory.smartBeanPostProcessors); this.hasInstantiationAwareBeanPostProcessors = this.hasInstantiationAwareBeanPostProcessors || otherAbstractFactory.hasInstantiationAwareBeanPostProcessors; + this.hasSmartInstantiationAwareBeanPostProcessors = this.hasSmartInstantiationAwareBeanPostProcessors || + otherAbstractFactory.hasSmartInstantiationAwareBeanPostProcessors; this.hasDestructionAwareBeanPostProcessors = this.hasDestructionAwareBeanPostProcessors || otherAbstractFactory.hasDestructionAwareBeanPostProcessors; this.scopes.putAll(otherAbstractFactory.scopes); diff --git a/spring-context/src/main/java/org/springframework/scripting/support/ScriptFactoryPostProcessor.java b/spring-context/src/main/java/org/springframework/scripting/support/ScriptFactoryPostProcessor.java index dfe735b5634a..003520906f7a 100644 --- a/spring-context/src/main/java/org/springframework/scripting/support/ScriptFactoryPostProcessor.java +++ b/spring-context/src/main/java/org/springframework/scripting/support/ScriptFactoryPostProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -234,6 +234,8 @@ public void setBeanFactory(BeanFactory beanFactory) { // since those are only meant to apply to beans defined in the original factory. this.scriptBeanFactory.getBeanPostProcessors().removeIf(beanPostProcessor -> beanPostProcessor instanceof AopInfrastructureBean); + this.scriptBeanFactory.getSmartBeanPostProcessors().removeIf(beanPostProcessor -> + beanPostProcessor instanceof AopInfrastructureBean); } @Override