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 fcef74b56ef..6bb3f913db1 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-2021 the original author or authors. + * Copyright 2002-2023 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. @@ -34,6 +34,7 @@ import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.support.GenericBeanDefinition; import org.springframework.lang.Nullable; +import org.springframework.util.Assert; /** * Convenient superclass for @@ -81,6 +82,11 @@ public abstract class AbstractBeanFactoryBasedTargetSourceCreator return this.beanFactory; } + private ConfigurableBeanFactory getConfigurableBeanFactory() { + Assert.state(this.beanFactory != null, "BeanFactory not set"); + return this.beanFactory; + } + //--------------------------------------------------------------------- // Implementation of the TargetSourceCreator interface @@ -104,7 +110,7 @@ public abstract class AbstractBeanFactoryBasedTargetSourceCreator // We need to override just this bean definition, as it may reference other beans // and we're happy to take the parent's definition for those. // Always use prototype scope if demanded. - BeanDefinition bd = this.beanFactory.getMergedBeanDefinition(beanName); + BeanDefinition bd = getConfigurableBeanFactory().getMergedBeanDefinition(beanName); GenericBeanDefinition bdCopy = new GenericBeanDefinition(bd); if (isPrototypeBased()) { bdCopy.setScope(BeanDefinition.SCOPE_PROTOTYPE); @@ -126,7 +132,7 @@ public abstract class AbstractBeanFactoryBasedTargetSourceCreator protected DefaultListableBeanFactory getInternalBeanFactoryForBean(String beanName) { synchronized (this.internalBeanFactories) { return this.internalBeanFactories.computeIfAbsent(beanName, - name -> buildInternalBeanFactory(this.beanFactory)); + name -> buildInternalBeanFactory(getConfigurableBeanFactory())); } } diff --git a/spring-aop/src/main/java/org/springframework/aop/target/AbstractBeanFactoryBasedTargetSource.java b/spring-aop/src/main/java/org/springframework/aop/target/AbstractBeanFactoryBasedTargetSource.java index 78c6d3abf6d..9b637a59b68 100644 --- a/spring-aop/src/main/java/org/springframework/aop/target/AbstractBeanFactoryBasedTargetSource.java +++ b/spring-aop/src/main/java/org/springframework/aop/target/AbstractBeanFactoryBasedTargetSource.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2023 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. @@ -24,6 +24,8 @@ import org.apache.commons.logging.LogFactory; import org.springframework.aop.TargetSource; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; +import org.springframework.lang.Nullable; +import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; /** @@ -57,15 +59,18 @@ public abstract class AbstractBeanFactoryBasedTargetSource implements TargetSour protected final Log logger = LogFactory.getLog(getClass()); /** Name of the target bean we will create on each invocation. */ + @Nullable private String targetBeanName; /** Class of the target. */ + @Nullable private volatile Class targetClass; /** * BeanFactory that owns this TargetSource. We need to hold onto this * reference so that we can create new prototype instances as necessary. */ + @Nullable private BeanFactory beanFactory; @@ -86,6 +91,7 @@ public abstract class AbstractBeanFactoryBasedTargetSource implements TargetSour * Return the name of the target bean in the factory. */ public String getTargetBeanName() { + Assert.state(this.targetBeanName != null, "Target bean name not set"); return this.targetBeanName; } @@ -115,11 +121,13 @@ public abstract class AbstractBeanFactoryBasedTargetSource implements TargetSour * Return the owning BeanFactory. */ public BeanFactory getBeanFactory() { + Assert.state(this.beanFactory != null, "BeanFactory not set"); return this.beanFactory; } @Override + @Nullable public Class getTargetClass() { Class targetClass = this.targetClass; if (targetClass != null) { @@ -128,7 +136,7 @@ public abstract class AbstractBeanFactoryBasedTargetSource implements TargetSour synchronized (this) { // Full check within synchronization, entering the BeanFactory interaction algorithm only once... targetClass = this.targetClass; - if (targetClass == null && this.beanFactory != null) { + if (targetClass == null && this.beanFactory != null && this.targetBeanName != null) { // Determine type of the target bean. targetClass = this.beanFactory.getType(this.targetBeanName); if (targetClass == null) { @@ -182,18 +190,16 @@ public abstract class AbstractBeanFactoryBasedTargetSource implements TargetSour @Override public int hashCode() { - int hashCode = getClass().hashCode(); - hashCode = 13 * hashCode + ObjectUtils.nullSafeHashCode(this.beanFactory); - hashCode = 13 * hashCode + ObjectUtils.nullSafeHashCode(this.targetBeanName); - return hashCode; + return getClass().hashCode() * 13 + ObjectUtils.nullSafeHashCode(this.targetBeanName); } @Override public String toString() { StringBuilder sb = new StringBuilder(getClass().getSimpleName()); sb.append(" for target bean '").append(this.targetBeanName).append('\''); - if (this.targetClass != null) { - sb.append(" of type [").append(this.targetClass.getName()).append(']'); + Class targetClass = this.targetClass; + if (targetClass != null) { + sb.append(" of type [").append(targetClass.getName()).append(']'); } return sb.toString(); } diff --git a/spring-aop/src/main/java/org/springframework/aop/target/AbstractLazyCreationTargetSource.java b/spring-aop/src/main/java/org/springframework/aop/target/AbstractLazyCreationTargetSource.java index f742a106bab..8246e1e6268 100644 --- a/spring-aop/src/main/java/org/springframework/aop/target/AbstractLazyCreationTargetSource.java +++ b/spring-aop/src/main/java/org/springframework/aop/target/AbstractLazyCreationTargetSource.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2023 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. @@ -46,6 +46,7 @@ public abstract class AbstractLazyCreationTargetSource implements TargetSource { protected final Log logger = LogFactory.getLog(getClass()); /** The lazily initialized target object. */ + @Nullable private Object lazyTarget; diff --git a/spring-aop/src/main/java/org/springframework/aop/target/EmptyTargetSource.java b/spring-aop/src/main/java/org/springframework/aop/target/EmptyTargetSource.java index 2ebcc216dce..22785ce0fa7 100644 --- a/spring-aop/src/main/java/org/springframework/aop/target/EmptyTargetSource.java +++ b/spring-aop/src/main/java/org/springframework/aop/target/EmptyTargetSource.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2023 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. @@ -70,6 +70,7 @@ public final class EmptyTargetSource implements TargetSource, Serializable { // Instance implementation //--------------------------------------------------------------------- + @Nullable private final Class targetClass; private final boolean isStatic; diff --git a/spring-aop/src/main/java/org/springframework/aop/target/HotSwappableTargetSource.java b/spring-aop/src/main/java/org/springframework/aop/target/HotSwappableTargetSource.java index 5d85f504386..18cc5d22e3c 100644 --- a/spring-aop/src/main/java/org/springframework/aop/target/HotSwappableTargetSource.java +++ b/spring-aop/src/main/java/org/springframework/aop/target/HotSwappableTargetSource.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2023 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. @@ -95,8 +95,7 @@ public class HotSwappableTargetSource implements TargetSource, Serializable { /** - * Two HotSwappableTargetSources are equal if the current target - * objects are equal. + * Two HotSwappableTargetSources are equal if the current target objects are equal. */ @Override public boolean equals(Object other) { diff --git a/spring-aop/src/main/java/org/springframework/aop/target/SingletonTargetSource.java b/spring-aop/src/main/java/org/springframework/aop/target/SingletonTargetSource.java index 24ae9865a6d..85f84128a09 100644 --- a/spring-aop/src/main/java/org/springframework/aop/target/SingletonTargetSource.java +++ b/spring-aop/src/main/java/org/springframework/aop/target/SingletonTargetSource.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2023 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. @@ -82,14 +82,8 @@ public class SingletonTargetSource implements TargetSource, Serializable { */ @Override public boolean equals(Object other) { - if (this == other) { - return true; - } - if (!(other instanceof SingletonTargetSource)) { - return false; - } - SingletonTargetSource otherTargetSource = (SingletonTargetSource) other; - return this.target.equals(otherTargetSource.target); + return (this == other || (other instanceof SingletonTargetSource && + this.target.equals(((SingletonTargetSource) other).target))); } /** diff --git a/spring-aop/src/main/java/org/springframework/aop/target/ThreadLocalTargetSource.java b/spring-aop/src/main/java/org/springframework/aop/target/ThreadLocalTargetSource.java index 5c4b03c7849..dc585654b95 100644 --- a/spring-aop/src/main/java/org/springframework/aop/target/ThreadLocalTargetSource.java +++ b/spring-aop/src/main/java/org/springframework/aop/target/ThreadLocalTargetSource.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2016 the original author or authors. + * Copyright 2002-2023 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. @@ -58,7 +58,12 @@ public class ThreadLocalTargetSource extends AbstractPrototypeBasedTargetSource * is meant to be per thread per instance of the ThreadLocalTargetSource class. */ private final ThreadLocal targetInThread = - new NamedThreadLocal<>("Thread-local instance of bean '" + getTargetBeanName() + "'"); + new NamedThreadLocal("Thread-local instance of bean") { + @Override + public String toString() { + return super.toString() + " '" + getTargetBeanName() + "'"; + } + }; /** * Set of managed targets, enabling us to keep track of the targets we've created.