Merge branch '5.1.x'

# Conflicts:
#	build.gradle
#	spring-aop/src/main/java/org/springframework/aop/framework/CglibAopProxy.java
#	spring-aspects/spring-aspects.gradle
#	spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java
#	spring-beans/src/main/java/org/springframework/beans/factory/support/GenericBeanDefinition.java
#	spring-beans/src/test/java/org/springframework/beans/factory/DefaultListableBeanFactoryTests.java
#	spring-orm/spring-orm.gradle
#	spring-test/spring-test.gradle
This commit is contained in:
Juergen Hoeller
2019-09-25 12:43:24 +02:00
20 changed files with 129 additions and 113 deletions

View File

@@ -256,7 +256,7 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName)
throws BeanCreationException {
// Let's check for lookup methods here..
// Let's check for lookup methods here...
if (!this.lookupMethodsChecked.contains(beanName)) {
if (AnnotationUtils.isCandidateClass(beanClass, Lookup.class)) {
try {
@@ -268,7 +268,8 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
Assert.state(this.beanFactory != null, "No BeanFactory available");
LookupOverride override = new LookupOverride(method, lookup.value());
try {
RootBeanDefinition mbd = (RootBeanDefinition) this.beanFactory.getMergedBeanDefinition(beanName);
RootBeanDefinition mbd = (RootBeanDefinition)
this.beanFactory.getMergedBeanDefinition(beanName);
mbd.getMethodOverrides().addOverride(override);
}
catch (NoSuchBeanDefinitionException ex) {

View File

@@ -408,7 +408,7 @@ public class ConstructorArgumentValues {
for (Map.Entry<Integer, ValueHolder> entry : this.indexedArgumentValues.entrySet()) {
ValueHolder vh1 = entry.getValue();
ValueHolder vh2 = that.indexedArgumentValues.get(entry.getKey());
if (!vh1.contentEquals(vh2)) {
if (vh2 == null || !vh1.contentEquals(vh2)) {
return false;
}
}

View File

@@ -181,8 +181,7 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
@Nullable
private MutablePropertyValues propertyValues;
@Nullable
private MethodOverrides methodOverrides;
private MethodOverrides methodOverrides = new MethodOverrides();
@Nullable
private String initMethodName;
@@ -903,9 +902,6 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
* <p>Never returns {@code null}.
*/
public MethodOverrides getMethodOverrides() {
if (this.methodOverrides == null) {
this.methodOverrides = new MethodOverrides();
}
return this.methodOverrides;
}
@@ -914,7 +910,7 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
* @since 5.0.2
*/
public boolean hasMethodOverrides() {
return (this.methodOverrides != null && !this.methodOverrides.isEmpty());
return !this.methodOverrides.isEmpty();
}
/**
@@ -1098,10 +1094,9 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
public void validate() throws BeanDefinitionValidationException {
if (hasMethodOverrides() && getFactoryMethodName() != null) {
throw new BeanDefinitionValidationException(
"Cannot combine static factory method with method overrides: " +
"the static factory method must create the instance");
"Cannot combine factory method with container-generated method overrides: " +
"the factory method must create the concrete bean instance.");
}
if (hasBeanClass()) {
prepareMethodOverrides();
}
@@ -1113,14 +1108,9 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
* @throws BeanDefinitionValidationException in case of validation failure
*/
public void prepareMethodOverrides() throws BeanDefinitionValidationException {
// Check that lookup methods exists.
// Check that lookup methods exist and determine their overloaded status.
if (hasMethodOverrides()) {
Set<MethodOverride> overrides = getMethodOverrides().getOverrides();
synchronized (overrides) {
for (MethodOverride mo : overrides) {
prepareMethodOverride(mo);
}
}
getMethodOverrides().getOverrides().forEach(this::prepareMethodOverride);
}
}

View File

@@ -201,7 +201,7 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt
public int accept(Method method) {
MethodOverride methodOverride = getBeanDefinition().getMethodOverrides().getOverride(method);
if (logger.isTraceEnabled()) {
logger.trace("Override for '" + method.getName() + "' is [" + methodOverride + "]");
logger.trace("MethodOverride for " + method + ": " + methodOverride);
}
if (methodOverride == null) {
return PASSTHROUGH;

View File

@@ -325,7 +325,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
this.allowEagerClassLoading = otherListableFactory.allowEagerClassLoading;
this.dependencyComparator = otherListableFactory.dependencyComparator;
// A clone of the AutowireCandidateResolver since it is potentially BeanFactoryAware...
setAutowireCandidateResolver(BeanUtils.instantiateClass(otherListableFactory.getAutowireCandidateResolver().getClass()));
setAutowireCandidateResolver(
BeanUtils.instantiateClass(otherListableFactory.getAutowireCandidateResolver().getClass()));
// Make resolvable dependencies (e.g. ResourceLoader) available here as well...
this.resolvableDependencies.putAll(otherListableFactory.resolvableDependencies);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2019 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.
@@ -18,6 +18,7 @@ package org.springframework.beans.factory.support;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.lang.Nullable;
import org.springframework.util.ObjectUtils;
/**
* GenericBeanDefinition is a one-stop shop for standard bean definition purposes.
@@ -84,7 +85,14 @@ public class GenericBeanDefinition extends AbstractBeanDefinition {
@Override
public boolean equals(@Nullable Object other) {
return (this == other || (other instanceof GenericBeanDefinition && super.equals(other)));
if (this == other) {
return true;
}
if (!(other instanceof GenericBeanDefinition)) {
return false;
}
GenericBeanDefinition that = (GenericBeanDefinition) other;
return (ObjectUtils.nullSafeEquals(this.parentName, that.parentName) && super.equals(other));
}
@Override

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2019 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.
@@ -17,9 +17,8 @@
package org.springframework.beans.factory.support;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import org.springframework.lang.Nullable;
@@ -37,9 +36,7 @@ import org.springframework.lang.Nullable;
*/
public class MethodOverrides {
private final Set<MethodOverride> overrides = Collections.synchronizedSet(new LinkedHashSet<>(2));
private volatile boolean modified = false;
private final Set<MethodOverride> overrides = new CopyOnWriteArraySet<>();
/**
@@ -61,7 +58,6 @@ public class MethodOverrides {
*/
public void addOverrides(@Nullable MethodOverrides other) {
if (other != null) {
this.modified = true;
this.overrides.addAll(other.overrides);
}
}
@@ -70,7 +66,6 @@ public class MethodOverrides {
* Add the given method override.
*/
public void addOverride(MethodOverride override) {
this.modified = true;
this.overrides.add(override);
}
@@ -80,7 +75,6 @@ public class MethodOverrides {
* @see MethodOverride
*/
public Set<MethodOverride> getOverrides() {
this.modified = true;
return this.overrides;
}
@@ -88,7 +82,7 @@ public class MethodOverrides {
* Return whether the set of method overrides is empty.
*/
public boolean isEmpty() {
return (!this.modified || this.overrides.isEmpty());
return this.overrides.isEmpty();
}
/**
@@ -98,18 +92,13 @@ public class MethodOverrides {
*/
@Nullable
public MethodOverride getOverride(Method method) {
if (!this.modified) {
return null;
}
synchronized (this.overrides) {
MethodOverride match = null;
for (MethodOverride candidate : this.overrides) {
if (candidate.matches(method)) {
match = candidate;
}
MethodOverride match = null;
for (MethodOverride candidate : this.overrides) {
if (candidate.matches(method)) {
match = candidate;
}
return match;
}
return match;
}
@@ -123,7 +112,6 @@ public class MethodOverrides {
}
MethodOverrides that = (MethodOverrides) other;
return this.overrides.equals(that.overrides);
}
@Override

View File

@@ -856,6 +856,18 @@ class DefaultListableBeanFactoryTests {
lbf.registerAlias("test", "test3");
}
@Test
void aliasChaining() {
lbf.registerBeanDefinition("test", new RootBeanDefinition(NestedTestBean.class));
lbf.registerAlias("test", "testAlias");
lbf.registerAlias("testAlias", "testAlias2");
lbf.registerAlias("testAlias2", "testAlias3");
Object bean = lbf.getBean("test");
assertThat(lbf.getBean("testAlias")).isSameAs(bean);
assertThat(lbf.getBean("testAlias2")).isSameAs(bean);
assertThat(lbf.getBean("testAlias3")).isSameAs(bean);
}
@Test
void beanDefinitionOverriding() {
lbf.registerBeanDefinition("test", new RootBeanDefinition(TestBean.class));
@@ -866,6 +878,43 @@ class DefaultListableBeanFactoryTests {
assertThat(lbf.getBean("test2")).isInstanceOf(NestedTestBean.class);
}
@Test
void beanDefinitionOverridingNotAllowed() {
lbf.setAllowBeanDefinitionOverriding(false);
BeanDefinition oldDef = new RootBeanDefinition(TestBean.class);
BeanDefinition newDef = new RootBeanDefinition(NestedTestBean.class);
lbf.registerBeanDefinition("test", oldDef);
assertThatExceptionOfType(BeanDefinitionOverrideException.class).isThrownBy(() ->
lbf.registerBeanDefinition("test", newDef))
.satisfies(ex -> {
assertThat(ex.getBeanName()).isEqualTo("test");
assertThat(ex.getBeanDefinition()).isEqualTo(newDef);
assertThat(ex.getExistingDefinition()).isEqualTo(oldDef);
});
}
@Test
void beanDefinitionOverridingWithAlias() {
lbf.registerBeanDefinition("test", new RootBeanDefinition(TestBean.class));
lbf.registerAlias("test", "testAlias");
lbf.registerBeanDefinition("test", new RootBeanDefinition(NestedTestBean.class));
lbf.registerAlias("test", "testAlias");
assertThat(lbf.getBean("test")).isInstanceOf(NestedTestBean.class);
assertThat(lbf.getBean("testAlias")).isInstanceOf(NestedTestBean.class);
}
@Test
void beanDefinitionOverridingWithConstructorArgumentMismatch() {
RootBeanDefinition bd1 = new RootBeanDefinition(NestedTestBean.class);
bd1.getConstructorArgumentValues().addIndexedArgumentValue(1, "value1");
lbf.registerBeanDefinition("test", bd1);
RootBeanDefinition bd2 = new RootBeanDefinition(NestedTestBean.class);
bd2.getConstructorArgumentValues().addIndexedArgumentValue(0, "value0");
lbf.registerBeanDefinition("test", bd2);
assertThat(lbf.getBean("test")).isInstanceOf(NestedTestBean.class);
assertThat(lbf.getBean("test", NestedTestBean.class).getCompany()).isEqualTo("value0");
}
@Test
void beanDefinitionRemoval() {
lbf.setAllowBeanDefinitionOverriding(false);
@@ -908,43 +957,6 @@ class DefaultListableBeanFactoryTests {
lbf.removeBeanDefinition(name);
}
@Test
void beanDefinitionOverridingNotAllowed() {
lbf.setAllowBeanDefinitionOverriding(false);
BeanDefinition oldDef = new RootBeanDefinition(TestBean.class);
BeanDefinition newDef = new RootBeanDefinition(NestedTestBean.class);
lbf.registerBeanDefinition("test", oldDef);
assertThatExceptionOfType(BeanDefinitionOverrideException.class).isThrownBy(() ->
lbf.registerBeanDefinition("test", newDef))
.satisfies(ex -> {
assertThat(ex.getBeanName()).isEqualTo("test");
assertThat(ex.getBeanDefinition()).isEqualTo(newDef);
assertThat(ex.getExistingDefinition()).isEqualTo(oldDef);
});
}
@Test
void beanDefinitionOverridingWithAlias() {
lbf.registerBeanDefinition("test", new RootBeanDefinition(TestBean.class));
lbf.registerAlias("test", "testAlias");
lbf.registerBeanDefinition("test", new RootBeanDefinition(NestedTestBean.class));
lbf.registerAlias("test", "testAlias");
assertThat(lbf.getBean("test")).isInstanceOf(NestedTestBean.class);
assertThat(lbf.getBean("testAlias")).isInstanceOf(NestedTestBean.class);
}
@Test
void aliasChaining() {
lbf.registerBeanDefinition("test", new RootBeanDefinition(NestedTestBean.class));
lbf.registerAlias("test", "testAlias");
lbf.registerAlias("testAlias", "testAlias2");
lbf.registerAlias("testAlias2", "testAlias3");
Object bean = lbf.getBean("test");
assertThat(lbf.getBean("testAlias")).isSameAs(bean);
assertThat(lbf.getBean("testAlias2")).isSameAs(bean);
assertThat(lbf.getBean("testAlias3")).isSameAs(bean);
}
@Test
void beanReferenceWithNewSyntax() {
Properties p = new Properties();

View File

@@ -114,6 +114,27 @@ public class BeanDefinitionTests {
assertThat(bd.hashCode() == otherBd.hashCode()).isTrue();
}
@Test
public void genericBeanDefinitionEquality() {
GenericBeanDefinition bd = new GenericBeanDefinition();
bd.setParentName("parent");
bd.setScope("request");
bd.setAbstract(true);
bd.setLazyInit(true);
GenericBeanDefinition otherBd = new GenericBeanDefinition();
otherBd.setScope("request");
otherBd.setAbstract(true);
otherBd.setLazyInit(true);
boolean condition1 = !bd.equals(otherBd);
assertTrue(condition1);
boolean condition = !otherBd.equals(bd);
assertTrue(condition);
otherBd.setParentName("parent");
assertTrue(bd.equals(otherBd));
assertTrue(otherBd.equals(bd));
assertTrue(bd.hashCode() == otherBd.hashCode());
}
@Test
public void beanDefinitionHolderEquality() {
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);