Skip to content

Commit ac8ba36

Browse files
authored
Merge pull request #260 from mercyblitz/dev-1.x
Refine documentation and simplify ListenableAutowireCandidateResolver
2 parents a44cc31 + e31b04e commit ac8ba36

6 files changed

Lines changed: 105 additions & 129 deletions

File tree

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,8 @@ Choose the version that matches your Spring Framework line:
9191

9292
| Branch | Spring Framework compatibility | Latest version |
9393
|--------|--------------------------------|----------------|
94-
| `main` | 6.0.x – 7.0.x | `0.2.29` |
95-
| `1.x` | 4.3.x – 5.3.x | `0.1.29` |
94+
| `main` | 6.0.x – 7.0.x | `0.2.30` |
95+
| `1.x` | 4.3.x – 5.3.x | `0.1.30` |
9696

9797
### 2. Add individual modules
9898

microsphere-spring-context/src/main/java/io/microsphere/spring/beans/factory/support/ListenableAutowireCandidateResolver.java

Lines changed: 4 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,7 @@
1616
*/
1717
package io.microsphere.spring.beans.factory.support;
1818

19-
import io.microsphere.annotation.ConfigurationProperty;
2019
import io.microsphere.annotation.Nullable;
21-
import io.microsphere.constants.PropertyConstants;
2220
import io.microsphere.logging.Logger;
2321
import org.springframework.beans.BeansException;
2422
import org.springframework.beans.factory.BeanFactory;
@@ -28,27 +26,18 @@
2826
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
2927
import org.springframework.beans.factory.config.DependencyDescriptor;
3028
import org.springframework.beans.factory.support.AutowireCandidateResolver;
31-
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
3229
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
33-
import org.springframework.context.ConfigurableApplicationContext;
34-
import org.springframework.context.EnvironmentAware;
35-
import org.springframework.core.env.Environment;
3630

3731
import java.lang.invoke.MethodHandle;
3832
import java.util.List;
3933

40-
import static io.microsphere.annotation.ConfigurationProperty.APPLICATION_SOURCE;
4134
import static io.microsphere.collection.Lists.ofList;
4235
import static io.microsphere.invoke.MethodHandleUtils.findVirtual;
4336
import static io.microsphere.invoke.MethodHandleUtils.handleInvokeExactFailure;
4437
import static io.microsphere.logging.LoggerFactory.getLogger;
45-
import static io.microsphere.spring.beans.factory.BeanFactoryUtils.asBeanDefinitionRegistry;
4638
import static io.microsphere.spring.beans.factory.BeanFactoryUtils.asDefaultListableBeanFactory;
4739
import static io.microsphere.spring.beans.factory.support.AutowireCandidateResolvingListener.loadListeners;
48-
import static io.microsphere.spring.beans.factory.support.BeanRegistrar.registerInfrastructureBean;
49-
import static io.microsphere.spring.constants.PropertyConstants.MICROSPHERE_SPRING_PROPERTY_NAME_PREFIX;
5040
import static io.microsphere.util.ArrayUtils.combine;
51-
import static java.lang.Boolean.parseBoolean;
5241
import static org.springframework.beans.BeanUtils.instantiateClass;
5342

