-
Notifications
You must be signed in to change notification settings - Fork 37
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #28 from microsphere-projects/dev
Sync 'dev' branch
- Loading branch information
Showing
16 changed files
with
1,977 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
105 changes: 105 additions & 0 deletions
105
.../java/io/microsphere/spring/beans/factory/support/AutowireCandidateResolvingListener.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
/* | ||
* Licensed to the Apache Software Foundation (ASF) under one or more | ||
* contributor license agreements. See the NOTICE file distributed with | ||
* this work for additional information regarding copyright ownership. | ||
* The ASF licenses this file to You under the Apache License, Version 2.0 | ||
* (the "License"); you may not use this file except in compliance with | ||
* the License. You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package io.microsphere.spring.beans.factory.support; | ||
|
||
import io.microsphere.spring.util.SpringFactoriesLoaderUtils; | ||
import org.springframework.beans.factory.BeanFactory; | ||
import org.springframework.beans.factory.ListableBeanFactory; | ||
import org.springframework.beans.factory.config.DependencyDescriptor; | ||
import org.springframework.beans.factory.support.AutowireCandidateResolver; | ||
import org.springframework.core.annotation.AnnotationAwareOrderComparator; | ||
import org.springframework.lang.Nullable; | ||
|
||
import java.util.LinkedList; | ||
import java.util.List; | ||
|
||
import static io.microsphere.spring.util.BeanUtils.getSortedBeans; | ||
import static io.microsphere.spring.util.SpringFactoriesLoaderUtils.loadFactories; | ||
import static java.util.Collections.unmodifiableList; | ||
import static org.springframework.core.annotation.AnnotationAwareOrderComparator.sort; | ||
|
||
/** | ||
* The Event Listener interface for the resolving processing including: | ||
* <ul> | ||
* <li>{@link AutowireCandidateResolver#getSuggestedValue(DependencyDescriptor) resolving suggested value}</li> | ||
* <li>{@link AutowireCandidateResolver#getLazyResolutionProxyIfNecessary(DependencyDescriptor, String) resolving lazy proxy}</li> | ||
* <li>{@link AutowireCandidateResolver#getLazyResolutionProxyClass(DependencyDescriptor, String) resolving lazy proxy class}</li> | ||
* </ul> | ||
* | ||
* @author <a href="mailto:mercyblitz@gmail.com">Mercy<a/> | ||
* @see ListenableAutowireCandidateResolver | ||
* @see LoggingAutowireCandidateResolvingListener | ||
* @see AutowireCandidateResolver | ||
* @since 1.0.0 | ||
*/ | ||
public interface AutowireCandidateResolvingListener { | ||
|
||
/** | ||
* Loads {@link AutowireCandidateResolvingListener the listeners} from | ||
* {@link SpringFactoriesLoaderUtils#loadFactories(BeanFactory, Class) Spring SPI with extension} and | ||
* {@link ListableBeanFactory#getBeansOfType Beans} | ||
* | ||
* @param beanFactory {@link BeanFactory} | ||
* @return the {@link AnnotationAwareOrderComparator#sort(List) sorted} {@link List} of | ||
* {@link AutowireCandidateResolvingListener the listeners} | ||
* @see SpringFactoriesLoaderUtils#loadFactories(BeanFactory, Class) | ||
*/ | ||
static List<AutowireCandidateResolvingListener> loadListeners(@Nullable BeanFactory beanFactory) { | ||
List<AutowireCandidateResolvingListener> listeners = new LinkedList<>(); | ||
// Add all Spring SPI with extension | ||
listeners.addAll(loadFactories(beanFactory, AutowireCandidateResolvingListener.class)); | ||
// Add all Spring Beans if BeanFactory is available | ||
if (beanFactory instanceof ListableBeanFactory lbf) { | ||
listeners.addAll(getSortedBeans(lbf, AutowireCandidateResolvingListener.class)); | ||
} | ||
// Sort | ||
sort(listeners); | ||
return unmodifiableList(listeners); | ||
} | ||
|
||
/** | ||
* The event raised after {@link AutowireCandidateResolver#getSuggestedValue(DependencyDescriptor)} called | ||
* | ||
* @param descriptor {@link DependencyDescriptor the descriptor for the target method parameter or field} | ||
* @param suggestedValue the value suggested (typically an expression String), or null if none found | ||
*/ | ||
default void suggestedValueResolved(DependencyDescriptor descriptor, @Nullable Object suggestedValue) { | ||
} | ||
|
||
/** | ||
* The event raised after {@link AutowireCandidateResolver#getLazyResolutionProxyIfNecessary(DependencyDescriptor, String)} called | ||
* | ||
* @param descriptor the descriptor for the target method parameter or field | ||
* @param beanName the name of the bean that contains the injection point | ||
* @param proxy the lazy resolution proxy for the actual dependency target, | ||
* or {@code null} if straight resolution is to be performed | ||
*/ | ||
default void lazyProxyResolved(DependencyDescriptor descriptor, @Nullable String beanName, @Nullable Object proxy) { | ||
} | ||
|
||
/** | ||
* The event raised after {@link AutowireCandidateResolver#getLazyResolutionProxyClass(DependencyDescriptor, String)} | ||
* called | ||
* | ||
* @param descriptor the descriptor for the target method parameter or field | ||
* @param beanName the name of the bean that contains the injection point | ||
* @param proxyClass the lazy resolution proxy class for the dependency target | ||
* @see AutowireCandidateResolver#getLazyResolutionProxyClass(DependencyDescriptor, String) | ||
*/ | ||
default void lazyProxyClassResolved(DependencyDescriptor descriptor, @Nullable String beanName, @Nullable Class<?> proxyClass) { | ||
} | ||
} |
68 changes: 68 additions & 0 deletions
68
...microsphere/spring/beans/factory/support/CompositeAutowireCandidateResolvingListener.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
/* | ||
* Licensed to the Apache Software Foundation (ASF) under one or more | ||
* contributor license agreements. See the NOTICE file distributed with | ||
* this work for additional information regarding copyright ownership. | ||
* The ASF licenses this file to You under the Apache License, Version 2.0 | ||
* (the "License"); you may not use this file except in compliance with | ||
* the License. You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package io.microsphere.spring.beans.factory.support; | ||
|
||
import org.springframework.beans.factory.config.DependencyDescriptor; | ||
|
||
import java.util.LinkedList; | ||
import java.util.List; | ||
|
||
import static io.microsphere.collection.CollectionUtils.isNotEmpty; | ||
import static io.microsphere.collection.ListUtils.forEach; | ||
import static org.springframework.core.annotation.AnnotationAwareOrderComparator.sort; | ||
import static org.springframework.util.Assert.isTrue; | ||
import static org.springframework.util.Assert.notNull; | ||
|
||
/** | ||
* The composite class for {@link AutowireCandidateResolvingListener} | ||
* | ||
* @author <a href="mailto:mercyblitz@gmail.com">Mercy<a/> | ||
* @see AutowireCandidateResolvingListener | ||
* @since 1.0.0 | ||
*/ | ||
public class CompositeAutowireCandidateResolvingListener implements AutowireCandidateResolvingListener { | ||
|
||
private final List<AutowireCandidateResolvingListener> listeners = new LinkedList<>(); | ||
|
||
public CompositeAutowireCandidateResolvingListener(List<AutowireCandidateResolvingListener> listeners) { | ||
isTrue(isNotEmpty(listeners), "The argument 'listeners' must not be empty!"); | ||
this.addListeners(listeners); | ||
} | ||
|
||
public void addListeners(List<AutowireCandidateResolvingListener> listeners) { | ||
forEach(listeners, listener -> { | ||
notNull(listener, "The element 'listener' must not be null!"); | ||
this.listeners.add(listener); | ||
}); | ||
sort(this.listeners); | ||
} | ||
|
||
@Override | ||
public void suggestedValueResolved(DependencyDescriptor descriptor, Object suggestedValue) { | ||
forEach(listeners, listener -> listener.suggestedValueResolved(descriptor, suggestedValue)); | ||
} | ||
|
||
@Override | ||
public void lazyProxyResolved(DependencyDescriptor descriptor, String beanName, Object proxy) { | ||
forEach(listeners, listener -> listener.lazyProxyResolved(descriptor, beanName, proxy)); | ||
} | ||
|
||
@Override | ||
public void lazyProxyClassResolved(DependencyDescriptor descriptor, String beanName, Class<?> proxyClass) { | ||
forEach(listeners, listener -> listener.lazyProxyClassResolved(descriptor, beanName, proxyClass)); | ||
} | ||
} |
137 changes: 137 additions & 0 deletions
137
...java/io/microsphere/spring/beans/factory/support/ListenableAutowireCandidateResolver.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
/* | ||
* Licensed to the Apache Software Foundation (ASF) under one or more | ||
* contributor license agreements. See the NOTICE file distributed with | ||
* this work for additional information regarding copyright ownership. | ||
* The ASF licenses this file to You under the Apache License, Version 2.0 | ||
* (the "License"); you may not use this file except in compliance with | ||
* the License. You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package io.microsphere.spring.beans.factory.support; | ||
|
||
import org.springframework.beans.BeansException; | ||
import org.springframework.beans.factory.BeanFactory; | ||
import org.springframework.beans.factory.config.BeanDefinitionHolder; | ||
import org.springframework.beans.factory.config.BeanFactoryPostProcessor; | ||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; | ||
import org.springframework.beans.factory.config.DependencyDescriptor; | ||
import org.springframework.beans.factory.support.AutowireCandidateResolver; | ||
import org.springframework.beans.factory.support.DefaultListableBeanFactory; | ||
import org.springframework.lang.Nullable; | ||
|
||
import java.util.Arrays; | ||
import java.util.List; | ||
|
||
import static io.microsphere.spring.beans.factory.support.AutowireCandidateResolvingListener.loadListeners; | ||
import static io.microsphere.spring.util.BeanFactoryUtils.asDefaultListableBeanFactory; | ||
import static io.microsphere.util.ArrayUtils.combine; | ||
|
||
/** | ||
* The decorator class of {@link AutowireCandidateResolver} to listen to the resolving process of autowire candidate by | ||
* {@link AutowireCandidateResolvingListener} | ||
* | ||
* @author <a href="mailto:mercyblitz@gmail.com">Mercy<a/> | ||
* @see AutowireCandidateResolver | ||
* @see AutowireCandidateResolvingListener | ||
* @see CompositeAutowireCandidateResolvingListener | ||
* @see DefaultListableBeanFactory#setAutowireCandidateResolver(AutowireCandidateResolver) | ||
* @see BeanFactoryPostProcessor | ||
* @since 1.0.0 | ||
*/ | ||
public class ListenableAutowireCandidateResolver implements AutowireCandidateResolver, BeanFactoryPostProcessor { | ||
|
||
private AutowireCandidateResolver delegate; | ||
|
||
private CompositeAutowireCandidateResolvingListener compositeListener; | ||
|
||
private ConfigurableListableBeanFactory beanFactory; | ||
|
||
public ListenableAutowireCandidateResolver() { | ||
} | ||
|
||
public void addListener(AutowireCandidateResolvingListener one, AutowireCandidateResolvingListener... more) { | ||
addListeners(combine(one, more)); | ||
} | ||
|
||
public void addListeners(AutowireCandidateResolvingListener[] listeners) { | ||
addListeners(Arrays.asList(listeners)); | ||
} | ||
|
||
public void addListeners(List<AutowireCandidateResolvingListener> listeners) { | ||
compositeListener.addListeners(listeners); | ||
} | ||
|
||
@Override | ||
public boolean isAutowireCandidate(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) { | ||
return delegate.isAutowireCandidate(bdHolder, descriptor); | ||
} | ||
|
||
@Override | ||
public boolean isRequired(DependencyDescriptor descriptor) { | ||
return delegate.isRequired(descriptor); | ||
} | ||
|
||
@Override | ||
public boolean hasQualifier(DependencyDescriptor descriptor) { | ||
return delegate.hasQualifier(descriptor); | ||
} | ||
|
||
@Nullable | ||
@Override | ||
public Object getSuggestedValue(DependencyDescriptor descriptor) { | ||
Object suggestedValue = delegate.getSuggestedValue(descriptor); | ||
compositeListener.suggestedValueResolved(descriptor, suggestedValue); | ||
return suggestedValue; | ||
} | ||
|
||
@Nullable | ||
@Override | ||
public Object getLazyResolutionProxyIfNecessary(DependencyDescriptor descriptor, String beanName) { | ||
Object proxy = delegate.getLazyResolutionProxyIfNecessary(descriptor, beanName); | ||
compositeListener.lazyProxyResolved(descriptor, beanName, proxy); | ||
return proxy; | ||
} | ||
|
||
@Nullable | ||
@Override | ||
public Class<?> getLazyResolutionProxyClass(DependencyDescriptor descriptor, String beanName) { | ||
Class<?> proxyClass = delegate.getLazyResolutionProxyClass(descriptor, beanName); | ||
compositeListener.lazyProxyClassResolved(descriptor, beanName, proxyClass); | ||
return proxyClass; | ||
} | ||
|
||
@Override | ||
public AutowireCandidateResolver cloneIfNecessary() { | ||
return delegate.cloneIfNecessary(); | ||
} | ||
|
||
@Override | ||
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { | ||
wrap(beanFactory); | ||
} | ||
|
||
/** | ||
* Wraps {@link AutowireCandidateResolver} as the {@link ListenableAutowireCandidateResolver} and then register to | ||
* the given {@link DefaultListableBeanFactory} | ||
* | ||
* @param beanFactory {@link DefaultListableBeanFactory} | ||
*/ | ||
public void wrap(BeanFactory beanFactory) { | ||
DefaultListableBeanFactory dbf = asDefaultListableBeanFactory(beanFactory); | ||
AutowireCandidateResolver autowireCandidateResolver = dbf.getAutowireCandidateResolver(); | ||
if (autowireCandidateResolver != null) { | ||
List<AutowireCandidateResolvingListener> listeners = loadListeners(beanFactory); | ||
CompositeAutowireCandidateResolvingListener compositeListener = new CompositeAutowireCandidateResolvingListener(listeners); | ||
this.delegate = autowireCandidateResolver; | ||
this.compositeListener = compositeListener; | ||
dbf.setAutowireCandidateResolver(this); | ||
} | ||
} | ||
} |
62 changes: 62 additions & 0 deletions
62
...o/microsphere/spring/beans/factory/support/LoggingAutowireCandidateResolvingListener.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
/* | ||
* Licensed to the Apache Software Foundation (ASF) under one or more | ||
* contributor license agreements. See the NOTICE file distributed with | ||
* this work for additional information regarding copyright ownership. | ||
* The ASF licenses this file to You under the Apache License, Version 2.0 | ||
* (the "License"); you may not use this file except in compliance with | ||
* the License. You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package io.microsphere.spring.beans.factory.support; | ||
|
||
import io.microsphere.logging.Logger; | ||
import io.microsphere.logging.LoggerFactory; | ||
import org.springframework.beans.factory.config.DependencyDescriptor; | ||
|
||
/** | ||
* {@link Logger logging} {@link AutowireCandidateResolvingListener} | ||
* | ||
* @author <a href="mailto:mercyblitz@gmail.com">Mercy<a/> | ||
* @see AutowireCandidateResolvingListener | ||
* @see Logger | ||
* @since 1.0.0 | ||
*/ | ||
public class LoggingAutowireCandidateResolvingListener implements AutowireCandidateResolvingListener { | ||
|
||
private static final Logger logger = LoggerFactory.getLogger(LoggingAutowireCandidateResolvingListener.class); | ||
|
||
@Override | ||
public void suggestedValueResolved(DependencyDescriptor descriptor, Object suggestedValue) { | ||
if (suggestedValue != null) { | ||
if (logger.isInfoEnabled()) { | ||
logger.info("The suggested value for {} was resolved : {}", descriptor, suggestedValue); | ||
} | ||
} | ||
} | ||
|
||
@Override | ||
public void lazyProxyResolved(DependencyDescriptor descriptor, String beanName, Object proxy) { | ||
if (proxy != null) { | ||
if (logger.isInfoEnabled()) { | ||
logger.info("The lazy proxy[descriptor : {} , bean name : '{}'] was resolved : {}", descriptor, beanName, proxy); | ||
} | ||
} | ||
} | ||
|
||
@Override | ||
public void lazyProxyClassResolved(DependencyDescriptor descriptor, String beanName, Class<?> proxyClass) { | ||
if (proxyClass != null) { | ||
if (logger.isInfoEnabled()) { | ||
logger.info("The lazy proxy class [descriptor : {} , bean name : '{}'] was resolved : {}", descriptor, beanName, proxyClass); | ||
} | ||
} | ||
} | ||
|
||
} |
Oops, something went wrong.