Merge branch '6.0.x'
This commit is contained in:
commit
cf3a25bfac
|
@ -265,18 +265,32 @@ public class ProxyFactoryBean extends ProxyCreatorSupport
|
|||
* Return the type of the proxy. Will check the singleton instance if
|
||||
* already created, else fall back to the proxy interface (in case of just
|
||||
* a single one), the target bean type, or the TargetSource's target class.
|
||||
* @see org.springframework.aop.TargetSource#getTargetClass
|
||||
* @see org.springframework.aop.framework.AopProxy#getProxyClass
|
||||
*/
|
||||
@Override
|
||||
@Nullable
|
||||
public Class<?> getObjectType() {
|
||||
synchronized (this) {
|
||||
if (this.singletonInstance != null) {
|
||||
return this.singletonInstance.getClass();
|
||||
}
|
||||
}
|
||||
// This might be incomplete since it potentially misses introduced interfaces
|
||||
// from Advisors that will be lazily retrieved via setInterceptorNames.
|
||||
return createAopProxy().getProxyClass(this.proxyClassLoader);
|
||||
try {
|
||||
// This might be incomplete since it potentially misses introduced interfaces
|
||||
// from Advisors that will be lazily retrieved via setInterceptorNames.
|
||||
return createAopProxy().getProxyClass(this.proxyClassLoader);
|
||||
}
|
||||
catch (AopConfigException ex) {
|
||||
if (getTargetClass() == null) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Failed to determine early proxy class: " + ex.getMessage());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -136,7 +136,6 @@ public abstract class ClassFilters {
|
|||
public String toString() {
|
||||
return getClass().getName() + ": " + Arrays.toString(this.filters);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -177,7 +176,6 @@ public abstract class ClassFilters {
|
|||
public String toString() {
|
||||
return getClass().getName() + ": " + Arrays.toString(this.filters);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -70,6 +70,7 @@ class BeanDefinitionPropertyValueCodeGenerator {
|
|||
|
||||
BeanDefinitionPropertyValueCodeGenerator(GeneratedMethods generatedMethods,
|
||||
@Nullable BiFunction<Object, ResolvableType, CodeBlock> customValueGenerator) {
|
||||
|
||||
this.generatedMethods = generatedMethods;
|
||||
this.delegates = new ArrayList<>();
|
||||
if (customValueGenerator != null) {
|
||||
|
@ -145,7 +146,6 @@ class BeanDefinitionPropertyValueCodeGenerator {
|
|||
|
||||
@Nullable
|
||||
CodeBlock generateCode(Object value, ResolvableType type);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -165,7 +165,6 @@ class BeanDefinitionPropertyValueCodeGenerator {
|
|||
'\\', "\\\\"
|
||||
);
|
||||
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public CodeBlock generateCode(Object value, ResolvableType type) {
|
||||
|
@ -233,7 +232,6 @@ class BeanDefinitionPropertyValueCodeGenerator {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -323,8 +321,8 @@ class BeanDefinitionPropertyValueCodeGenerator {
|
|||
this.emptyResult = emptyResult;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
@Nullable
|
||||
public CodeBlock generateCode(Object value, ResolvableType type) {
|
||||
if (this.collectionType.isInstance(value)) {
|
||||
|
|
|
@ -445,7 +445,7 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean
|
|||
* @see #getResource
|
||||
* @see Lazy
|
||||
*/
|
||||
protected Object buildLazyResourceProxy(final LookupElement element, final @Nullable String requestingBeanName) {
|
||||
protected Object buildLazyResourceProxy(LookupElement element, @Nullable String requestingBeanName) {
|
||||
TargetSource ts = new TargetSource() {
|
||||
@Override
|
||||
public Class<?> getTargetClass() {
|
||||
|
@ -525,16 +525,16 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean
|
|||
String name = element.name;
|
||||
|
||||
if (factory instanceof AutowireCapableBeanFactory autowireCapableBeanFactory) {
|
||||
DependencyDescriptor descriptor = element.getDependencyDescriptor();
|
||||
if (this.fallbackToDefaultTypeMatch && element.isDefaultName && !factory.containsBean(name)) {
|
||||
autowiredBeanNames = new LinkedHashSet<>();
|
||||
resource = autowireCapableBeanFactory.resolveDependency(descriptor, requestingBeanName, autowiredBeanNames, null);
|
||||
resource = autowireCapableBeanFactory.resolveDependency(
|
||||
element.getDependencyDescriptor(), requestingBeanName, autowiredBeanNames, null);
|
||||
if (resource == null) {
|
||||
throw new NoSuchBeanDefinitionException(element.getLookupType(), "No resolvable resource object");
|
||||
}
|
||||
}
|
||||
else {
|
||||
resource = autowireCapableBeanFactory.resolveBeanByName(name, descriptor);
|
||||
resource = autowireCapableBeanFactory.resolveBeanByName(name, element.getDependencyDescriptor());
|
||||
autowiredBeanNames = Collections.singleton(name);
|
||||
}
|
||||
}
|
||||
|
@ -661,8 +661,6 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Class representing injection information about an annotated field
|
||||
* or setter method, supporting the @Resource annotation.
|
||||
|
|
|
@ -139,22 +139,24 @@ public class ProxyFactoryBeanTests {
|
|||
private void testDoubleTargetSourceIsRejected(String name) {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(new ClassPathResource(DBL_TARGETSOURCE_CONTEXT, CLASS));
|
||||
|
||||
assertThatExceptionOfType(BeanCreationException.class).as("Should not allow TargetSource to be specified in interceptorNames as well as targetSource property")
|
||||
.isThrownBy(() -> bf.getBean(name))
|
||||
.havingCause()
|
||||
.isInstanceOf(AopConfigException.class)
|
||||
.withMessageContaining("TargetSource");
|
||||
.isThrownBy(() -> bf.getBean(name))
|
||||
.havingCause()
|
||||
.isInstanceOf(AopConfigException.class)
|
||||
.withMessageContaining("TargetSource");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTargetSourceNotAtEndOfInterceptorNamesIsRejected() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(new ClassPathResource(NOTLAST_TARGETSOURCE_CONTEXT, CLASS));
|
||||
|
||||
assertThatExceptionOfType(BeanCreationException.class).as("TargetSource or non-advised object must be last in interceptorNames")
|
||||
.isThrownBy(() -> bf.getBean("targetSourceNotLast"))
|
||||
.havingCause()
|
||||
.isInstanceOf(AopConfigException.class)
|
||||
.withMessageContaining("interceptorNames");
|
||||
.isThrownBy(() -> bf.getBean("targetSourceNotLast"))
|
||||
.havingCause()
|
||||
.isInstanceOf(AopConfigException.class)
|
||||
.withMessageContaining("interceptorNames");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -171,7 +173,7 @@ public class ProxyFactoryBeanTests {
|
|||
assertThat(cba.getCalls()).isEqualTo(1);
|
||||
|
||||
ProxyFactoryBean pfb = (ProxyFactoryBean) bf.getBean("&directTarget");
|
||||
assertThat(TestBean.class.isAssignableFrom(pfb.getObjectType())).as("Has correct object type").isTrue();
|
||||
assertThat(pfb.getObjectType()).isAssignableTo(TestBean.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -181,7 +183,7 @@ public class ProxyFactoryBeanTests {
|
|||
ITestBean tb = (ITestBean) bf.getBean("viaTargetSource");
|
||||
assertThat(tb.getName()).isEqualTo("Adam");
|
||||
ProxyFactoryBean pfb = (ProxyFactoryBean) bf.getBean("&viaTargetSource");
|
||||
assertThat(TestBean.class.isAssignableFrom(pfb.getObjectType())).as("Has correct object type").isTrue();
|
||||
assertThat(pfb.getObjectType()).isAssignableTo(TestBean.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -190,11 +192,15 @@ public class ProxyFactoryBeanTests {
|
|||
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(new ClassPathResource(TARGETSOURCE_CONTEXT, CLASS));
|
||||
|
||||
ITestBean tb = (ITestBean) bf.getBean("noTarget");
|
||||
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() ->
|
||||
tb.getName())
|
||||
.withMessage("getName");
|
||||
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(tb::getName).withMessage("getName");
|
||||
FactoryBean<?> pfb = (ProxyFactoryBean) bf.getBean("&noTarget");
|
||||
assertThat(ITestBean.class.isAssignableFrom(pfb.getObjectType())).as("Has correct object type").isTrue();
|
||||
assertThat(pfb.getObjectType()).isAssignableTo(ITestBean.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetObjectTypeOnUninitializedFactoryBean() {
|
||||
ProxyFactoryBean pfb = new ProxyFactoryBean();
|
||||
assertThat(pfb.getObjectType()).isNull();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -227,12 +233,12 @@ public class ProxyFactoryBeanTests {
|
|||
|
||||
@Test
|
||||
public void testPrototypeInstancesAreNotEqual() {
|
||||
assertThat(ITestBean.class.isAssignableFrom(factory.getType("prototype"))).as("Has correct object type").isTrue();
|
||||
assertThat(factory.getType("prototype")).isAssignableTo(ITestBean.class);
|
||||
ITestBean test2 = (ITestBean) factory.getBean("prototype");
|
||||
ITestBean test2_1 = (ITestBean) factory.getBean("prototype");
|
||||
assertThat(test2).as("Prototype instances !=").isNotSameAs(test2_1);
|
||||
assertThat(test2).as("Prototype instances equal").isEqualTo(test2_1);
|
||||
assertThat(ITestBean.class.isAssignableFrom(factory.getType("prototype"))).as("Has correct object type").isTrue();
|
||||
assertThat(factory.getType("prototype")).isAssignableTo(ITestBean.class);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -291,13 +297,13 @@ public class ProxyFactoryBeanTests {
|
|||
@Test
|
||||
public void testCanGetFactoryReferenceAndManipulate() {
|
||||
ProxyFactoryBean config = (ProxyFactoryBean) factory.getBean("&test1");
|
||||
assertThat(ITestBean.class.isAssignableFrom(config.getObjectType())).as("Has correct object type").isTrue();
|
||||
assertThat(ITestBean.class.isAssignableFrom(factory.getType("test1"))).as("Has correct object type").isTrue();
|
||||
assertThat(config.getObjectType()).isAssignableTo(ITestBean.class);
|
||||
assertThat(factory.getType("test1")).isAssignableTo(ITestBean.class);
|
||||
// Trigger lazy initialization.
|
||||
config.getObject();
|
||||
assertThat(config.getAdvisors().length).as("Have one advisors").isEqualTo(1);
|
||||
assertThat(ITestBean.class.isAssignableFrom(config.getObjectType())).as("Has correct object type").isTrue();
|
||||
assertThat(ITestBean.class.isAssignableFrom(factory.getType("test1"))).as("Has correct object type").isTrue();
|
||||
assertThat(config.getObjectType()).isAssignableTo(ITestBean.class);
|
||||
assertThat(factory.getType("test1")).isAssignableTo(ITestBean.class);
|
||||
|
||||
ITestBean tb = (ITestBean) factory.getBean("test1");
|
||||
// no exception
|
||||
|
|
|
@ -543,6 +543,25 @@ public class CommonAnnotationBeanPostProcessorTests {
|
|||
assertThat(tb.getName()).isEqualTo("notLazyAnymore");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLazyResolutionWithFallbackTypeMatch() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
bf.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
|
||||
CommonAnnotationBeanPostProcessor bpp = new CommonAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(bf);
|
||||
bf.addBeanPostProcessor(bpp);
|
||||
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(LazyResourceCglibInjectionBean.class));
|
||||
bf.registerBeanDefinition("tb", new RootBeanDefinition(TestBean.class));
|
||||
|
||||
LazyResourceCglibInjectionBean bean = (LazyResourceCglibInjectionBean) bf.getBean("annotatedBean");
|
||||
assertThat(bf.containsSingleton("tb")).isFalse();
|
||||
bean.testBean.setName("notLazyAnymore");
|
||||
assertThat(bf.containsSingleton("tb")).isTrue();
|
||||
TestBean tb = (TestBean) bf.getBean("tb");
|
||||
assertThat(tb.getName()).isEqualTo("notLazyAnymore");
|
||||
}
|
||||
|
||||
|
||||
public static class AnnotatedInitDestroyBean {
|
||||
|
||||
|
|
|
@ -498,7 +498,6 @@ public class SpringFactoriesLoader {
|
|||
|
||||
/**
|
||||
* Strategy for resolving constructor arguments based on their type.
|
||||
*
|
||||
* @since 6.0
|
||||
* @see ArgumentResolver#of(Class, Object)
|
||||
* @see ArgumentResolver#ofSupplied(Class, Supplier)
|
||||
|
@ -595,13 +594,11 @@ public class SpringFactoriesLoader {
|
|||
*/
|
||||
static ArgumentResolver from(Function<Class<?>, Object> function) {
|
||||
return new ArgumentResolver() {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T> T resolve(Class<T> type) {
|
||||
return (T) function.apply(type);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -609,7 +606,6 @@ public class SpringFactoriesLoader {
|
|||
|
||||
/**
|
||||
* Strategy for handling a failure that occurs when instantiating a factory.
|
||||
*
|
||||
* @since 6.0
|
||||
* @see FailureHandler#throwing()
|
||||
* @see FailureHandler#logging(Log)
|
||||
|
@ -671,7 +667,7 @@ public class SpringFactoriesLoader {
|
|||
static FailureHandler handleMessage(BiConsumer<Supplier<String>, Throwable> messageHandler) {
|
||||
return (factoryType, factoryImplementationName, failure) -> {
|
||||
Supplier<String> messageSupplier = () -> "Unable to instantiate factory class [%s] for factory type [%s]"
|
||||
.formatted(factoryImplementationName, factoryType.getName());
|
||||
.formatted(factoryImplementationName, factoryType.getName());
|
||||
messageHandler.accept(messageSupplier, failure);
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue