custom stereotype annotations can be meta-annotated with @Service, @Controller etc as well; @Scope and @Transactional are now supported as meta-annotations on custom annotations
This commit is contained in:
@@ -19,7 +19,6 @@ package org.springframework.context.annotation;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.aop.scope.ScopedProxyUtils;
|
||||
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
||||
@@ -318,17 +317,4 @@ public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateCo
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Inner factory class used to just introduce an AOP framework dependency
|
||||
* when actually creating a scoped proxy.
|
||||
*/
|
||||
private static class ScopedProxyCreator {
|
||||
|
||||
public static BeanDefinitionHolder createScopedProxy(
|
||||
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry, boolean proxyTargetClass) {
|
||||
|
||||
return ScopedProxyUtils.createScopedProxy(definitionHolder, registry, proxyTargetClass);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@ import java.util.Set;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.aop.scope.ScopedProxyUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowire;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
||||
@@ -184,7 +183,7 @@ class ConfigurationClassBeanDefinitionReader {
|
||||
// replace the original bean definition with the target one, if necessary
|
||||
BeanDefinition beanDefToRegister = beanDef;
|
||||
if (proxyMode != ScopedProxyMode.NO) {
|
||||
BeanDefinitionHolder proxyDef = ScopedProxyUtils.createScopedProxy(
|
||||
BeanDefinitionHolder proxyDef = ScopedProxyCreator.createScopedProxy(
|
||||
new BeanDefinitionHolder(beanDef, beanName), registry, proxyMode == ScopedProxyMode.TARGET_CLASS);
|
||||
beanDefToRegister = proxyDef.getBeanDefinition();
|
||||
}
|
||||
|
||||
@@ -60,14 +60,17 @@ class ConfigurationClassEnhancer {
|
||||
*/
|
||||
public ConfigurationClassEnhancer(ConfigurableBeanFactory beanFactory) {
|
||||
Assert.notNull(beanFactory, "BeanFactory must not be null");
|
||||
|
||||
this.callbackInstances.add(new BeanMethodInterceptor(beanFactory));
|
||||
this.callbackInstances.add(NoOp.INSTANCE);
|
||||
|
||||
for (Callback callback : this.callbackInstances) {
|
||||
this.callbackTypes.add(callback.getClass());
|
||||
}
|
||||
|
||||
// Set up the callback filter to return the index of the BeanMethodInterceptor when
|
||||
// handling a @Bean-annotated method; otherwise, return index of the NoOp callback.
|
||||
this.callbackFilter = new CallbackFilter() {
|
||||
callbackFilter = new CallbackFilter() {
|
||||
public int accept(Method candidateMethod) {
|
||||
return (AnnotationUtils.findAnnotation(candidateMethod, Bean.class) != null) ? 0 : 1;
|
||||
}
|
||||
@@ -85,8 +88,8 @@ class ConfigurationClassEnhancer {
|
||||
logger.debug("Enhancing " + configClass.getName());
|
||||
}
|
||||
Class<?> enhancedClass = createClass(newEnhancer(configClass));
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(String.format("Successfully enhanced %s; enhanced class name is: %s",
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info(String.format("Successfully enhanced %s; enhanced class name is: %s",
|
||||
configClass.getName(), enhancedClass.getName()));
|
||||
}
|
||||
return enhancedClass;
|
||||
@@ -151,6 +154,7 @@ class ConfigurationClassEnhancer {
|
||||
}
|
||||
|
||||
// determine whether this bean is a scoped-proxy
|
||||
// TODO: remove hard ScopedProxyUtils dependency
|
||||
Scope scope = AnnotationUtils.findAnnotation(method, Scope.class);
|
||||
if (scope != null && scope.proxyMode() != ScopedProxyMode.NO) {
|
||||
String scopedBeanName = ScopedProxyUtils.getTargetBeanName(beanName);
|
||||
|
||||
@@ -17,7 +17,9 @@
|
||||
package org.springframework.context.annotation;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
@@ -121,7 +123,7 @@ public class ConfigurationClassPostProcessor implements BeanFactoryPostProcessor
|
||||
* Build and validate a configuration model based on the registry of
|
||||
* {@link Configuration} classes.
|
||||
*/
|
||||
protected final void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
|
||||
protected void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
|
||||
Set<BeanDefinitionHolder> configCandidates = new LinkedHashSet<BeanDefinitionHolder>();
|
||||
for (String beanName : registry.getBeanDefinitionNames()) {
|
||||
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
|
||||
@@ -157,14 +159,19 @@ public class ConfigurationClassPostProcessor implements BeanFactoryPostProcessor
|
||||
new ConfigurationClassBeanDefinitionReader(registry).loadBeanDefinitions(parser.getModel());
|
||||
}
|
||||
|
||||
private boolean checkConfigurationClassCandidate(BeanDefinition beanDef) {
|
||||
/**
|
||||
* Check whether the given bean definition is a candidate for a configuration class,
|
||||
* and mark it accordingly.
|
||||
* @param beanDef the bean definition to check
|
||||
* @return whether the candidate qualifies as (any kind of) configuration class
|
||||
*/
|
||||
protected boolean checkConfigurationClassCandidate(BeanDefinition beanDef) {
|
||||
AnnotationMetadata metadata;
|
||||
|
||||
// Check already loaded Class if present...
|
||||
// since we possibly can't even load the class file for this Class.
|
||||
if (beanDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) beanDef).hasBeanClass()) {
|
||||
Class beanClass = ((AbstractBeanDefinition) beanDef).getBeanClass();
|
||||
metadata = new StandardAnnotationMetadata(beanClass);
|
||||
metadata = new StandardAnnotationMetadata(((AbstractBeanDefinition) beanDef).getBeanClass());
|
||||
}
|
||||
else {
|
||||
String className = beanDef.getBeanClassName();
|
||||
@@ -199,12 +206,16 @@ public class ConfigurationClassPostProcessor implements BeanFactoryPostProcessor
|
||||
* Candidate status is determined by BeanDefinition attribute metadata.
|
||||
* @see ConfigurationClassEnhancer
|
||||
*/
|
||||
private void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
|
||||
Set<BeanDefinitionHolder> configBeanDefs = new LinkedHashSet<BeanDefinitionHolder>();
|
||||
protected void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
|
||||
Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<String, AbstractBeanDefinition>();
|
||||
for (String beanName : beanFactory.getBeanDefinitionNames()) {
|
||||
BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
|
||||
if (CONFIGURATION_CLASS_FULL.equals(beanDef.getAttribute(CONFIGURATION_CLASS_ATTRIBUTE))) {
|
||||
configBeanDefs.add(new BeanDefinitionHolder(beanDef, beanName));
|
||||
if (!(beanDef instanceof AbstractBeanDefinition)) {
|
||||
throw new BeanDefinitionStoreException("Cannot enhance @Configuration bean definition '" +
|
||||
beanName + "' since it is not stored in an AbstractBeanDefinition subclass");
|
||||
}
|
||||
configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);
|
||||
}
|
||||
}
|
||||
if (configBeanDefs.isEmpty()) {
|
||||
@@ -212,27 +223,23 @@ public class ConfigurationClassPostProcessor implements BeanFactoryPostProcessor
|
||||
return;
|
||||
}
|
||||
if (!cglibAvailable) {
|
||||
Set<String> beanNames = new LinkedHashSet<String>();
|
||||
for (BeanDefinitionHolder holder : configBeanDefs) {
|
||||
beanNames.add(holder.getBeanName());
|
||||
}
|
||||
throw new IllegalStateException("CGLIB is required to process @Configuration classes. " +
|
||||
"Either add CGLIB to the classpath or remove the following @Configuration bean definitions: " +
|
||||
beanNames);
|
||||
configBeanDefs.keySet());
|
||||
}
|
||||
ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer(beanFactory);
|
||||
for (BeanDefinitionHolder holder : configBeanDefs) {
|
||||
AbstractBeanDefinition beanDef = (AbstractBeanDefinition) holder.getBeanDefinition();
|
||||
for (Map.Entry<String, AbstractBeanDefinition> entry : configBeanDefs.entrySet()) {
|
||||
AbstractBeanDefinition beanDef = entry.getValue();
|
||||
try {
|
||||
Class configClass = beanDef.resolveBeanClass(this.beanClassLoader);
|
||||
Class enhancedClass = enhancer.enhance(configClass);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(String.format("Replacing bean definition '%s' existing class name '%s' " +
|
||||
"with enhanced class name '%s'", holder.getBeanName(), configClass.getName(), enhancedClass.getName()));
|
||||
"with enhanced class name '%s'", entry.getKey(), configClass.getName(), enhancedClass.getName()));
|
||||
}
|
||||
beanDef.setBeanClass(enhancedClass);
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
catch (Throwable ex) {
|
||||
throw new IllegalStateException("Cannot load configuration class: " + beanDef.getBeanClassName(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
*
|
||||
* Licensed 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 org.springframework.context.annotation;
|
||||
|
||||
import org.springframework.aop.scope.ScopedProxyUtils;
|
||||
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
|
||||
/**
|
||||
* Delegate factory class used to just introduce an AOP framework dependency
|
||||
* when actually creating a scoped proxy.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
* @see org.springframework.aop.scope.ScopedProxyUtils#createScopedProxy
|
||||
*/
|
||||
class ScopedProxyCreator {
|
||||
|
||||
public static BeanDefinitionHolder createScopedProxy(
|
||||
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry, boolean proxyTargetClass) {
|
||||
|
||||
return ScopedProxyUtils.createScopedProxy(definitionHolder, registry, proxyTargetClass);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user