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:
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user