Skip to content

Commit f9be717

Browse files
committed
Avoid getObjectType exception for uninitialized ProxyFactoryBean
Closes gh-31473
1 parent bb446a3 commit f9be717

File tree

2 files changed

+44
-24
lines changed

2 files changed

+44
-24
lines changed

spring-aop/src/main/java/org/springframework/aop/framework/ProxyFactoryBean.java

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -265,18 +265,32 @@ public Object getObject() throws BeansException {
265265
* Return the type of the proxy. Will check the singleton instance if
266266
* already created, else fall back to the proxy interface (in case of just
267267
* a single one), the target bean type, or the TargetSource's target class.
268-
* @see org.springframework.aop.TargetSource#getTargetClass
268+
* @see org.springframework.aop.framework.AopProxy#getProxyClass
269269
*/
270270
@Override
271+
@Nullable
271272
public Class<?> getObjectType() {
272273
synchronized (this) {
273274
if (this.singletonInstance != null) {
274275
return this.singletonInstance.getClass();
275276
}
276277
}
277-
// This might be incomplete since it potentially misses introduced interfaces
278-
// from Advisors that will be lazily retrieved via setInterceptorNames.
279-
return createAopProxy().getProxyClass(this.proxyClassLoader);
278+
try {
279+
// This might be incomplete since it potentially misses introduced interfaces
280+
// from Advisors that will be lazily retrieved via setInterceptorNames.
281+
return createAopProxy().getProxyClass(this.proxyClassLoader);
282+
}
283+
catch (AopConfigException ex) {
284+
if (getTargetClass() == null) {
285+
if (logger.isDebugEnabled()) {
286+
logger.debug("Failed to determine early proxy class: " + ex.getMessage());
287+
}
288+
return null;
289+
}
290+
else {
291+
throw ex;
292+
}
293+
}
280294
}
281295

282296
@Override

spring-context/src/test/java/org/springframework/aop/framework/ProxyFactoryBeanTests.java

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -139,22 +139,24 @@ public void testDoubleTargetSourcesAreRejected() {
139139
private void testDoubleTargetSourceIsRejected(String name) {
140140
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
141141
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(new ClassPathResource(DBL_TARGETSOURCE_CONTEXT, CLASS));
142+
142143
assertThatExceptionOfType(BeanCreationException.class).as("Should not allow TargetSource to be specified in interceptorNames as well as targetSource property")
143-
.isThrownBy(() -> bf.getBean(name))
144-
.havingCause()
145-
.isInstanceOf(AopConfigException.class)
146-
.withMessageContaining("TargetSource");
144+
.isThrownBy(() -> bf.getBean(name))
145+
.havingCause()
146+
.isInstanceOf(AopConfigException.class)
147+
.withMessageContaining("TargetSource");
147148
}
148149

149150
@Test
150151
public void testTargetSourceNotAtEndOfInterceptorNamesIsRejected() {
151152
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
152153
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(new ClassPathResource(NOTLAST_TARGETSOURCE_CONTEXT, CLASS));
154+
153155
assertThatExceptionOfType(BeanCreationException.class).as("TargetSource or non-advised object must be last in interceptorNames")
154-
.isThrownBy(() -> bf.getBean("targetSourceNotLast"))
155-
.havingCause()
156-
.isInstanceOf(AopConfigException.class)
157-
.withMessageContaining("interceptorNames");
156+
.isThrownBy(() -> bf.getBean("targetSourceNotLast"))
157+
.havingCause()
158+
.isInstanceOf(AopConfigException.class)
159+
.withMessageContaining("interceptorNames");
158160
}
159161

160162
@Test
@@ -171,7 +173,7 @@ public void testGetObjectTypeWithDirectTarget() {
171173
assertThat(cba.getCalls()).isEqualTo(1);
172174

173175
ProxyFactoryBean pfb = (ProxyFactoryBean) bf.getBean("&directTarget");
174-
assertThat(TestBean.class.isAssignableFrom(pfb.getObjectType())).as("Has correct object type").isTrue();
176+
assertThat(pfb.getObjectType()).isAssignableTo(TestBean.class);
175177
}
176178

177179
@Test
@@ -181,7 +183,7 @@ public void testGetObjectTypeWithTargetViaTargetSource() {
181183
ITestBean tb = (ITestBean) bf.getBean("viaTargetSource");
182184
assertThat(tb.getName()).isEqualTo("Adam");
183185
ProxyFactoryBean pfb = (ProxyFactoryBean) bf.getBean("&viaTargetSource");
184-
assertThat(TestBean.class.isAssignableFrom(pfb.getObjectType())).as("Has correct object type").isTrue();
186+
assertThat(pfb.getObjectType()).isAssignableTo(TestBean.class);
185187
}
186188

187189
@Test
@@ -190,11 +192,15 @@ public void testGetObjectTypeWithNoTargetOrTargetSource() {
190192
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(new ClassPathResource(TARGETSOURCE_CONTEXT, CLASS));
191193

192194
ITestBean tb = (ITestBean) bf.getBean("noTarget");
193-
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() ->
194-
tb.getName())
195-
.withMessage("getName");
195+
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(tb::getName).withMessage("getName");
196196
FactoryBean<?> pfb = (ProxyFactoryBean) bf.getBean("&noTarget");
197-
assertThat(ITestBean.class.isAssignableFrom(pfb.getObjectType())).as("Has correct object type").isTrue();
197+
assertThat(pfb.getObjectType()).isAssignableTo(ITestBean.class);
198+
}
199+
200+
@Test
201+
public void testGetObjectTypeOnUninitializedFactoryBean() {
202+
ProxyFactoryBean pfb = new ProxyFactoryBean();
203+
assertThat(pfb.getObjectType()).isNull();
198204
}
199205

200206
/**
@@ -227,12 +233,12 @@ public void testSingletonInstancesAreEqual() {
227233

228234
@Test
229235
public void testPrototypeInstancesAreNotEqual() {
230-
assertThat(ITestBean.class.isAssignableFrom(factory.getType("prototype"))).as("Has correct object type").isTrue();
236+
assertThat(factory.getType("prototype")).isAssignableTo(ITestBean.class);
231237
ITestBean test2 = (ITestBean) factory.getBean("prototype");
232238
ITestBean test2_1 = (ITestBean) factory.getBean("prototype");
233239
assertThat(test2).as("Prototype instances !=").isNotSameAs(test2_1);
234240
assertThat(test2).as("Prototype instances equal").isEqualTo(test2_1);
235-
assertThat(ITestBean.class.isAssignableFrom(factory.getType("prototype"))).as("Has correct object type").isTrue();
241+
assertThat(factory.getType("prototype")).isAssignableTo(ITestBean.class);
236242
}
237243

238244
/**
@@ -291,13 +297,13 @@ public void testAutoInvoker() {
291297
@Test
292298
public void testCanGetFactoryReferenceAndManipulate() {
293299
ProxyFactoryBean config = (ProxyFactoryBean) factory.getBean("&test1");
294-
assertThat(ITestBean.class.isAssignableFrom(config.getObjectType())).as("Has correct object type").isTrue();
295-
assertThat(ITestBean.class.isAssignableFrom(factory.getType("test1"))).as("Has correct object type").isTrue();
300+
assertThat(config.getObjectType()).isAssignableTo(ITestBean.class);
301+
assertThat(factory.getType("test1")).isAssignableTo(ITestBean.class);
296302
// Trigger lazy initialization.
297303
config.getObject();
298304
assertThat(config.getAdvisors().length).as("Have one advisors").isEqualTo(1);
299-
assertThat(ITestBean.class.isAssignableFrom(config.getObjectType())).as("Has correct object type").isTrue();
300-
assertThat(ITestBean.class.isAssignableFrom(factory.getType("test1"))).as("Has correct object type").isTrue();
305+
assertThat(config.getObjectType()).isAssignableTo(ITestBean.class);
306+
assertThat(factory.getType("test1")).isAssignableTo(ITestBean.class);
301307

302308
ITestBean tb = (ITestBean) factory.getBean("test1");
303309
// no exception

0 commit comments

Comments
 (0)