5443
/**
@@ -62,22 +51,10 @@
6251
* <h3>Key Features</h3>
6352
* <ul>
6453
* <li>Wraps the existing {@link AutowireCandidateResolver} in a Spring bean factory</li>
65-
* <li>Supports dynamic registration of resolving listeners</li>
54+
* <li>Supports dynamic registration of resolving listeners based on Spring Beans or Spring Factories</li>
6655
* <li>Provides lifecycle integration through {@link BeanFactoryPostProcessor}</li>
67-
* <li>Configurable via environment properties (e.g., enable/disable)</li>
6856
* </ul>
6957
*
70-
* <h3>Example Usage</h3>
71-
* <pre>{@code
72-
* // Register as infrastructure bean
73-
* ListenableAutowireCandidateResolver.register(applicationContext);
74-
*
75-
* // Add custom listener
76-
* ListenableAutowireCandidateResolver resolver = beanFactory.getBean(ListenableAutowireCandidateResolver.class);
77-
* resolver.addListener((descriptor, candidates) -> {
78-
* System.out.println("Resolved candidates for " + descriptor.getDependencyType());
79-
* });
80-
* }</pre>
8158
*
8259
* <h3>Configuration</h3>
8360
* Enable the resolver using property configuration:
@@ -90,10 +67,11 @@
9067
* @see AutowireCandidateResolvingListener
9168
* @see CompositeAutowireCandidateResolvingListener
9269
* @see DefaultListableBeanFactory#setAutowireCandidateResolver(AutowireCandidateResolver)
70+
* @see BeanFactoryPostProcessor
9371
* @since 1.0.0
9472
*/
9573
public class ListenableAutowireCandidateResolver implements AutowireCandidateResolver, BeanFactoryPostProcessor,
96-
EnvironmentAware, BeanNameAware {
74+
BeanNameAware {
9775

9876
private static final Logger logger = getLogger(ListenableAutowireCandidateResolver.class);
9977

@@ -118,35 +96,10 @@ public class ListenableAutowireCandidateResolver implements AutowireCandidateRes
11896
*/
11997
private static final MethodHandle CLONE_IF_NECESSARY_METHOD_HANDLE = findVirtual(AutowireCandidateResolver.class, "cloneIfNecessary");
12098

121-
/**
122-
* The prefix of the property name of {@link ListenableAutowireCandidateResolver}
123-
*/
124-
public static final String PROPERTY_NAME_PREFIX = MICROSPHERE_SPRING_PROPERTY_NAME_PREFIX + "listenable-autowire-candidate-resolver.";
125-
126-
private static final String DEFAULT_ENABLED = "false";
127-
128-
/**
129-
* The property name of {@link ListenableAutowireCandidateResolver} to be 'enabled'
130-
*/
131-
@ConfigurationProperty(
132-
type = boolean.class,
133-
defaultValue = DEFAULT_ENABLED,
134-
description = "The property name of ListenableAutowireCandidateResolver to be enabled or not",
135-
source = APPLICATION_SOURCE
136-
)
137-
public static final String ENABLED_PROPERTY_NAME = PROPERTY_NAME_PREFIX + PropertyConstants.ENABLED_PROPERTY_NAME;
138-
139-
/**
140-
* The default property value of {@link ListenableAutowireCandidateResolver} to be 'enabled'
141-
*/
142-
public static final boolean DEFAULT_ENABLED_PROPERTY_VALUE = parseBoolean(DEFAULT_ENABLED);
143-
14499
private AutowireCandidateResolver delegate;
145100

146101
private CompositeAutowireCandidateResolvingListener compositeListener;
147102

148-
private Environment environment;
149-
150103
private String beanName;
151104

152105
/**
@@ -366,38 +319,6 @@ public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
366319
wrap(beanFactory);
367320
}
368321

369-
/**
370-
* {@inheritDoc}
371-
* <p>Stores the {@link Environment} for later use in determining whether this resolver is
372-
* {@link #isEnabled(Environment) enabled} and for resolving configuration properties.
373-
*
374-
* <h3>Example Usage</h3>
375-
* <pre>{@code
376-
* // Typically called automatically by Spring's EnvironmentAware callback.
377-
* // The environment can be configured with the enabling property:
378-
* // microsphere.spring.listenable-autowire-candidate-resolver.enabled=true
379-
* }</pre>
380-
*
381-
* @param environment the {@link Environment} to set
382-
*/
383-
@Override
384-
public void setEnvironment(Environment environment) {
385-
this.environment = environment;
386-
}
387-
388-
/**
389-
* {@inheritDoc}
390-
* <p>Stores the bean name assigned to this resolver instance for logging and diagnostics.
391-
*
392-
* <h3>Example Usage</h3>
393-
* <pre>{@code
394-
* // Typically called automatically by Spring's BeanNameAware callback.
395-
* // The bean is registered as an infrastructure bean:
396-
* ListenableAutowireCandidateResolver.register(applicationContext);
397-
* }</pre>
398-
*
399-
* @param name the name of this bean in the Spring container
400-
*/
401322
@Override
402323
public void setBeanName(String name) {
403324
this.beanName = name;
@@ -410,16 +331,6 @@ public void setBeanName(String name) {
410331
* @param beanFactory {@link DefaultListableBeanFactory}
411332
*/
412333
public void wrap(BeanFactory beanFactory) {
413-
if (!isEnabled(this.environment)) {
414-
if (logger.isInfoEnabled()) {
415-
logger.info("The ListenableAutowireCandidateResolver bean[name : '{}'] is disabled.", this.beanName);
416-
logger.info("Setting the configuration property '{} = true' to enable it if requires.", ENABLED_PROPERTY_NAME);
417-
}
418-
return;
419-
}
420-
if (logger.isTraceEnabled()) {
421-
logger.trace("The ListenableAutowireCandidateResolver bean[name : '{}'] is enabled.", this.beanName);
422-
}
423334
DefaultListableBeanFactory dbf = asDefaultListableBeanFactory(beanFactory);
424335
AutowireCandidateResolver autowireCandidateResolver = dbf.getAutowireCandidateResolver();
425336
if (autowireCandidateResolver != this) {
@@ -428,28 +339,7 @@ public void wrap(BeanFactory beanFactory) {
428339
this.delegate = autowireCandidateResolver;
429340
this.compositeListener = compositeListener;
430341
dbf.setAutowireCandidateResolver(this);
342+
logger.info("The ListenableAutowireCandidateResolver has been wrapped and registered to BeanFactory[{}]", dbf);
431343
}
432344
}
433-
434-
/**
435-
* Determine whether the {@link ListenableAutowireCandidateResolver} is enabled or not
436-
*
437-
* @param environment {@link Environment}
438-
* @return <code>true</code> if enabled, otherwise <code>false</code>
439-
*/
440-
public static boolean isEnabled(Environment environment) {
441-
return environment.getProperty(ENABLED_PROPERTY_NAME, boolean.class, DEFAULT_ENABLED_PROPERTY_VALUE);
442-
}
443-
444-
/**
445-
* Register the {@link ListenableAutowireCandidateResolver} as the infrastructure bean
446-
*
447-
* @param applicationContext {@link ConfigurableApplicationContext}
448-
*/
449-
public static void register(ConfigurableApplicationContext applicationContext) {
450-
ConfigurableListableBeanFactory beanFactory = applicationContext.getBeanFactory();
451-
BeanDefinitionRegistry beanDefinitionRegistry = asBeanDefinitionRegistry(beanFactory);
452-
registerInfrastructureBean(beanDefinitionRegistry, ListenableAutowireCandidateResolver.class);
453-
}
454-
455345
}

microsphere-spring-context/src/main/java/io/microsphere/spring/beans/factory/support/ListenableAutowireCandidateResolverInitializer.java

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,32 +20,56 @@
2020
import io.microsphere.constants.PropertyConstants;
2121
import io.microsphere.spring.context.ConfigurableApplicationContextInitializer;
2222
import io.microsphere.spring.core.env.ListenableConfigurableEnvironment;
23+
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
24+
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
2325
import org.springframework.context.ApplicationContextInitializer;
2426
import org.springframework.context.ConfigurableApplicationContext;
2527
import org.springframework.core.env.ConfigurableEnvironment;
2628

27-
import static io.microsphere.spring.beans.factory.support.ListenableAutowireCandidateResolver.register;
29+
import static io.microsphere.spring.beans.factory.BeanFactoryUtils.asBeanDefinitionRegistry;
30+
import static io.microsphere.spring.beans.factory.support.BeanRegistrar.registerBeanDefinition;
2831
import static io.microsphere.spring.constants.PropertyConstants.MICROSPHERE_SPRING_PROPERTY_NAME_PREFIX;
2932
import static java.lang.Boolean.parseBoolean;
3033

3134
/**
3235
* An {@link ApplicationContextInitializer} implementation that registers a
3336
* {@link ListenableAutowireCandidateResolver} to provide extensible autowiring
3437
* capabilities within the Spring application context.
38+
* <p>
39+
* It allows developers to customize the autowire candidate resolution strategy
40+
* based on specific requirements, such as conditional bean matching or external configuration.
41+
* The functionality is disabled by default and can be enabled via configuration properties.
42+
*
43+
* <h3>Configuration Properties</h3>
44+
* <ul>
45+
* <li>{@code microsphere.spring.listenable-autowire-candidate-resolver.enabled} -
46+
* Whether to enable the {@link ListenableAutowireCandidateResolver} (default: {@code false}).</li>
47+
* </ul>
3548
*
3649
* <h3>Example Usage</h3>
50+
* <h4>1. Configuration</h4>
51+
* <p><strong> application.properties (Spring Boot):</strong></p>
52+
* <pre>
53+
* microsphere.spring.listenable-autowire-candidate-resolver.enabled=true
54+
* </pre>
55+
*
56+
* <p><strong> spring.factories (Spring Boot):</strong></p>
3757
* <pre>{@code
38-
* public class MyConfig implements WebMvcConfigurer {
39-
* // Configuration code...
40-
* }
58+
* org.springframework.context.ApplicationContextInitializer=\
59+
* io.microsphere.spring.beans.factory.support.ListenableAutowireCandidateResolverInitializer
4160
* }</pre>
4261
*
43-
* <p>This initializer should be registered with a {@link org.springframework.context.ApplicationContext}
44-
* to enable custom autowiring logic during the application context initialization phase.
62+
* <h4>2. Programmatic</h4>
63+
* <pre>{@code
64+
* new SpringApplicationBuilder(MyApplication.class)
65+
* .initializers(new ListenableAutowireCandidateResolverInitializer())
66+
* .properties("microsphere.spring.listenable-autowire-candidate-resolver.enabled=true")
67+
* .run(args);
68+
* }</pre>
4569
*
46-
* @author <a href="mailto:mercyblitz@gmail.com">Mercy<a/>
70+
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
4771
* @see ListenableAutowireCandidateResolver
48-
* @see ApplicationContextInitializer
72+
* @see ConfigurableApplicationContextInitializer
4973
* @since 1.0.0
5074
*/
5175
public class ListenableAutowireCandidateResolverInitializer extends ConfigurableApplicationContextInitializer {
@@ -74,7 +98,9 @@ public class ListenableAutowireCandidateResolverInitializer extends Configurable
7498

7599
@Override
76100
protected void initialize(ConfigurableApplicationContext context, ConfigurableEnvironment environment) {
77-
register(context);
101+
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
102+
BeanDefinitionRegistry beanDefinitionRegistry = asBeanDefinitionRegistry(beanFactory);
103+
registerBeanDefinition(beanDefinitionRegistry, ListenableAutowireCandidateResolver.class);
78104
}
79105

80106
@Override

microsphere-spring-context/src/main/java/io/microsphere/spring/context/event/EventPublishingBeanInitializer.java

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,39 @@
2929
import static java.lang.Boolean.parseBoolean;
3030

3131
/**
32-
* {@link ApplicationContextInitializer} for Publishing Bean Event with the highest priority
32+
* An {@link ApplicationContextInitializer} that registers processors to publish Spring bean lifecycle events
33+
* during context initialization.
34+
* <p>
35+
* This initializer executes with the highest priority to guarantee that bean event publishing capabilities
36+
* are established before other components are processed. It automatically registers an
37+
* {@link EventPublishingBeanBeforeProcessor} as a {@link org.springframework.beans.factory.config.BeanFactoryPostProcessor}.
38+
*
39+
* <h3>Configuration Properties</h3>
40+
* <ul>
41+
* <li>{@code microsphere.spring.event-publishing-bean.enabled} -
42+
* Whether to enable the EventPublishingBean* (default: {@code false}).</li>
43+
* </ul>
44+
*
45+
* <h3>Example Usage</h3>
46+
* <h4>1. Configuration</h4>
47+
* <p><strong> application.properties (Spring Boot):</strong></p>
48+
* <pre>
49+
* microsphere.spring.event-publishing-bean.enabled=true
50+
* </pre>
51+
*
52+
* <p><strong> spring.factories (Spring Boot):</strong></p>
53+
* <pre>{@code
54+
* org.springframework.context.ApplicationContextInitializer=\
55+
* io.microsphere.spring.context.event.EventPublishingBeanInitializer
56+
* }</pre>
57+
*
58+
* <h4>2. Programmatic</h4>
59+
* <pre>{@code
60+
* new SpringApplicationBuilder(MyApplication.class)
61+
* .initializers(new EventPublishingBeanInitializer())
62+
* .properties("microsphere.spring.event-publishing-bean.enabled=true")
63+
* .run(args);
64+
* }</pre>
3365
*
3466
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
3567
* @see EventPublishingBeanBeforeProcessor

microsphere-spring-context/src/main/java/io/microsphere/spring/core/env/ListenableConfigurableEnvironmentInitializer.java

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,37 @@
2727
import static java.lang.Boolean.parseBoolean;
2828

2929
/**
30-
* The Initializer of {@link ListenableConfigurableEnvironment} based on {@link ApplicationContextInitializer}
30+
* An {@link ApplicationContextInitializer} implementation that initializes {@link ConfigurableEnvironment}
31+
* with {@link ListenableConfigurableEnvironment} to enable listening for environment changes.
3132
*
32-
* @author <a href="mailto:mercyblitz@gmail.com">Mercy<a/>
33+
* <h3>Configuration Properties</h3>
34+
* <ul>
35+
* <li>{@code microsphere.spring.listenable-environment.enabled} -
36+
* Whether to enable the {@link ListenableConfigurableEnvironment} (default: {@code false}).</li>
37+
* </ul>
38+
*
39+
* <h3>Example Usage</h3>
40+
* <h4>1. Configuration</h4>
41+
* <p><strong> application.properties (Spring Boot):</strong></p>
42+
* <pre>
43+
* microsphere.spring.listenable-environment.enabled=true
44+
* </pre>
45+
*
46+
* <p><strong> spring.factories (Spring Boot):</strong></p>
47+
* <pre>{@code
48+
* org.springframework.context.ApplicationContextInitializer=\
49+
* io.microsphere.spring.beans.factory.support.ListenableConfigurableEnvironmentInitializer
50+
* }</pre>
51+
*
52+
* <h4>2. Programmatic</h4>
53+
* <pre>{@code
54+
* new SpringApplicationBuilder(MyApplication.class)
55+
* .initializers(new ListenableConfigurableEnvironmentInitializer())
56+
* .properties("microsphere.spring.listenable-environment.enabled=true")
57+
* .run(args);
58+
* }</pre>
59+
*
60+
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
3361
* @see ListenableConfigurableEnvironment
3462
* @see EnvironmentListener
3563
* @see ProfileListener

microsphere-spring-context/src/test/java/io/microsphere/spring/beans/factory/support/ListenableAutowireCandidateResolverTest.java

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

2727
import static io.microsphere.logging.test.junit4.LoggingLevelsRule.levels;
2828
import static io.microsphere.reflect.FieldUtils.findField;
29-
import static io.microsphere.spring.beans.factory.support.ListenableAutowireCandidateResolver.ENABLED_PROPERTY_NAME;
29+
import static io.microsphere.spring.beans.factory.support.ListenableAutowireCandidateResolverInitializer.ENABLED_PROPERTY_NAME;
3030
import static io.microsphere.spring.core.SpringVersion.CURRENT;
3131
import static io.microsphere.spring.core.SpringVersion.SPRING_5_1;
3232
import static org.junit.Assert.assertEquals;

0 commit comments

Comments
 (0)