Skip to content

Commit fac6399

Browse files
committed
Merge remote-tracking branch 'origin/master'
2 parents f98a6c6 + 9ed0a56 commit fac6399

File tree

7 files changed

+103
-17
lines changed

7 files changed

+103
-17
lines changed

spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1451,9 +1451,15 @@ protected Class<?> getTypeForFactoryBean(String beanName, RootBeanDefinition mbd
14511451
return getTypeForFactoryBean(factoryBean);
14521452
}
14531453
catch (BeanCreationException ex) {
1454-
// Can only happen when getting a FactoryBean.
1455-
if (logger.isWarnEnabled()) {
1456-
logger.warn("Bean creation exception on FactoryBean type check: " + ex);
1454+
if (ex instanceof BeanCurrentlyInCreationException) {
1455+
if (logger.isDebugEnabled()) {
1456+
logger.debug("Bean currently in creation on FactoryBean type check: " + ex);
1457+
}
1458+
}
1459+
else {
1460+
if (logger.isWarnEnabled()) {
1461+
logger.warn("Bean creation exception on FactoryBean type check: " + ex);
1462+
}
14571463
}
14581464
onSuppressedException(ex);
14591465
return null;

spring-beans/src/test/java/org/springframework/beans/factory/FactoryBeanTests.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
* @author Juergen Hoeller
3939
* @author Chris Beams
4040
*/
41-
public final class FactoryBeanTests {
41+
public class FactoryBeanTests {
4242

4343
private static final Class<?> CLASS = FactoryBeanTests.class;
4444
private static final Resource RETURNS_NULL_CONTEXT = qualifiedResource(CLASS, "returnsNull.xml");
@@ -63,10 +63,13 @@ public void testFactoryBeansWithAutowiring() throws Exception {
6363
BeanFactoryPostProcessor ppc = (BeanFactoryPostProcessor) factory.getBean("propertyPlaceholderConfigurer");
6464
ppc.postProcessBeanFactory(factory);
6565

66+
assertNull(factory.getType("betaFactory"));
67+
6668
Alpha alpha = (Alpha) factory.getBean("alpha");
6769
Beta beta = (Beta) factory.getBean("beta");
6870
Gamma gamma = (Gamma) factory.getBean("gamma");
6971
Gamma gamma2 = (Gamma) factory.getBean("gammaFactory");
72+
7073
assertSame(beta, alpha.getBeta());
7174
assertSame(gamma, beta.getGamma());
7275
assertSame(gamma2, beta.getGamma());
@@ -194,6 +197,9 @@ public static class Gamma {
194197
@Component
195198
public static class BetaFactoryBean implements FactoryBean<Object> {
196199

200+
public BetaFactoryBean(Alpha alpha) {
201+
}
202+
197203
private Beta beta;
198204

199205
public void setBeta(Beta beta) {

spring-beans/src/test/resources/org/springframework/beans/factory/FactoryBeanTests-withAutowiring.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
<bean id="gamma" class="org.springframework.beans.factory.FactoryBeanTests$Gamma"/>
1313

14-
<bean id="betaFactory" class="org.springframework.beans.factory.FactoryBeanTests$BetaFactoryBean">
14+
<bean id="betaFactory" class="org.springframework.beans.factory.FactoryBeanTests$BetaFactoryBean" autowire="constructor">
1515
<property name="beta" ref="beta"/>
1616
</bean>
1717

spring-context/src/main/java/org/springframework/context/ApplicationEventPublisher.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
/**
2020
* Interface that encapsulates event publication functionality.
21-
* Serves as super-interface for ApplicationContext.
21+
* Serves as super-interface for {@link ApplicationContext}.
2222
*
2323
* @author Juergen Hoeller
2424
* @author Stephane Nicoll
@@ -42,9 +42,10 @@ public interface ApplicationEventPublisher {
4242
/**
4343
* Notify all <strong>matching</strong> listeners registered with this
4444
* application of an event.
45-
* <p>If the specified {@code event} is not an {@link ApplicationEvent}, it
46-
* is wrapped in a {@code GenericApplicationEvent}.
45+
* <p>If the specified {@code event} is not an {@link ApplicationEvent},
46+
* it is wrapped in a {@link PayloadApplicationEvent}.
4747
* @param event the event to publish
48+
* @since 4.2
4849
* @see PayloadApplicationEvent
4950
*/
5051
void publishEvent(Object event);

spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassEnhancer.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
import org.springframework.cglib.transform.TransformingClassGenerator;
4747
import org.springframework.core.annotation.AnnotationUtils;
4848
import org.springframework.util.Assert;
49+
import org.springframework.util.ClassUtils;
4950
import org.springframework.util.ObjectUtils;
5051
import org.springframework.util.ReflectionUtils;
5152

@@ -322,7 +323,7 @@ public Object intercept(Object enhancedConfigInstance, Method beanMethod, Object
322323
}
323324
Object beanInstance = (!ObjectUtils.isEmpty(beanMethodArgs) ?
324325
beanFactory.getBean(beanName, beanMethodArgs) : beanFactory.getBean(beanName));
325-
if (beanInstance != null && !beanMethod.getReturnType().isInstance(beanInstance)) {
326+
if (beanInstance != null && !ClassUtils.isAssignableValue(beanMethod.getReturnType(), beanInstance)) {
326327
String msg = String.format("@Bean method %s.%s called as a bean reference " +
327328
"for type [%s] but overridden by non-compatible bean instance of type [%s].",
328329
beanMethod.getDeclaringClass().getSimpleName(), beanMethod.getName(),

spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,9 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
165165
/** Parent context */
166166
private ApplicationContext parent;
167167

168+
/** Environment used by this context */
169+
private ConfigurableEnvironment environment;
170+
168171
/** BeanFactoryPostProcessors to apply on refresh */
169172
private final List<BeanFactoryPostProcessor> beanFactoryPostProcessors =
170173
new ArrayList<BeanFactoryPostProcessor>();
@@ -197,10 +200,10 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
197200
private ApplicationEventMulticaster applicationEventMulticaster;
198201

199202
/** Statically specified listeners */
200-
private Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<ApplicationListener<?>>();
203+
private final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<ApplicationListener<?>>();
201204

202-
/** Environment used by this context; initialized by {@link #createEnvironment()} */
203-
private ConfigurableEnvironment environment;
205+
/** ApplicationEvents published early */
206+
private Set<ApplicationEvent> earlyApplicationEvents;
204207

205208

206209
/**
@@ -340,7 +343,9 @@ protected void publishEvent(Object event, ResolvableType eventType) {
340343
if (logger.isTraceEnabled()) {
341344
logger.trace("Publishing event in " + getDisplayName() + ": " + event);
342345
}
343-
final ApplicationEvent applicationEvent;
346+
347+
// Decorate event as an ApplicationEvent if necessary
348+
ApplicationEvent applicationEvent;
344349
if (event instanceof ApplicationEvent) {
345350
applicationEvent = (ApplicationEvent) event;
346351
}
@@ -350,7 +355,16 @@ protected void publishEvent(Object event, ResolvableType eventType) {
350355
eventType = ResolvableType.forClassWithGenerics(PayloadApplicationEvent.class, event.getClass());
351356
}
352357
}
353-
getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
358+
359+
// Multicast right now if possible - or lazily once the multicaster is initialized
360+
if (this.earlyApplicationEvents != null) {
361+
this.earlyApplicationEvents.add(applicationEvent);
362+
}
363+
else {
364+
getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
365+
}
366+
367+
// Publish event via parent context as well...
354368
if (this.parent != null) {
355369
if (this.parent instanceof AbstractApplicationContext) {
356370
((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
@@ -379,7 +393,7 @@ ApplicationEventMulticaster getApplicationEventMulticaster() throws IllegalState
379393
* @return the internal LifecycleProcessor (never {@code null})
380394
* @throws IllegalStateException if the context has not been initialized yet
381395
*/
382-
LifecycleProcessor getLifecycleProcessor() {
396+
LifecycleProcessor getLifecycleProcessor() throws IllegalStateException {
383397
if (this.lifecycleProcessor == null) {
384398
throw new IllegalStateException("LifecycleProcessor not initialized - " +
385399
"call 'refresh' before invoking lifecycle methods via the context: " + this);
@@ -543,6 +557,10 @@ protected void prepareRefresh() {
543557
// Validate that all properties marked as required are resolvable
544558
// see ConfigurablePropertyResolver#setRequiredProperties
545559
getEnvironment().validateRequiredProperties();
560+
561+
// Allow for the collection of early ApplicationEvents,
562+
// to be published once the multicaster is available...
563+
this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
546564
}
547565

548566
/**
@@ -748,11 +766,21 @@ protected void registerListeners() {
748766
for (ApplicationListener<?> listener : getApplicationListeners()) {
749767
getApplicationEventMulticaster().addApplicationListener(listener);
750768
}
769+
751770
// Do not initialize FactoryBeans here: We need to leave all regular beans
752771
// uninitialized to let post-processors apply to them!
753772
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
754-
for (String lisName : listenerBeanNames) {
755-
getApplicationEventMulticaster().addApplicationListenerBean(lisName);
773+
for (String listenerBeanName : listenerBeanNames) {
774+
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
775+
}
776+
777+
// Publish early application events now that we finally have a multicaster...
778+
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
779+
this.earlyApplicationEvents = null;
780+
if (earlyEventsToProcess != null) {
781+
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
782+
getApplicationEventMulticaster().multicastEvent(earlyEvent);
783+
}
756784
}
757785
}
758786

spring-context/src/test/java/org/springframework/context/event/ApplicationContextEventTests.java

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,20 @@
2424
import org.junit.Test;
2525

2626
import org.springframework.aop.framework.ProxyFactory;
27+
import org.springframework.beans.BeansException;
28+
import org.springframework.beans.factory.config.BeanPostProcessor;
2729
import org.springframework.beans.factory.config.RuntimeBeanReference;
2830
import org.springframework.beans.factory.support.RootBeanDefinition;
2931
import org.springframework.context.ApplicationContext;
32+
import org.springframework.context.ApplicationContextAware;
3033
import org.springframework.context.ApplicationEvent;
3134
import org.springframework.context.ApplicationListener;
3235
import org.springframework.context.BeanThatBroadcasts;
3336
import org.springframework.context.BeanThatListens;
3437
import org.springframework.context.support.AbstractApplicationContext;
38+
import org.springframework.context.support.GenericApplicationContext;
3539
import org.springframework.context.support.StaticApplicationContext;
40+
import org.springframework.context.support.StaticMessageSource;
3641
import org.springframework.core.Ordered;
3742
import org.springframework.core.ResolvableType;
3843
import org.springframework.core.annotation.Order;
@@ -48,6 +53,7 @@
4853
* @author Alef Arendsen
4954
* @author Rick Evans
5055
* @author Stephane Nicoll
56+
* @author Juergen Hoeller
5157
*/
5258
public class ApplicationContextEventTests extends AbstractApplicationEventListenerTests {
5359

@@ -337,6 +343,21 @@ public void innerBeanAsListener() {
337343
context.close();
338344
}
339345

346+
@Test
347+
public void beanPostProcessorPublishesEvents() {
348+
GenericApplicationContext context = new GenericApplicationContext();
349+
context.registerBeanDefinition("listener", new RootBeanDefinition(BeanThatListens.class));
350+
context.registerBeanDefinition("messageSource", new RootBeanDefinition(StaticMessageSource.class));
351+
context.registerBeanDefinition("postProcessor", new RootBeanDefinition(EventPublishingBeanPostProcessor.class));
352+
context.refresh();
353+
354+
context.publishEvent(new MyEvent(this));
355+
BeanThatListens listener = context.getBean(BeanThatListens.class);
356+
assertEquals(4, listener.getEventCount());
357+
358+
context.close();
359+
}
360+
340361

341362
@SuppressWarnings("serial")
342363
public static class MyEvent extends ApplicationEvent {
@@ -410,6 +431,7 @@ public void onApplicationEvent(ApplicationEvent event) {
410431
}
411432
}
412433

434+
413435
@Order(5)
414436
public static class MyOrderedListener3 implements ApplicationListener<ApplicationEvent> {
415437

@@ -422,6 +444,7 @@ public void onApplicationEvent(ApplicationEvent event) {
422444

423445
}
424446

447+
425448
@Order(50)
426449
public static class MyOrderedListener4 implements ApplicationListener<MyEvent> {
427450

@@ -437,4 +460,25 @@ public void onApplicationEvent(MyEvent event) {
437460
}
438461
}
439462

463+
464+
public static class EventPublishingBeanPostProcessor implements BeanPostProcessor, ApplicationContextAware {
465+
466+
private ApplicationContext applicationContext;
467+
468+
public void setApplicationContext(ApplicationContext applicationContext) {
469+
this.applicationContext = applicationContext;
470+
}
471+
472+
@Override
473+
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
474+
this.applicationContext.publishEvent(new MyEvent(this));
475+
return bean;
476+
}
477+
478+
@Override
479+
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
480+
return bean;
481+
}
482+
}
483+
440484
}

0 commit comments

Comments
 (0)