Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
爱吃血肠
spring-framework
提交
ea9d8925
S
spring-framework
项目概览
爱吃血肠
/
spring-framework
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
S
spring-framework
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
ea9d8925
编写于
4月 22, 2009
作者:
J
Juergen Hoeller
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
next cut of JavaConfig metadata reading revision: using cached MetadataReaders
上级
4c42597c
变更
17
隐藏空白更改
内联
并排
Showing
17 changed file
with
339 addition
and
286 deletion
+339
-286
org.springframework.beans/src/main/java/org/springframework/beans/factory/annotation/QualifierAnnotationAutowireCandidateResolver.java
...otation/QualifierAnnotationAutowireCandidateResolver.java
+2
-2
org.springframework.beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java
...gframework/beans/factory/support/AbstractBeanFactory.java
+6
-1
org.springframework.beans/src/main/java/org/springframework/beans/factory/support/ConstructorResolver.java
...gframework/beans/factory/support/ConstructorResolver.java
+36
-4
org.springframework.beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java
...ork/beans/factory/support/DefaultListableBeanFactory.java
+2
-29
org.springframework.beans/src/main/java/org/springframework/beans/factory/support/RootBeanDefinition.java
...ngframework/beans/factory/support/RootBeanDefinition.java
+28
-6
org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClass.java
...pringframework/context/annotation/ConfigurationClass.java
+67
-35
org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassAnnotationVisitor.java
...ntext/annotation/ConfigurationClassAnnotationVisitor.java
+33
-29
org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassBeanDefinitionReader.java
...xt/annotation/ConfigurationClassBeanDefinitionReader.java
+21
-4
org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java
...ramework/context/annotation/ConfigurationClassParser.java
+11
-12
org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassPostProcessor.java
...k/context/annotation/ConfigurationClassPostProcessor.java
+13
-4
org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassReaderUtils.java
...ork/context/annotation/ConfigurationClassReaderUtils.java
+14
-108
org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassVisitor.java
...amework/context/annotation/ConfigurationClassVisitor.java
+50
-33
org.springframework.context/src/test/java/org/springframework/context/annotation/AsmCircularImportDetectionTests.java
...k/context/annotation/AsmCircularImportDetectionTests.java
+3
-5
org.springframework.context/src/test/java/org/springframework/context/annotation4/FactoryMethodComponent.java
...framework/context/annotation4/FactoryMethodComponent.java
+5
-1
org.springframework.core/src/main/java/org/springframework/core/type/classreading/CachingMetadataReaderFactory.java
.../core/type/classreading/CachingMetadataReaderFactory.java
+3
-3
org.springframework.core/src/main/java/org/springframework/core/type/classreading/SimpleMetadataReader.java
...ramework/core/type/classreading/SimpleMetadataReader.java
+34
-8
org.springframework.core/src/main/java/org/springframework/core/type/classreading/SimpleMetadataReaderFactory.java
...k/core/type/classreading/SimpleMetadataReaderFactory.java
+11
-2
未找到文件。
org.springframework.beans/src/main/java/org/springframework/beans/factory/annotation/QualifierAnnotationAutowireCandidateResolver.java
浏览文件 @
ea9d8925
...
...
@@ -192,8 +192,8 @@ public class QualifierAnnotationAutowireCandidateResolver implements AutowireCan
}
if
(
qualifier
==
null
)
{
Annotation
targetAnnotation
=
null
;
if
(
bd
.
get
FactoryMethodForIntrospection
()
!=
null
)
{
targetAnnotation
=
bd
.
get
FactoryMethodForIntrospection
().
getAnnotation
(
type
);
if
(
bd
.
get
ResolvedFactoryMethod
()
!=
null
)
{
targetAnnotation
=
bd
.
get
ResolvedFactoryMethod
().
getAnnotation
(
type
);
}
if
(
targetAnnotation
==
null
&&
bd
.
hasBeanClass
())
{
// look for matching annotation on the target class
...
...
org.springframework.beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java
浏览文件 @
ea9d8925
...
...
@@ -1025,7 +1025,12 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
if
(
mbd
==
null
)
{
if
(
bd
.
getParentName
()
==
null
)
{
// Use copy of given root bean definition.
mbd
=
new
RootBeanDefinition
(
bd
);
if
(
bd
instanceof
RootBeanDefinition
)
{
mbd
=
((
RootBeanDefinition
)
bd
).
cloneBeanDefinition
();
}
else
{
mbd
=
new
RootBeanDefinition
(
bd
);
}
}
else
{
// Child bean definition: needs to be merged with parent.
...
...
org.springframework.beans/src/main/java/org/springframework/beans/factory/support/ConstructorResolver.java
浏览文件 @
ea9d8925
...
...
@@ -21,6 +21,7 @@ import java.lang.reflect.Member;
import
java.lang.reflect.Method
;
import
java.lang.reflect.Modifier
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.HashSet
;
import
java.util.LinkedHashSet
;
import
java.util.LinkedList
;
...
...
@@ -43,10 +44,10 @@ import org.springframework.beans.factory.config.DependencyDescriptor;
import
org.springframework.beans.factory.config.TypedStringValue
;
import
org.springframework.core.GenericTypeResolver
;
import
org.springframework.core.MethodParameter
;
import
org.springframework.util.ClassUtils
;
import
org.springframework.util.MethodInvoker
;
import
org.springframework.util.ObjectUtils
;
import
org.springframework.util.ReflectionUtils
;
import
org.springframework.util.ClassUtils
;
/**
* Helper class for resolving constructors and factory methods.
...
...
@@ -247,6 +248,36 @@ class ConstructorResolver {
}
}
/**
* Resolve the factory method in the specified bean definition, if possible.
* {@link RootBeanDefinition#getResolvedFactoryMethod()} can be checked for the result.
* @param mbd the bean definition to check
*/
public
void
resolveFactoryMethodIfPossible
(
RootBeanDefinition
mbd
)
{
Class
factoryClass
;
if
(
mbd
.
getFactoryBeanName
()
!=
null
)
{
factoryClass
=
this
.
beanFactory
.
getType
(
mbd
.
getFactoryBeanName
());
}
else
{
factoryClass
=
mbd
.
getBeanClass
();
}
factoryClass
=
ClassUtils
.
getUserClass
(
factoryClass
);
Method
[]
candidates
=
ReflectionUtils
.
getAllDeclaredMethods
(
factoryClass
);
Method
uniqueCandidate
=
null
;
for
(
Method
candidate
:
candidates
)
{
if
(
mbd
.
isFactoryMethod
(
candidate
))
{
if
(
uniqueCandidate
==
null
)
{
uniqueCandidate
=
candidate
;
}
else
if
(!
Arrays
.
equals
(
uniqueCandidate
.
getParameterTypes
(),
candidate
.
getParameterTypes
()))
{
uniqueCandidate
=
null
;
break
;
}
}
}
mbd
.
resolvedConstructorOrFactoryMethod
=
uniqueCandidate
;
}
/**
* Instantiate the bean using a named factory method. The method may be static, if the
* bean definition parameter specifies a class, rather than a "factory-bean", or
...
...
@@ -306,13 +337,13 @@ class ConstructorResolver {
if
(
factoryMethodToUse
!=
null
)
{
// Found a cached factory method...
argsToUse
=
mbd
.
resolvedConstructorArguments
;
if
(
argsToUse
==
null
)
{
if
(
argsToUse
==
null
&&
mbd
.
preparedConstructorArguments
!=
null
)
{
argsToUse
=
resolvePreparedArguments
(
beanName
,
mbd
,
bw
,
factoryMethodToUse
);
}
}
}
if
(
factoryMethodToUse
==
null
)
{
if
(
factoryMethodToUse
==
null
||
argsToUse
==
null
)
{
// Need to determine the factory method...
// Try all methods with this name to see if they match the given arguments.
factoryClass
=
ClassUtils
.
getUserClass
(
factoryClass
);
...
...
@@ -320,7 +351,8 @@ class ConstructorResolver {
List
<
Method
>
candidateSet
=
new
ArrayList
<
Method
>();
for
(
Method
candidate
:
rawCandidates
)
{
if
(
Modifier
.
isStatic
(
candidate
.
getModifiers
())
==
isStatic
&&
candidate
.
getName
().
equals
(
mbd
.
getFactoryMethodName
()))
{
candidate
.
getName
().
equals
(
mbd
.
getFactoryMethodName
())
&&
mbd
.
isFactoryMethod
(
candidate
))
{
candidateSet
.
add
(
candidate
);
}
}
...
...
org.springframework.beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java
浏览文件 @
ea9d8925
...
...
@@ -17,9 +17,7 @@
package
org.springframework.beans.factory.support
;
import
java.lang.annotation.Annotation
;
import
java.lang.reflect.Method
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.Collection
;
import
java.util.HashMap
;
import
java.util.LinkedHashMap
;
...
...
@@ -49,9 +47,7 @@ import org.springframework.beans.factory.config.DependencyDescriptor;
import
org.springframework.core.ParameterNameDiscoverer
;
import
org.springframework.core.annotation.AnnotationUtils
;
import
org.springframework.util.Assert
;
import
org.springframework.util.ClassUtils
;
import
org.springframework.util.ObjectUtils
;
import
org.springframework.util.ReflectionUtils
;
import
org.springframework.util.StringUtils
;
/**
...
...
@@ -432,31 +428,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
*/
protected
boolean
isAutowireCandidate
(
String
beanName
,
RootBeanDefinition
mbd
,
DependencyDescriptor
descriptor
)
{
resolveBeanClass
(
mbd
,
beanName
);
// TODO: the following is duplicating the factory method resolution algorithm in
// ConstructorResolver quite a bit...
if
(
mbd
.
getFactoryMethodName
()
!=
null
&&
mbd
.
factoryMethodForIntrospection
==
null
)
{
Class
factoryClass
;
if
(
mbd
.
getFactoryBeanName
()
!=
null
)
{
factoryClass
=
getType
(
mbd
.
getFactoryBeanName
());
}
else
{
factoryClass
=
mbd
.
getBeanClass
();
}
factoryClass
=
ClassUtils
.
getUserClass
(
factoryClass
);
Method
[]
candidates
=
ReflectionUtils
.
getAllDeclaredMethods
(
factoryClass
);
Method
uniqueCandidate
=
null
;
for
(
Method
candidate
:
candidates
)
{
if
(
candidate
.
getName
().
equals
(
mbd
.
getFactoryMethodName
()))
{
if
(
uniqueCandidate
==
null
)
{
uniqueCandidate
=
candidate
;
}
else
if
(!
Arrays
.
equals
(
uniqueCandidate
.
getParameterTypes
(),
candidate
.
getParameterTypes
()))
{
uniqueCandidate
=
null
;
break
;
}
}
}
mbd
.
factoryMethodForIntrospection
=
uniqueCandidate
;
if
(
mbd
.
isFactoryMethodUnique
&&
mbd
.
resolvedConstructorOrFactoryMethod
==
null
)
{
new
ConstructorResolver
(
this
,
null
,
null
,
null
).
resolveFactoryMethodIfPossible
(
mbd
);
}
return
getAutowireCandidateResolver
().
isAutowireCandidate
(
new
BeanDefinitionHolder
(
mbd
,
beanName
,
getAliases
(
beanName
)),
descriptor
);
...
...
org.springframework.beans/src/main/java/org/springframework/beans/factory/support/RootBeanDefinition.java
浏览文件 @
ea9d8925
/*
* Copyright 2002-200
8
the original author or authors.
* Copyright 2002-200
9
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.
...
...
@@ -25,6 +25,7 @@ import java.util.Set;
import
org.springframework.beans.MutablePropertyValues
;
import
org.springframework.beans.factory.config.BeanDefinition
;
import
org.springframework.beans.factory.config.ConstructorArgumentValues
;
import
org.springframework.util.Assert
;
/**
* A root bean definition represents the merged bean definition that backs
...
...
@@ -52,7 +53,7 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
private
final
Set
<
String
>
externallyManagedDestroyMethods
=
Collections
.
synchronizedSet
(
new
HashSet
<
String
>());
volatile
Method
factoryMethodForIntrospection
;
boolean
isFactoryMethodUnique
;
/** Package-visible field for caching the resolved constructor or factory method */
volatile
Object
resolvedConstructorOrFactoryMethod
;
...
...
@@ -198,7 +199,7 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
* @param original the original bean definition to copy from
*/
public
RootBeanDefinition
(
RootBeanDefinition
original
)
{
super
((
BeanDefinition
)
original
);
this
((
BeanDefinition
)
original
);
}
/**
...
...
@@ -208,6 +209,9 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
*/
RootBeanDefinition
(
BeanDefinition
original
)
{
super
(
original
);
if
(
original
instanceof
RootBeanDefinition
)
{
this
.
isFactoryMethodUnique
=
((
RootBeanDefinition
)
original
).
isFactoryMethodUnique
;
}
}
...
...
@@ -221,8 +225,26 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
}
}
public
Method
getFactoryMethodForIntrospection
()
{
return
this
.
factoryMethodForIntrospection
;
/**
* Specify a factory method name that refers to a non-overloaded method.
*/
public
void
setUniqueFactoryMethodName
(
String
name
)
{
Assert
.
hasText
(
name
,
"Factory method name must not be empty"
);
setFactoryMethodName
(
name
);
this
.
isFactoryMethodUnique
=
true
;
}
public
boolean
isFactoryMethod
(
Method
candidate
)
{
return
(
candidate
!=
null
&&
candidate
.
getName
().
equals
(
getFactoryMethodName
()));
}
/**
* Return the resolved factory method as a Java Method object, if available.
* @return the factory method, or <code>null</code> if not found or not resolved yet
*/
public
Method
getResolvedFactoryMethod
()
{
Object
candidate
=
this
.
resolvedConstructorOrFactoryMethod
;
return
(
candidate
instanceof
Method
?
(
Method
)
candidate
:
null
);
}
...
...
@@ -252,7 +274,7 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
@Override
public
Abstrac
tBeanDefinition
cloneBeanDefinition
()
{
public
Roo
tBeanDefinition
cloneBeanDefinition
()
{
return
new
RootBeanDefinition
(
this
);
}
...
...
org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClass.java
浏览文件 @
ea9d8925
...
...
@@ -19,6 +19,9 @@ package org.springframework.context.annotation;
import
java.lang.annotation.Annotation
;
import
java.lang.reflect.Modifier
;
import
java.util.HashSet
;
import
java.util.LinkedHashMap
;
import
java.util.LinkedHashSet
;
import
java.util.Map
;
import
java.util.Set
;
import
org.springframework.beans.BeanMetadataElement
;
...
...
@@ -46,31 +49,33 @@ final class ConfigurationClass implements BeanMetadataElement {
private
String
name
;
private
transient
Object
source
;
private
ConfigurationClass
declaringClass
;
private
Object
source
;
private
String
beanName
;
private
int
modifiers
;
private
Set
<
Annotation
>
annotations
=
new
HashSet
<
Annotation
>();
private
final
Set
<
Annotation
>
annotations
=
new
HashSet
<
Annotation
>();
private
Set
<
ConfigurationClassMethod
>
methods
=
new
HashSet
<
ConfigurationClassMethod
>();
private
final
Set
<
ConfigurationClassMethod
>
methods
=
new
Linked
HashSet
<
ConfigurationClassMethod
>();
private
ConfigurationClass
declaringClass
;
private
final
Map
<
String
,
Integer
>
overloadedMethodMap
=
new
LinkedHashMap
<
String
,
Integer
>()
;
/**
*
Return
s the fully-qualified name of this class.
*
Set
s the fully-qualified name of this class.
*/
public
String
getName
(
)
{
return
n
ame
;
public
void
setName
(
String
className
)
{
this
.
name
=
classN
ame
;
}
/**
*
Set
s the fully-qualified name of this class.
*
Return
s the fully-qualified name of this class.
*/
public
void
setName
(
String
className
)
{
this
.
name
=
classN
ame
;
public
String
getName
(
)
{
return
n
ame
;
}
/**
...
...
@@ -80,12 +85,12 @@ final class ConfigurationClass implements BeanMetadataElement {
return
name
==
null
?
null
:
ClassUtils
.
getShortName
(
name
);
}
/**
* Returns a resource path-formatted representation of the .java file that declares this
* class
*/
public
Object
getSource
()
{
return
source
;
public
void
setDeclaringClass
(
ConfigurationClass
configurationClass
)
{
this
.
declaringClass
=
configurationClass
;
}
public
ConfigurationClass
getDeclaringClass
()
{
return
declaringClass
;
}
/**
...
...
@@ -96,6 +101,14 @@ final class ConfigurationClass implements BeanMetadataElement {
this
.
source
=
source
;
}
/**
* Returns a resource path-formatted representation of the .java file that declares this
* class
*/
public
Object
getSource
()
{
return
source
;
}
public
Location
getLocation
()
{
if
(
getName
()
==
null
)
{
throw
new
IllegalStateException
(
"'name' property is null. Call setName() before calling getLocation()"
);
...
...
@@ -103,23 +116,23 @@ final class ConfigurationClass implements BeanMetadataElement {
return
new
Location
(
new
ClassPathResource
(
ClassUtils
.
convertClassNameToResourcePath
(
getName
())),
getSource
());
}
public
String
getBeanName
()
{
return
beanName
;
}
public
void
setBeanName
(
String
beanName
)
{
this
.
beanName
=
beanName
;
}
public
int
getModifiers
()
{
return
modifiers
;
public
String
getBeanName
()
{
return
beanName
;
}
public
void
setModifiers
(
int
modifiers
)
{
Assert
.
isTrue
(
modifiers
>=
0
,
"modifiers must be non-negative"
);
this
.
modifiers
=
modifiers
;
}
public
int
getModifiers
()
{
return
modifiers
;
}
public
void
addAnnotation
(
Annotation
annotation
)
{
this
.
annotations
.
add
(
annotation
);
}
...
...
@@ -153,26 +166,34 @@ final class ConfigurationClass implements BeanMetadataElement {
return
anno
;
}
public
Set
<
ConfigurationClassMethod
>
getBeanMethods
()
{
return
methods
;
}
public
ConfigurationClass
addMethod
(
ConfigurationClassMethod
method
)
{
method
.
setDeclaringClass
(
this
);
methods
.
add
(
method
);
Integer
count
=
overloadedMethodMap
.
get
(
method
.
getName
());
if
(
count
!=
null
)
{
overloadedMethodMap
.
put
(
method
.
getName
(),
count
+
1
);
}
else
{
overloadedMethodMap
.
put
(
method
.
getName
(),
1
);
}
return
this
;
}
public
ConfigurationClass
getDeclaringClass
()
{
return
declaringClass
;
}
public
void
setDeclaringClass
(
ConfigurationClass
configurationClass
)
{
this
.
declaringClass
=
configurationClass
;
public
Set
<
ConfigurationClassMethod
>
getBeanMethods
()
{
return
methods
;
}
public
void
validate
(
ProblemReporter
problemReporter
)
{
// a configuration class may not be final (CGLIB limitation)
// No overloading of factory methods allowed
for
(
Map
.
Entry
<
String
,
Integer
>
entry
:
overloadedMethodMap
.
entrySet
())
{
String
methodName
=
entry
.
getKey
();
int
count
=
entry
.
getValue
();
if
(
count
>
1
)
{
problemReporter
.
error
(
new
OverloadedMethodProblem
(
methodName
,
count
));
}
}
// A configuration class may not be final (CGLIB limitation)
if
(
getAnnotation
(
Configuration
.
class
)
!=
null
)
{
if
(
Modifier
.
isFinal
(
modifiers
))
{
problemReporter
.
error
(
new
FinalConfigurationProblem
());
...
...
@@ -188,10 +209,21 @@ final class ConfigurationClass implements BeanMetadataElement {
private
class
FinalConfigurationProblem
extends
Problem
{
public
FinalConfigurationProblem
()
{
super
(
String
.
format
(
"@Configuration class
[%s]
may not be final. Remove the final modifier to continue."
,
super
(
String
.
format
(
"@Configuration class
'%s'
may not be final. Remove the final modifier to continue."
,
getSimpleName
()),
ConfigurationClass
.
this
.
getLocation
());
}
}
/** Factory methods on configuration classes must not be overloaded. */
private
class
OverloadedMethodProblem
extends
Problem
{
public
OverloadedMethodProblem
(
String
methodName
,
int
count
)
{
super
(
String
.
format
(
"@Configuration class '%s' has %s overloaded factory methods of name '%s'. "
+
"Only one factory method of the same name allowed."
,
getSimpleName
(),
count
,
methodName
),
ConfigurationClass
.
this
.
getLocation
());
}
}
}
org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassAnnotationVisitor.java
浏览文件 @
ea9d8925
...
...
@@ -17,10 +17,10 @@
package
org.springframework.context.annotation
;
import
java.lang.annotation.Annotation
;
import
java.lang.reflect.Field
;
import
java.lang.reflect.Array
;
import
java.
util.List
;
import
java.
lang.reflect.Field
;
import
java.util.ArrayList
;
import
java.util.List
;
import
org.springframework.asm.AnnotationVisitor
;
import
org.springframework.asm.Type
;
...
...
@@ -57,40 +57,47 @@ class ConfigurationClassAnnotationVisitor implements AnnotationVisitor {
public
void
visit
(
String
attribName
,
Object
attribValue
)
{
Class
<?>
attribReturnType
=
mutableAnno
.
getAttributeType
(
attribName
);
if
(
attribReturnType
.
equals
(
Class
.
class
))
{
// the attribute type is Class -> load it and set it.
String
fqClassName
=
((
Type
)
attribValue
).
getClassName
();
Class
<?>
classVal
=
ConfigurationClassReaderUtils
.
loadToolingSafeClass
(
fqClassName
,
classLoader
);
if
(
classVal
==
null
)
{
return
;
String
className
=
((
Type
)
attribValue
).
getClassName
();
try
{
Class
<?>
classVal
=
classLoader
.
loadClass
(
className
);
if
(
classVal
!=
null
)
{
mutableAnno
.
setAttributeValue
(
attribName
,
classVal
);
}
}
catch
(
ClassNotFoundException
ex
)
{
throw
new
IllegalStateException
(
"Cannot resolve attribute type ["
+
className
+
"]"
,
ex
);
}
mutableAnno
.
setAttributeValue
(
attribName
,
classVal
);
return
;
}
// otherwise, assume the value can be set literally
mutableAnno
.
setAttributeValue
(
attribName
,
attribValue
);
else
{
// otherwise, assume the value can be set literally
mutableAnno
.
setAttributeValue
(
attribName
,
attribValue
);
}
}
@SuppressWarnings
(
"unchecked"
)
public
void
visitEnum
(
String
attribName
,
String
enumTypeDescriptor
,
String
strEnumValue
)
{
String
enumClassName
=
ConfigurationClassReaderUtils
.
convertAsmTypeDescriptorToClassName
(
enumTypeDescriptor
);
Class
<?
extends
Enum
>
enumClass
=
ConfigurationClassReaderUtils
.
loadToolingSafeClass
(
enumClassName
,
classLoader
);
if
(
enumClass
==
null
)
{
return
;
String
enumTypeName
=
ConfigurationClassReaderUtils
.
convertAsmTypeDescriptorToClassName
(
enumTypeDescriptor
);
try
{
Class
<?
extends
Enum
>
enumType
=
(
Class
<?
extends
Enum
>)
classLoader
.
loadClass
(
enumTypeName
);
if
(
enumType
==
null
)
{
return
;
}
Enum
enumValue
=
Enum
.
valueOf
(
enumType
,
strEnumValue
);
mutableAnno
.
setAttributeValue
(
attribName
,
enumValue
);
}
catch
(
ClassNotFoundException
ex
)
{
throw
new
IllegalStateException
(
"Cannot resolve enum type ["
+
enumTypeName
+
"]"
,
ex
);
}
Enum
enumValue
=
Enum
.
valueOf
(
enumClass
,
strEnumValue
);
mutableAnno
.
setAttributeValue
(
attribName
,
enumValue
);
}
public
AnnotationVisitor
visitAnnotation
(
String
attribName
,
String
attribAnnoTypeDesc
)
{
String
annoTypeName
=
ConfigurationClassReaderUtils
.
convertAsmTypeDescriptorToClassName
(
attribAnnoTypeDesc
);
Class
<?
extends
Annotation
>
annoType
=
ConfigurationClassReaderUtils
.
loadToolingSafeClass
(
annoTypeName
,
classLoader
);
if
(
annoType
==
null
)
{
public
AnnotationVisitor
visitAnnotation
(
String
attribName
,
String
annoTypeDesc
)
{
Class
<?
extends
Annotation
>
annoClass
=
ConfigurationClassReaderUtils
.
loadAnnotationType
(
annoTypeDesc
,
classLoader
);
if
(
annoClass
==
null
)
{
return
new
EmptyVisitor
();
}
ConfigurationClassAnnotation
anno
=
ConfigurationClassReaderUtils
.
createMutableAnnotation
(
anno
Type
,
classLoader
);
ConfigurationClassAnnotation
anno
=
ConfigurationClassReaderUtils
.
createMutableAnnotation
(
anno
Class
,
classLoader
);
try
{
Field
attribute
=
mutableAnno
.
getClass
().
getField
(
attribName
);
attribute
.
set
(
mutableAnno
,
anno
);
...
...
@@ -123,14 +130,12 @@ class ConfigurationClassAnnotationVisitor implements AnnotationVisitor {
private
final
ClassLoader
classLoader
;
public
MutableAnnotationArrayVisitor
(
ConfigurationClassAnnotation
mutableAnno
,
String
attribName
,
ClassLoader
classLoader
)
{
this
.
mutableAnno
=
mutableAnno
;
this
.
attribName
=
attribName
;
this
.
classLoader
=
classLoader
;
}
public
void
visit
(
String
na
,
Object
value
)
{
values
.
add
(
value
);
}
...
...
@@ -139,12 +144,11 @@ class ConfigurationClassAnnotationVisitor implements AnnotationVisitor {
}
public
AnnotationVisitor
visitAnnotation
(
String
na
,
String
annoTypeDesc
)
{
String
annoTypeName
=
ConfigurationClassReaderUtils
.
convertAsmTypeDescriptorToClassName
(
annoTypeDesc
);
Class
<?
extends
Annotation
>
annoType
=
ConfigurationClassReaderUtils
.
loadToolingSafeClass
(
annoTypeName
,
classLoader
);
if
(
annoType
==
null
)
{
Class
<?
extends
Annotation
>
annoClass
=
ConfigurationClassReaderUtils
.
loadAnnotationType
(
annoTypeDesc
,
classLoader
);
if
(
annoClass
==
null
)
{
return
new
EmptyVisitor
();
}
ConfigurationClassAnnotation
anno
=
ConfigurationClassReaderUtils
.
createMutableAnnotation
(
anno
Type
,
classLoader
);
ConfigurationClassAnnotation
anno
=
ConfigurationClassReaderUtils
.
createMutableAnnotation
(
anno
Class
,
classLoader
);
values
.
add
(
anno
);
return
new
ConfigurationClassAnnotationVisitor
(
anno
,
classLoader
);
}
...
...
org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassBeanDefinitionReader.java
浏览文件 @
ea9d8925
...
...
@@ -16,6 +16,7 @@
package
org.springframework.context.annotation
;
import
java.lang.reflect.Method
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.List
;
...
...
@@ -25,6 +26,7 @@ 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
;
import
org.springframework.beans.factory.support.BeanDefinitionReader
;
...
...
@@ -32,7 +34,6 @@ import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import
org.springframework.beans.factory.support.BeanDefinitionRegistry
;
import
org.springframework.beans.factory.support.GenericBeanDefinition
;
import
org.springframework.beans.factory.support.RootBeanDefinition
;
import
org.springframework.beans.factory.annotation.Autowire
;
import
org.springframework.core.io.Resource
;
import
org.springframework.util.Assert
;
import
org.springframework.util.StringUtils
;
...
...
@@ -105,7 +106,7 @@ class ConfigurationClassBeanDefinitionReader {
RootBeanDefinition
beanDef
=
new
ConfigurationClassBeanDefinition
();
ConfigurationClass
configClass
=
method
.
getDeclaringClass
();
beanDef
.
setFactoryBeanName
(
configClass
.
getBeanName
());
beanDef
.
setFactoryMethodName
(
method
.
getName
());
beanDef
.
set
Unique
FactoryMethodName
(
method
.
getName
());
beanDef
.
setAutowireMode
(
RootBeanDefinition
.
AUTOWIRE_CONSTRUCTOR
);
// consider name and any aliases
...
...
@@ -197,11 +198,27 @@ class ConfigurationClassBeanDefinitionReader {
/**
* {@link RootBeanDefinition} marker subclass used to signify that a bean definition created
* by JavaConfig as opposed to any other configuration source. Used in bean overriding cases
* where it's necessary to determine whether the bean definition was created externally
* (e.g. via XML).
* where it's necessary to determine whether the bean definition was created externally.
*/
@SuppressWarnings
(
"serial"
)
private
class
ConfigurationClassBeanDefinition
extends
RootBeanDefinition
{
public
ConfigurationClassBeanDefinition
()
{
}
private
ConfigurationClassBeanDefinition
(
ConfigurationClassBeanDefinition
original
)
{
super
(
original
);
}
@Override
public
boolean
isFactoryMethod
(
Method
candidate
)
{
return
(
super
.
isFactoryMethod
(
candidate
)
&&
candidate
.
isAnnotationPresent
(
Bean
.
class
));
}
@Override
public
ConfigurationClassBeanDefinition
cloneBeanDefinition
()
{
return
new
ConfigurationClassBeanDefinition
(
this
);
}
}
}
org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java
浏览文件 @
ea9d8925
...
...
@@ -16,14 +16,14 @@
package
org.springframework.context.annotation
;
import
java.io.IOException
;
import
java.util.LinkedHashSet
;
import
java.util.Set
;
import
java.util.Stack
;
import
org.springframework.asm.ClassReader
;
import
org.springframework.beans.factory.config.BeanDefinition
;
import
org.springframework.beans.factory.parsing.ProblemReporter
;
import
org.springframework.util.ClassUtils
;
import
org.springframework.core.type.classreading.SimpleMetadataReader
;
import
org.springframework.core.type.classreading.SimpleMetadataReaderFactory
;
/**
* Parses a {@link Configuration} class definition, populating a configuration model.
...
...
@@ -41,11 +41,11 @@ import org.springframework.util.ClassUtils;
*/
class
ConfigurationClassParser
{
private
final
S
et
<
ConfigurationClass
>
model
;
private
final
S
impleMetadataReaderFactory
metadataReaderFactory
;
private
final
ProblemReporter
problemReporter
;
private
final
ClassLoader
classLoader
;
private
final
Set
<
ConfigurationClass
>
model
;
/**
...
...
@@ -53,10 +53,10 @@ class ConfigurationClassParser {
* configuration model.
* @param model model to be populated by each successive call to {@link #parse}
*/
public
ConfigurationClassParser
(
ProblemReporter
problemReporter
,
ClassLoader
classLoad
er
)
{
this
.
m
odel
=
new
LinkedHashSet
<
ConfigurationClass
>()
;
public
ConfigurationClassParser
(
SimpleMetadataReaderFactory
metadataReaderFactory
,
ProblemReporter
problemReport
er
)
{
this
.
m
etadataReaderFactory
=
metadataReaderFactory
;
this
.
problemReporter
=
problemReporter
;
this
.
classLoader
=
classLoader
;
this
.
model
=
new
LinkedHashSet
<
ConfigurationClass
>()
;
}
...
...
@@ -66,12 +66,11 @@ class ConfigurationClassParser {
* @param beanName may be null, but if populated represents the bean id
* (assumes that this configuration class was configured via XML)
*/
public
void
parse
(
String
className
,
String
beanName
)
{
String
resourcePath
=
ClassUtils
.
convertClassNameToResourcePath
(
className
);
ClassReader
configClassReader
=
ConfigurationClassReaderUtils
.
newAsmClassReader
(
ConfigurationClassReaderUtils
.
getClassAsStream
(
resourcePath
,
classLoader
));
public
void
parse
(
String
className
,
String
beanName
)
throws
IOException
{
SimpleMetadataReader
reader
=
this
.
metadataReaderFactory
.
getMetadataReader
(
className
);
ConfigurationClass
configClass
=
new
ConfigurationClass
();
configClass
.
setBeanName
(
beanName
);
configClassReader
.
accept
(
new
ConfigurationClassVisitor
(
configClass
,
model
,
problemReporter
,
classLoader
),
false
);
reader
.
getClassReader
().
accept
(
new
ConfigurationClassVisitor
(
configClass
,
model
,
problemReporter
,
metadataReaderFactory
),
false
);
model
.
add
(
configClass
);
}
...
...
org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassPostProcessor.java
浏览文件 @
ea9d8925
...
...
@@ -37,6 +37,7 @@ import org.springframework.core.Conventions;
import
org.springframework.core.Ordered
;
import
org.springframework.core.annotation.AnnotationUtils
;
import
org.springframework.core.type.AnnotationMetadata
;
import
org.springframework.core.type.classreading.CachingMetadataReaderFactory
;
import
org.springframework.core.type.classreading.MetadataReader
;
import
org.springframework.core.type.classreading.SimpleMetadataReaderFactory
;
import
org.springframework.stereotype.Component
;
...
...
@@ -81,6 +82,8 @@ public class ConfigurationClassPostProcessor implements BeanFactoryPostProcessor
private
ClassLoader
beanClassLoader
=
ClassUtils
.
getDefaultClassLoader
();
private
SimpleMetadataReaderFactory
metadataReaderFactory
=
new
SimpleMetadataReaderFactory
();
/**
* Override the default {@link ProblemReporter}.
...
...
@@ -92,6 +95,7 @@ public class ConfigurationClassPostProcessor implements BeanFactoryPostProcessor
public
void
setBeanClassLoader
(
ClassLoader
beanClassLoader
)
{
this
.
beanClassLoader
=
beanClassLoader
;
this
.
metadataReaderFactory
=
new
CachingMetadataReaderFactory
(
beanClassLoader
);
}
public
int
getOrder
()
{
...
...
@@ -132,9 +136,15 @@ public class ConfigurationClassPostProcessor implements BeanFactoryPostProcessor
}
// Populate a new configuration model by parsing each @Configuration classes
ConfigurationClassParser
parser
=
new
ConfigurationClassParser
(
this
.
problemReporter
,
this
.
beanClassLoad
er
);
ConfigurationClassParser
parser
=
new
ConfigurationClassParser
(
this
.
metadataReaderFactory
,
this
.
problemReport
er
);
for
(
BeanDefinitionHolder
holder
:
configBeanDefs
)
{
parser
.
parse
(
holder
.
getBeanDefinition
().
getBeanClassName
(),
holder
.
getBeanName
());
String
beanClassName
=
holder
.
getBeanDefinition
().
getBeanClassName
();
try
{
parser
.
parse
(
beanClassName
,
holder
.
getBeanName
());
}
catch
(
IOException
ex
)
{
throw
new
BeanDefinitionStoreException
(
"Failed to load bean class ["
+
beanClassName
+
"]"
,
ex
);
}
}
parser
.
validate
();
...
...
@@ -208,11 +218,10 @@ public class ConfigurationClassPostProcessor implements BeanFactoryPostProcessor
return
false
;
}
}
SimpleMetadataReaderFactory
metadataReaderFactory
=
new
SimpleMetadataReaderFactory
(
this
.
beanClassLoader
);
String
className
=
beanDef
.
getBeanClassName
();
while
(
className
!=
null
&&
!(
className
.
equals
(
Object
.
class
.
getName
())))
{
try
{
MetadataReader
metadataReader
=
metadataReaderFactory
.
getMetadataReader
(
className
);
MetadataReader
metadataReader
=
this
.
metadataReaderFactory
.
getMetadataReader
(
className
);
AnnotationMetadata
metadata
=
metadataReader
.
getAnnotationMetadata
();
if
(
metadata
.
hasAnnotation
(
Configuration
.
class
.
getName
()))
{
beanDef
.
setAttribute
(
CONFIGURATION_CLASS_ATTRIBUTE
,
"full"
);
...
...
org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassReaderUtils.java
浏览文件 @
ea9d8925
...
...
@@ -16,8 +16,6 @@
package
org.springframework.context.annotation
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
static
java
.
lang
.
String
.*;
import
java.lang.annotation.Annotation
;
import
java.lang.reflect.InvocationHandler
;
...
...
@@ -26,17 +24,11 @@ import java.lang.reflect.Proxy;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
import
org.apache.commons.logging.Log
;
import
org.apache.commons.logging.LogFactory
;
import
org.springframework.asm.ClassReader
;
import
org.springframework.beans.factory.BeanDefinitionStoreException
;
import
static
org
.
springframework
.
core
.
annotation
.
AnnotationUtils
.*;
import
org.springframework.core.annotation.AnnotationUtils
;
import
org.springframework.util.Assert
;
import
org.springframework.util.ClassUtils
;
import
org.springframework.util.ReflectionUtils
;
import
org.springframework.util.StringUtils
;
/**
...
...
@@ -48,8 +40,6 @@ import org.springframework.util.StringUtils;
*/
class
ConfigurationClassReaderUtils
{
private
static
final
Log
logger
=
LogFactory
.
getLog
(
ConfigurationClassReaderUtils
.
class
);
/**
* Convert a type descriptor to a classname suitable for classloading with
* Class.forName().
...
...
@@ -92,94 +82,14 @@ class ConfigurationClassReaderUtils {
return
convertAsmTypeDescriptorToClassName
(
returnTypeDescriptor
);
}
/**
* Create a new ASM {@link ClassReader} for <var>pathToClass</var>. Appends '.class' to
* pathToClass before attempting to load.
*/
public
static
ClassReader
newAsmClassReader
(
String
pathToClass
,
ClassLoader
classLoader
)
{
InputStream
is
=
getClassAsStream
(
pathToClass
,
classLoader
);
return
newAsmClassReader
(
is
);
}
/**
* Convenience method that creates and returns a new ASM {@link ClassReader} for the
* given InputStream <var>is</var>, closing the InputStream after creating the
* ClassReader and rethrowing any IOException thrown during ClassReader instantiation as
* an unchecked exception. Logs and ignores any IOException thrown when closing the
* InputStream.
*
* @param is InputStream that will be provided to the new ClassReader instance.
*/
public
static
ClassReader
newAsmClassReader
(
InputStream
is
)
{
try
{
return
new
ClassReader
(
is
);
}
catch
(
IOException
ex
)
{
throw
new
BeanDefinitionStoreException
(
"An unexpected exception occurred while creating ASM ClassReader: "
+
ex
);
}
finally
{
try
{
is
.
close
();
}
catch
(
IOException
ex
)
{
// ignore
}
}
}
/**
* Uses the default ClassLoader to load <var>pathToClass</var>. Appends '.class' to
* pathToClass before attempting to load.
* @param pathToClass resource path to class, not including .class suffix. e.g.: com/acme/MyClass
* @return inputStream for <var>pathToClass</var>
* @throws RuntimeException if <var>pathToClass</var> does not exist
*/
public
static
InputStream
getClassAsStream
(
String
pathToClass
,
ClassLoader
classLoader
)
{
String
classFileName
=
pathToClass
+
ClassUtils
.
CLASS_FILE_SUFFIX
;
InputStream
is
=
classLoader
.
getResourceAsStream
(
classFileName
);
if
(
is
==
null
)
{
throw
new
IllegalStateException
(
"Class file ["
+
classFileName
+
"] not found"
);
}
return
is
;
}
/**
* Loads the specified class using the default class loader, gracefully handling any
* {@link ClassNotFoundException} that may be thrown by issuing a WARN level logging
* statement and return null. This functionality is specifically implemented to
* accomodate tooling (Spring IDE) concerns, where user-defined types will not be
* available to the tooling.
* <p>
* Because {@link ClassNotFoundException} is compensated for by returning null, callers
* must take care to handle the null case appropriately.
* <p>
* In cases where the WARN logging statement is not desired, use the
* {@link #loadClass(String)} method, which returns null but issues no logging
* statements.
* <p>
* This method should only ever return null in the case of a user-defined type be
* processed at tooling time. Therefore, tooling may not be able to represent any custom
* annotation semantics, but JavaConfig itself will not have any problem loading and
* respecting them at actual runtime.
*
* @param <T> type of class to be returned
* @param fqClassName fully-qualified class name
*
* @return newly loaded class, null if class could not be found.
*
* @see #loadClass(String)
* @see #loadRequiredClass(String)
* @see ClassUtils#getDefaultClassLoader()
*/
@SuppressWarnings
(
"unchecked"
)
public
static
<
T
>
Class
<?
extends
T
>
loadToolingSafeClass
(
String
fqClassName
,
ClassLoader
classLoader
)
{
public
static
Class
<?
extends
Annotation
>
loadAnnotationType
(
String
annoTypeDesc
,
ClassLoader
classLoader
)
{
String
annoTypeName
=
ConfigurationClassReaderUtils
.
convertAsmTypeDescriptorToClassName
(
annoTypeDesc
);
try
{
return
(
Class
<?
extends
T
>)
classLoader
.
loadClass
(
fqClass
Name
);
return
(
Class
<?
extends
Annotation
>)
classLoader
.
loadClass
(
annoType
Name
);
}
catch
(
ClassNotFoundException
ex
)
{
logger
.
warn
(
String
.
format
(
"Unable to load class [%s], likely due to tooling-specific restrictions."
+
"Attempting to continue, but unexpected errors may occur"
,
fqClassName
),
ex
);
return
null
;
throw
new
IllegalStateException
(
"Could not load annotation type ["
+
annoTypeName
+
"]"
,
ex
);
}
}
...
...
@@ -212,7 +122,7 @@ class ConfigurationClassReaderUtils {
// and default values of the attributes defined in 'annoType'
Method
[]
attribs
=
annoType
.
getDeclaredMethods
();
for
(
Method
attrib
:
attribs
)
{
this
.
attributes
.
put
(
attrib
.
getName
(),
getDefaultValue
(
annoType
,
attrib
.
getName
()));
this
.
attributes
.
put
(
attrib
.
getName
(),
AnnotationUtils
.
getDefaultValue
(
annoType
,
attrib
.
getName
()));
this
.
attributeTypes
.
put
(
attrib
.
getName
(),
getAttributeType
(
annoType
,
attrib
.
getName
()));
}
...
...
@@ -349,11 +259,10 @@ class ConfigurationClassReaderUtils {
}
private
String
getAttribs
()
{
ArrayList
<
String
>
attribs
=
new
ArrayList
<
String
>();
for
(
String
attribName
:
attributes
.
keySet
())
List
<
String
>
attribs
=
new
ArrayList
<
String
>();
for
(
String
attribName
:
attributes
.
keySet
())
{
attribs
.
add
(
format
(
"%s=%s"
,
attribName
,
attributes
.
get
(
attribName
)));
}
return
StringUtils
.
collectionToDelimitedString
(
attribs
,
", "
);
}
...
...
@@ -361,15 +270,12 @@ class ConfigurationClassReaderUtils {
* Retrieve the type of the given annotation attribute.
*/
private
static
Class
<?>
getAttributeType
(
Class
<?
extends
Annotation
>
annotationType
,
String
attributeName
)
{
Method
method
=
null
;
try
{
method
=
annotationType
.
getDeclaredMethod
(
attributeName
);
}
catch
(
Exception
ex
)
{
ReflectionUtils
.
handleReflectionException
(
ex
);
return
annotationType
.
getDeclaredMethod
(
attributeName
).
getReturnType
();
}
catch
(
Exception
ex
)
{
throw
new
IllegalStateException
(
"Could not introspect return type"
,
ex
);
}
return
method
.
getReturnType
();
}
}
...
...
org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassVisitor.java
浏览文件 @
ea9d8925
...
...
@@ -16,6 +16,7 @@
package
org.springframework.context.annotation
;
import
java.io.IOException
;
import
java.lang.annotation.Annotation
;
import
java.util.ArrayList
;
import
java.util.Collections
;
...
...
@@ -37,10 +38,13 @@ import org.springframework.asm.MethodVisitor;
import
org.springframework.asm.Opcodes
;
import
org.springframework.asm.Type
;
import
org.springframework.asm.commons.EmptyVisitor
;
import
org.springframework.beans.factory.BeanDefinitionStoreException
;
import
org.springframework.beans.factory.parsing.Location
;
import
org.springframework.beans.factory.parsing.Problem
;
import
org.springframework.beans.factory.parsing.ProblemReporter
;
import
org.springframework.core.io.ClassPathResource
;
import
org.springframework.core.type.classreading.SimpleMetadataReader
;
import
org.springframework.core.type.classreading.SimpleMetadataReaderFactory
;
import
org.springframework.util.Assert
;
import
org.springframework.util.ClassUtils
;
...
...
@@ -64,27 +68,28 @@ class ConfigurationClassVisitor implements ClassVisitor {
private
final
ProblemReporter
problemReporter
;
private
final
ClassLoader
classLoader
;
private
final
SimpleMetadataReaderFactory
metadataReaderFactory
;
private
final
Stack
<
ConfigurationClass
>
importStack
;
public
ConfigurationClassVisitor
(
ConfigurationClass
configClass
,
Set
<
ConfigurationClass
>
model
,
ProblemReporter
problemReporter
,
ClassLoader
classLoader
)
{
ProblemReporter
problemReporter
,
SimpleMetadataReaderFactory
metadataReaderFactory
)
{
this
.
configClass
=
configClass
;
this
.
model
=
model
;
this
.
problemReporter
=
problemReporter
;
this
.
classLoader
=
classLoader
;
this
.
metadataReaderFactory
=
metadataReaderFactory
;
this
.
importStack
=
new
ImportStack
();
}
private
ConfigurationClassVisitor
(
ConfigurationClass
configClass
,
Set
<
ConfigurationClass
>
model
,
ProblemReporter
problemReporter
,
ClassLoader
classLoader
,
Stack
<
ConfigurationClass
>
importStack
)
{
ProblemReporter
problemReporter
,
SimpleMetadataReaderFactory
metadataReaderFactory
,
Stack
<
ConfigurationClass
>
importStack
)
{
this
.
configClass
=
configClass
;
this
.
model
=
model
;
this
.
problemReporter
=
problemReporter
;
this
.
classLoader
=
classLoader
;
this
.
metadataReaderFactory
=
metadataReaderFactory
;
this
.
importStack
=
importStack
;
}
...
...
@@ -105,9 +110,15 @@ class ConfigurationClassVisitor implements ClassVisitor {
if
(
OBJECT_DESC
.
equals
(
superTypeDesc
))
{
return
;
}
ConfigurationClassVisitor
visitor
=
new
ConfigurationClassVisitor
(
configClass
,
model
,
problemReporter
,
classLoader
,
importStack
);
ClassReader
reader
=
ConfigurationClassReaderUtils
.
newAsmClassReader
(
superTypeDesc
,
classLoader
);
reader
.
accept
(
visitor
,
false
);
ConfigurationClassVisitor
visitor
=
new
ConfigurationClassVisitor
(
configClass
,
model
,
problemReporter
,
metadataReaderFactory
,
importStack
);
String
superClassName
=
ClassUtils
.
convertResourcePathToClassName
(
superTypeDesc
);
try
{
SimpleMetadataReader
reader
=
this
.
metadataReaderFactory
.
getMetadataReader
(
superClassName
);
reader
.
getClassReader
().
accept
(
visitor
,
false
);
}
catch
(
IOException
ex
)
{
throw
new
BeanDefinitionStoreException
(
"Failed to load bean super class ["
+
superClassName
+
"]"
,
ex
);
}
}
public
void
visitSource
(
String
sourceFile
,
String
debug
)
{
...
...
@@ -132,15 +143,14 @@ class ConfigurationClassVisitor implements ClassVisitor {
* @see Lazy
* @see Import
*/
@SuppressWarnings
(
"unchecked"
)
public
AnnotationVisitor
visitAnnotation
(
String
annoTypeDesc
,
boolean
visible
)
{
String
annoTypeName
=
ConfigurationClassReaderUtils
.
convertAsmTypeDescriptorToClassName
(
annoTypeDesc
);
Class
<?
extends
Annotation
>
annoClass
=
ConfigurationClassReaderUtils
.
loadToolingSafeClass
(
annoTypeName
,
classLoader
);
ClassLoader
classLoader
=
metadataReaderFactory
.
getResourceLoader
().
getClassLoader
();
Class
<?
extends
Annotation
>
annoClass
=
ConfigurationClassReaderUtils
.
loadAnnotationType
(
annoTypeDesc
,
classLoader
);
if
(
annoClass
==
null
)
{
// annotation was unable to be loaded -> probably Spring IDE unable to load a user-defined annotation
return
new
EmptyVisitor
();
}
if
(
Import
.
class
.
equals
(
annoClass
))
{
if
(!
importStack
.
contains
(
configClass
))
{
importStack
.
push
(
configClass
);
...
...
@@ -169,6 +179,7 @@ class ConfigurationClassVisitor implements ClassVisitor {
* {@link ConfigurationClassMethodVisitor}.
*/
public
MethodVisitor
visitMethod
(
int
modifiers
,
String
methodName
,
String
methodDescriptor
,
String
arg3
,
String
[]
arg4
)
{
ClassLoader
classLoader
=
metadataReaderFactory
.
getResourceLoader
().
getClassLoader
();
return
new
ConfigurationClassMethodVisitor
(
configClass
,
methodName
,
methodDescriptor
,
modifiers
,
classLoader
);
}
...
...
@@ -181,7 +192,7 @@ class ConfigurationClassVisitor implements ClassVisitor {
* {@link Configuration} class. Determines whether the method is a {@link Bean}
* method and if so, adds it to the {@link ConfigurationClass}.
*/
private
static
class
ConfigurationClassMethodVisitor
extends
MethodAdapter
{
private
class
ConfigurationClassMethodVisitor
extends
MethodAdapter
{
private
final
ConfigurationClass
configClass
;
private
final
String
methodName
;
...
...
@@ -214,9 +225,9 @@ class ConfigurationClassVisitor implements ClassVisitor {
* present (regardless of its RetentionPolicy).
*/
@Override
@SuppressWarnings
(
"unchecked"
)
public
AnnotationVisitor
visitAnnotation
(
String
annoTypeDesc
,
boolean
visible
)
{
String
annoClassName
=
ConfigurationClassReaderUtils
.
convertAsmTypeDescriptorToClassName
(
annoTypeDesc
);
Class
<?
extends
Annotation
>
annoClass
=
ConfigurationClassReaderUtils
.
loadToolingSafeClass
(
annoClassName
,
classLoader
);
Class
<?
extends
Annotation
>
annoClass
=
ConfigurationClassReaderUtils
.
loadAnnotationType
(
annoTypeDesc
,
classLoader
);
if
(
annoClass
==
null
)
{
return
super
.
visitAnnotation
(
annoTypeDesc
,
visible
);
}
...
...
@@ -262,14 +273,19 @@ class ConfigurationClassVisitor implements ClassVisitor {
private
ConfigurationClassMethod
.
ReturnType
initReturnTypeFromMethodDescriptor
(
String
methodDescriptor
)
{
final
ConfigurationClassMethod
.
ReturnType
returnType
=
new
ConfigurationClassMethod
.
ReturnType
(
ConfigurationClassReaderUtils
.
getReturnTypeFromAsmMethodDescriptor
(
methodDescriptor
));
// detect whether the return type is an interface
ConfigurationClassReaderUtils
.
newAsmClassReader
(
ClassUtils
.
convertClassNameToResourcePath
(
returnType
.
getName
()),
classLoader
).
accept
(
new
ClassAdapter
(
new
EmptyVisitor
())
{
@Override
public
void
visit
(
int
arg0
,
int
arg1
,
String
arg2
,
String
arg3
,
String
arg4
,
String
[]
arg5
)
{
returnType
.
setInterface
((
arg1
&
Opcodes
.
ACC_INTERFACE
)
==
Opcodes
.
ACC_INTERFACE
);
}
},
false
);
return
returnType
;
try
{
metadataReaderFactory
.
getMetadataReader
(
returnType
.
getName
()).
getClassReader
().
accept
(
new
ClassAdapter
(
new
EmptyVisitor
())
{
@Override
public
void
visit
(
int
arg0
,
int
arg1
,
String
arg2
,
String
arg3
,
String
arg4
,
String
[]
arg5
)
{
returnType
.
setInterface
((
arg1
&
Opcodes
.
ACC_INTERFACE
)
==
Opcodes
.
ACC_INTERFACE
);
}
},
false
);
return
returnType
;
}
catch
(
IOException
ex
)
{
throw
new
BeanDefinitionStoreException
(
"Failed to load bean return type ["
+
returnType
.
getName
()
+
"]"
,
ex
);
}
}
}
...
...
@@ -285,17 +301,13 @@ class ConfigurationClassVisitor implements ClassVisitor {
private
final
ProblemReporter
problemReporter
;
private
final
ClassLoader
classLoader
;
private
final
List
<
String
>
classesToImport
=
new
ArrayList
<
String
>();
public
ImportAnnotationVisitor
(
Set
<
ConfigurationClass
>
model
,
ProblemReporter
problemReporter
,
ClassLoader
classLoader
)
{
this
.
model
=
model
;
this
.
problemReporter
=
problemReporter
;
this
.
classLoader
=
classLoader
;
}
public
void
visit
(
String
s
,
Object
o
)
{
...
...
@@ -337,13 +349,18 @@ class ConfigurationClassVisitor implements ClassVisitor {
private
void
processClassToImport
(
String
classToImport
)
{
ConfigurationClass
configClass
=
new
ConfigurationClass
();
ClassReader
reader
=
ConfigurationClassReaderUtils
.
newAsmClassReader
(
ClassUtils
.
convertClassNameToResourcePath
(
classToImport
),
classLoader
);
reader
.
accept
(
new
ConfigurationClassVisitor
(
configClass
,
model
,
problemReporter
,
classLoader
,
importStack
),
false
);
if
(
configClass
.
getAnnotation
(
Configuration
.
class
)
==
null
)
{
problemReporter
.
error
(
new
NonAnnotatedConfigurationProblem
(
configClass
.
getName
(),
configClass
.
getLocation
()));
try
{
ClassReader
reader
=
metadataReaderFactory
.
getMetadataReader
(
classToImport
).
getClassReader
();
reader
.
accept
(
new
ConfigurationClassVisitor
(
configClass
,
model
,
problemReporter
,
metadataReaderFactory
,
importStack
),
false
);
if
(
configClass
.
getAnnotation
(
Configuration
.
class
)
==
null
)
{
problemReporter
.
error
(
new
NonAnnotatedConfigurationProblem
(
configClass
.
getName
(),
configClass
.
getLocation
()));
}
else
{
model
.
add
(
configClass
);
}
}
else
{
model
.
add
(
configClass
);
catch
(
IOException
ex
)
{
throw
new
BeanDefinitionStoreException
(
"Failed to load imported configuration class ["
+
classToImport
+
"]"
,
ex
);
}
}
}
...
...
org.springframework.context/src/test/java/org/springframework/context/annotation/AsmCircularImportDetectionTests.java
浏览文件 @
ea9d8925
...
...
@@ -16,10 +16,7 @@
package
org.springframework.context.annotation
;
import
org.springframework.beans.factory.parsing.FailFastProblemReporter
;
import
org.springframework.context.annotation.ConfigurationClassParser
;
import
org.springframework.context.annotation.Import
;
import
org.springframework.util.ClassUtils
;
import
org.springframework.core.type.classreading.CachingMetadataReaderFactory
;
/**
* Unit test proving that ASM-based {@link ConfigurationClassParser} correctly detects circular use of
...
...
@@ -32,9 +29,10 @@ import org.springframework.util.ClassUtils;
* @author Chris Beams
*/
public
class
AsmCircularImportDetectionTests
extends
AbstractCircularImportDetectionTests
{
@Override
protected
ConfigurationClassParser
newParser
()
{
return
new
ConfigurationClassParser
(
new
FailFastProblemReporter
(),
ClassUtils
.
getDefaultClassLoad
er
());
return
new
ConfigurationClassParser
(
new
CachingMetadataReaderFactory
(),
new
FailFastProblemReport
er
());
}
@Override
...
...
org.springframework.context/src/test/java/org/springframework/context/annotation4/FactoryMethodComponent.java
浏览文件 @
ea9d8925
...
...
@@ -21,7 +21,6 @@ import org.springframework.beans.factory.annotation.Qualifier;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.BeanAge
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.context.annotation.Scope
;
import
org.springframework.context.annotation.ScopedProxyMode
;
import
org.springframework.stereotype.Component
;
...
...
@@ -47,6 +46,11 @@ public final class FactoryMethodComponent {
return
new
TestBean
(
"publicInstance"
);
}
// to be ignored
public
TestBean
publicInstance
(
boolean
doIt
)
{
return
new
TestBean
(
"publicInstance"
);
}
@Bean
@BeanAge
(
1
)
protected
TestBean
protectedInstance
(
@Qualifier
(
"public"
)
TestBean
spouse
,
@Value
(
"#{privateInstance.age}"
)
String
country
)
{
TestBean
tb
=
new
TestBean
(
"protectedInstance"
,
1
);
...
...
org.springframework.core/src/main/java/org/springframework/core/type/classreading/CachingMetadataReaderFactory.java
浏览文件 @
ea9d8925
...
...
@@ -33,7 +33,7 @@ import org.springframework.core.io.ResourceLoader;
*/
public
class
CachingMetadataReaderFactory
extends
SimpleMetadataReaderFactory
{
private
final
Map
<
Resource
,
MetadataReader
>
classReaderCache
=
new
HashMap
<
Resource
,
MetadataReader
>();
private
final
Map
<
Resource
,
SimpleMetadataReader
>
classReaderCache
=
new
HashMap
<
Resource
,
Simple
MetadataReader
>();
/**
...
...
@@ -62,9 +62,9 @@ public class CachingMetadataReaderFactory extends SimpleMetadataReaderFactory {
@Override
public
MetadataReader
getMetadataReader
(
Resource
resource
)
throws
IOException
{
public
Simple
MetadataReader
getMetadataReader
(
Resource
resource
)
throws
IOException
{
synchronized
(
this
.
classReaderCache
)
{
MetadataReader
metadataReader
=
this
.
classReaderCache
.
get
(
resource
);
Simple
MetadataReader
metadataReader
=
this
.
classReaderCache
.
get
(
resource
);
if
(
metadataReader
==
null
)
{
metadataReader
=
super
.
getMetadataReader
(
resource
);
this
.
classReaderCache
.
put
(
resource
,
metadataReader
);
...
...
org.springframework.core/src/main/java/org/springframework/core/type/classreading/SimpleMetadataReader.java
浏览文件 @
ea9d8925
...
...
@@ -30,29 +30,55 @@ import org.springframework.core.type.ClassMetadata;
* @author Juergen Hoeller
* @since 2.5
*/
class
SimpleMetadataReader
implements
MetadataReader
{
public
class
SimpleMetadataReader
implements
MetadataReader
{
private
final
ClassReader
classReader
;
private
final
ClassLoader
classLoader
;
private
ClassMetadata
classMetadata
;
public
SimpleMetadataReader
(
ClassReader
classReader
,
ClassLoader
classLoader
)
{
private
AnnotationMetadata
annotationMetadata
;
SimpleMetadataReader
(
ClassReader
classReader
,
ClassLoader
classLoader
)
{
this
.
classReader
=
classReader
;
this
.
classLoader
=
classLoader
;
}
/**
* Return the underlying ASM ClassReader.
*/
public
final
ClassReader
getClassReader
()
{
return
this
.
classReader
;
}
/**
* Return the underlying ClassLoader.
*/
public
final
ClassLoader
getClassLoader
()
{
return
this
.
classLoader
;
}
public
ClassMetadata
getClassMetadata
()
{
ClassMetadataReadingVisitor
visitor
=
new
ClassMetadataReadingVisitor
();
this
.
classReader
.
accept
(
visitor
,
true
);
return
visitor
;
if
(
this
.
classMetadata
==
null
)
{
ClassMetadataReadingVisitor
visitor
=
new
ClassMetadataReadingVisitor
();
this
.
classReader
.
accept
(
visitor
,
true
);
this
.
classMetadata
=
visitor
;
}
return
this
.
classMetadata
;
}
public
AnnotationMetadata
getAnnotationMetadata
()
{
AnnotationMetadataReadingVisitor
visitor
=
new
AnnotationMetadataReadingVisitor
(
this
.
classLoader
);
this
.
classReader
.
accept
(
visitor
,
true
);
return
visitor
;
if
(
this
.
annotationMetadata
==
null
)
{
AnnotationMetadataReadingVisitor
visitor
=
new
AnnotationMetadataReadingVisitor
(
this
.
classLoader
);
this
.
classReader
.
accept
(
visitor
,
true
);
this
.
annotationMetadata
=
visitor
;
this
.
classMetadata
=
visitor
;
}
return
this
.
annotationMetadata
;
}
}
org.springframework.core/src/main/java/org/springframework/core/type/classreading/SimpleMetadataReaderFactory.java
浏览文件 @
ea9d8925
...
...
@@ -63,13 +63,22 @@ public class SimpleMetadataReaderFactory implements MetadataReaderFactory {
}
public
MetadataReader
getMetadataReader
(
String
className
)
throws
IOException
{
/**
* Return the ResourceLoader that this MetadataReaderFactory has been
* constructed with.
*/
public
final
ResourceLoader
getResourceLoader
()
{
return
this
.
resourceLoader
;
}
public
SimpleMetadataReader
getMetadataReader
(
String
className
)
throws
IOException
{
String
resourcePath
=
ResourceLoader
.
CLASSPATH_URL_PREFIX
+
ClassUtils
.
convertClassNameToResourcePath
(
className
)
+
ClassUtils
.
CLASS_FILE_SUFFIX
;
return
getMetadataReader
(
this
.
resourceLoader
.
getResource
(
resourcePath
));
}
public
MetadataReader
getMetadataReader
(
Resource
resource
)
throws
IOException
{
public
Simple
MetadataReader
getMetadataReader
(
Resource
resource
)
throws
IOException
{
InputStream
is
=
resource
.
getInputStream
();
try
{
return
new
SimpleMetadataReader
(
new
ClassReader
(
is
),
this
.
resourceLoader
.
getClassLoader
());
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录