Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
爱吃血肠
spring-framework
提交
f75c01d1
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,发现更多精彩内容 >>
提交
f75c01d1
编写于
5月 27, 2012
作者:
C
Chris Beams
浏览文件
操作
浏览文件
下载
差异文件
Merge branch cbeams/SPR-6870
* SPR-6870: Cache by-type lookups in DefaultListableBeanFactory Polish
上级
f55a4a1a
4c7a1c0a
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
92 addition
and
35 deletion
+92
-35
spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java
...ork/beans/factory/support/DefaultListableBeanFactory.java
+51
-20
spring-beans/src/test/java/org/springframework/beans/factory/DefaultListableBeanFactoryTests.java
...mework/beans/factory/DefaultListableBeanFactoryTests.java
+41
-15
未找到文件。
spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java
浏览文件 @
f75c01d1
...
...
@@ -21,13 +21,14 @@ import java.io.NotSerializableException;
import
java.io.ObjectInputStream
;
import
java.io.ObjectStreamException
;
import
java.io.Serializable
;
import
java.lang.annotation.Annotation
;
import
java.lang.ref.Reference
;
import
java.lang.ref.WeakReference
;
import
java.lang.reflect.ParameterizedType
;
import
java.lang.reflect.Type
;
import
java.security.AccessController
;
import
java.security.PrivilegedAction
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.Collection
;
...
...
@@ -38,6 +39,7 @@ import java.util.List;
import
java.util.Map
;
import
java.util.Set
;
import
java.util.concurrent.ConcurrentHashMap
;
import
javax.inject.Provider
;
import
org.springframework.beans.BeansException
;
...
...
@@ -90,6 +92,7 @@ import org.springframework.util.StringUtils;
* @author Juergen Hoeller
* @author Sam Brannen
* @author Costin Leau
* @author Chris Beams
* @since 16 April 2001
* @see StaticListableBeanFactory
* @see PropertiesBeanDefinitionReader
...
...
@@ -98,7 +101,7 @@ import org.springframework.util.StringUtils;
public
class
DefaultListableBeanFactory
extends
AbstractAutowireCapableBeanFactory
implements
ConfigurableListableBeanFactory
,
BeanDefinitionRegistry
,
Serializable
{
private
static
Class
javaxInjectProviderClass
=
null
;
private
static
Class
<?>
javaxInjectProviderClass
=
null
;
static
{
ClassLoader
cl
=
DefaultListableBeanFactory
.
class
.
getClassLoader
();
...
...
@@ -128,11 +131,17 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
private
AutowireCandidateResolver
autowireCandidateResolver
=
new
SimpleAutowireCandidateResolver
();
/** Map from dependency type to corresponding autowired value */
private
final
Map
<
Class
,
Object
>
resolvableDependencies
=
new
HashMap
<
Class
,
Object
>();
private
final
Map
<
Class
<?>,
Object
>
resolvableDependencies
=
new
HashMap
<
Class
<?>
,
Object
>();
/** Map of bean definition objects, keyed by bean name */
private
final
Map
<
String
,
BeanDefinition
>
beanDefinitionMap
=
new
ConcurrentHashMap
<
String
,
BeanDefinition
>();
/** Map of singleton bean names keyed by bean class */
private
final
Map
<
Class
<?>,
String
[]>
singletonBeanNamesByType
=
new
ConcurrentHashMap
<
Class
<?>,
String
[]>();
/** Map of non-singleton bean names keyed by bean class */
private
final
Map
<
Class
<?>,
String
[]>
nonSingletonBeanNamesByType
=
new
ConcurrentHashMap
<
Class
<?>,
String
[]>();
/** List of bean definition names, in registration order */
private
final
List
<
String
>
beanDefinitionNames
=
new
ArrayList
<
String
>();
...
...
@@ -294,11 +303,26 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
}
}
public
String
[]
getBeanNamesForType
(
Class
type
)
{
public
String
[]
getBeanNamesForType
(
Class
<?>
type
)
{
return
getBeanNamesForType
(
type
,
true
,
true
);
}
public
String
[]
getBeanNamesForType
(
Class
type
,
boolean
includeNonSingletons
,
boolean
allowEagerInit
)
{
public
String
[]
getBeanNamesForType
(
Class
<?>
type
,
boolean
includeNonSingletons
,
boolean
allowEagerInit
)
{
if
(
type
==
null
||
!
allowEagerInit
)
{
return
this
.
doGetBeanNamesForType
(
type
,
includeNonSingletons
,
allowEagerInit
);
}
Map
<
Class
<?>,
String
[]>
cache
=
includeNonSingletons
?
this
.
nonSingletonBeanNamesByType
:
this
.
singletonBeanNamesByType
;
String
[]
resolvedBeanNames
=
cache
.
get
(
type
);
if
(
resolvedBeanNames
!=
null
)
{
return
resolvedBeanNames
;
}
resolvedBeanNames
=
this
.
doGetBeanNamesForType
(
type
,
includeNonSingletons
,
allowEagerInit
);
cache
.
put
(
type
,
resolvedBeanNames
);
return
resolvedBeanNames
;
}
private
String
[]
doGetBeanNamesForType
(
Class
<?>
type
,
boolean
includeNonSingletons
,
boolean
allowEagerInit
)
{
List
<
String
>
result
=
new
ArrayList
<
String
>();
// Check all bean definitions.
...
...
@@ -441,7 +465,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
*/
public
<
A
extends
Annotation
>
A
findAnnotationOnBean
(
String
beanName
,
Class
<
A
>
annotationType
)
{
A
ann
=
null
;
Class
beanType
=
getType
(
beanName
);
Class
<?>
beanType
=
getType
(
beanName
);
if
(
beanType
!=
null
)
{
ann
=
AnnotationUtils
.
findAnnotation
(
beanType
,
annotationType
);
}
...
...
@@ -564,18 +588,18 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
RootBeanDefinition
bd
=
getMergedLocalBeanDefinition
(
beanName
);
if
(!
bd
.
isAbstract
()
&&
bd
.
isSingleton
()
&&
!
bd
.
isLazyInit
())
{
if
(
isFactoryBean
(
beanName
))
{
final
FactoryBean
factory
=
(
FactoryBean
)
getBean
(
FACTORY_BEAN_PREFIX
+
beanName
);
final
FactoryBean
<?>
factory
=
(
FactoryBean
<?>
)
getBean
(
FACTORY_BEAN_PREFIX
+
beanName
);
boolean
isEagerInit
;
if
(
System
.
getSecurityManager
()
!=
null
&&
factory
instanceof
SmartFactoryBean
)
{
isEagerInit
=
AccessController
.
doPrivileged
(
new
PrivilegedAction
<
Boolean
>()
{
public
Boolean
run
()
{
return
((
SmartFactoryBean
)
factory
).
isEagerInit
();
return
((
SmartFactoryBean
<?>
)
factory
).
isEagerInit
();
}
},
getAccessControlContext
());
}
else
{
isEagerInit
=
(
factory
instanceof
SmartFactoryBean
&&
((
SmartFactoryBean
)
factory
).
isEagerInit
());
((
SmartFactoryBean
<?>
)
factory
).
isEagerInit
());
}
if
(
isEagerInit
)
{
getBean
(
beanName
);
...
...
@@ -669,6 +693,10 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
destroySingleton
(
beanName
);
}
// Remove any assumptions about by-type mappings
this
.
singletonBeanNamesByType
.
clear
();
this
.
nonSingletonBeanNamesByType
.
clear
();
// Reset all bean definitions that have the given bean as parent (recursively).
for
(
String
bdName
:
this
.
beanDefinitionNames
)
{
if
(!
beanName
.
equals
(
bdName
))
{
...
...
@@ -723,7 +751,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
}
if
(
type
.
isArray
())
{
Class
componentType
=
type
.
getComponentType
();
Class
<?>
componentType
=
type
.
getComponentType
();
Map
<
String
,
Object
>
matchingBeans
=
findAutowireCandidates
(
beanName
,
componentType
,
descriptor
);
if
(
matchingBeans
.
isEmpty
())
{
if
(
descriptor
.
isRequired
())
{
...
...
@@ -738,7 +766,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
return
converter
.
convertIfNecessary
(
matchingBeans
.
values
(),
type
);
}
else
if
(
Collection
.
class
.
isAssignableFrom
(
type
)
&&
type
.
isInterface
())
{
Class
elementType
=
descriptor
.
getCollectionType
();
Class
<?>
elementType
=
descriptor
.
getCollectionType
();
if
(
elementType
==
null
)
{
if
(
descriptor
.
isRequired
())
{
throw
new
FatalBeanException
(
"No element type declared for collection ["
+
type
.
getName
()
+
"]"
);
...
...
@@ -759,7 +787,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
return
converter
.
convertIfNecessary
(
matchingBeans
.
values
(),
type
);
}
else
if
(
Map
.
class
.
isAssignableFrom
(
type
)
&&
type
.
isInterface
())
{
Class
keyType
=
descriptor
.
getMapKeyType
();
Class
<?>
keyType
=
descriptor
.
getMapKeyType
();
if
(
keyType
==
null
||
!
String
.
class
.
isAssignableFrom
(
keyType
))
{
if
(
descriptor
.
isRequired
())
{
throw
new
FatalBeanException
(
"Key type ["
+
keyType
+
"] of map ["
+
type
.
getName
()
+
...
...
@@ -767,7 +795,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
}
return
null
;
}
Class
valueType
=
descriptor
.
getMapValueType
();
Class
<?>
valueType
=
descriptor
.
getMapValueType
();
if
(
valueType
==
null
)
{
if
(
descriptor
.
isRequired
())
{
throw
new
FatalBeanException
(
"No value type declared for map ["
+
type
.
getName
()
+
"]"
);
...
...
@@ -828,12 +856,12 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
* @see #autowireConstructor
*/
protected
Map
<
String
,
Object
>
findAutowireCandidates
(
String
beanName
,
Class
requiredType
,
DependencyDescriptor
descriptor
)
{
String
beanName
,
Class
<?>
requiredType
,
DependencyDescriptor
descriptor
)
{
String
[]
candidateNames
=
BeanFactoryUtils
.
beanNamesForTypeIncludingAncestors
(
this
,
requiredType
,
true
,
descriptor
.
isEager
());
Map
<
String
,
Object
>
result
=
new
LinkedHashMap
<
String
,
Object
>(
candidateNames
.
length
);
for
(
Class
autowiringType
:
this
.
resolvableDependencies
.
keySet
())
{
for
(
Class
<?>
autowiringType
:
this
.
resolvableDependencies
.
keySet
())
{
if
(
autowiringType
.
isAssignableFrom
(
requiredType
))
{
Object
autowiringValue
=
this
.
resolvableDependencies
.
get
(
autowiringType
);
autowiringValue
=
AutowireUtils
.
resolveAutowiringValue
(
autowiringValue
,
requiredType
);
...
...
@@ -918,7 +946,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
* Raise a NoSuchBeanDefinitionException for an unresolvable dependency.
*/
private
void
raiseNoSuchBeanDefinitionException
(
Class
type
,
String
dependencyDescription
,
DependencyDescriptor
descriptor
)
Class
<?>
type
,
String
dependencyDescription
,
DependencyDescriptor
descriptor
)
throws
NoSuchBeanDefinitionException
{
throw
new
NoSuchBeanDefinitionException
(
type
,
dependencyDescription
,
...
...
@@ -967,6 +995,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
* Minimal id reference to the factory.
* Resolved to the actual factory instance on deserialization.
*/
@SuppressWarnings
(
"serial"
)
private
static
class
SerializedBeanFactoryReference
implements
Serializable
{
private
final
String
id
;
...
...
@@ -976,7 +1005,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
}
private
Object
readResolve
()
{
Reference
ref
=
serializableFactories
.
get
(
this
.
id
);
Reference
<?>
ref
=
serializableFactories
.
get
(
this
.
id
);
if
(
ref
==
null
)
{
throw
new
IllegalStateException
(
"Cannot deserialize BeanFactory with id "
+
this
.
id
+
": no factory registered for this id"
);
...
...
@@ -994,7 +1023,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
/**
* Serializable ObjectFactory for lazy resolution of a dependency.
*/
private
class
DependencyObjectFactory
implements
ObjectFactory
,
Serializable
{
@SuppressWarnings
(
"serial"
)
private
class
DependencyObjectFactory
implements
ObjectFactory
<
Object
>,
Serializable
{
private
final
DependencyDescriptor
descriptor
;
...
...
@@ -1015,7 +1045,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
/**
* Serializable ObjectFactory for lazy resolution of a dependency.
*/
private
class
DependencyProvider
extends
DependencyObjectFactory
implements
Provider
{
@SuppressWarnings
(
"serial"
)
private
class
DependencyProvider
extends
DependencyObjectFactory
implements
Provider
<
Object
>
{
public
DependencyProvider
(
DependencyDescriptor
descriptor
,
String
beanName
)
{
super
(
descriptor
,
beanName
);
...
...
spring-beans/src/test/java/org/springframework/beans/factory/DefaultListableBeanFactoryTests.java
浏览文件 @
f75c01d1
/*
* Copyright 2002-201
1
the original author or authors.
* Copyright 2002-201
2
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.
...
...
@@ -16,26 +16,18 @@
package
org.springframework.beans.factory
;
import
static
org
.
hamcrest
.
CoreMatchers
.
is
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
assertFalse
;
import
static
org
.
junit
.
Assert
.
assertNotNull
;
import
static
org
.
junit
.
Assert
.
assertNotSame
;
import
static
org
.
junit
.
Assert
.
assertNull
;
import
static
org
.
junit
.
Assert
.
assertSame
;
import
static
org
.
junit
.
Assert
.
assertThat
;
import
static
org
.
junit
.
Assert
.
assertTrue
;
import
static
org
.
junit
.
Assert
.
fail
;
import
static
org
.
springframework
.
beans
.
factory
.
support
.
BeanDefinitionBuilder
.
rootBeanDefinition
;
import
java.lang.reflect.Field
;
import
java.net.MalformedURLException
;
import
java.security.AccessControlContext
;
import
java.security.AccessController
;
import
java.security.Principal
;
import
java.security.PrivilegedAction
;
import
java.text.NumberFormat
;
import
java.text.ParseException
;
import
java.util.Arrays
;
import
java.util.Iterator
;
import
java.util.List
;
...
...
@@ -48,8 +40,10 @@ import javax.security.auth.Subject;
import
org.apache.commons.logging.Log
;
import
org.apache.commons.logging.LogFactory
;
import
org.junit.Ignore
;
import
org.junit.Test
;
import
org.springframework.beans.BeansException
;
import
org.springframework.beans.MutablePropertyValues
;
import
org.springframework.beans.NotWritablePropertyException
;
...
...
@@ -92,6 +86,10 @@ import test.beans.LifecycleBean;
import
test.beans.NestedTestBean
;
import
test.beans.TestBean
;
import
static
org
.
hamcrest
.
CoreMatchers
.*;
import
static
org
.
junit
.
Assert
.*;
/**
* Tests properties population and autowire behavior.
*
...
...
@@ -2159,13 +2157,41 @@ public class DefaultListableBeanFactoryTests {
@Test
public
void
testContainsBeanReturnsTrueEvenForAbstractBeanDefinition
()
{
DefaultListableBeanFactory
bf
=
new
DefaultListableBeanFactory
();
bf
.
registerBeanDefinition
(
"abs"
,
rootBeanDefinition
(
TestBean
.
class
).
setAbstract
(
true
).
getBeanDefinition
());
bf
.
registerBeanDefinition
(
"abs"
,
BeanDefinitionBuilder
.
rootBeanDefinition
(
TestBean
.
class
).
setAbstract
(
true
).
getBeanDefinition
());
assertThat
(
bf
.
containsBean
(
"abs"
),
is
(
true
));
assertThat
(
bf
.
containsBean
(
"bogus"
),
is
(
false
));
}
static
class
A
{
}
static
class
B
{
}
/**
* Test that by-type bean lookup caching is working effectively by searching for a
* bean of type B 10K times within a container having 1K additional beans of type A.
* Prior to by-type caching, each bean lookup would traverse the entire container
* (all 1001 beans), performing expensive assignability checks, etc. Now these
* operations are necessary only once, providing a dramatic performance improvement.
* On load-free modern hardware (e.g. an 8-core MPB), this method should complete well
* under the 1000 ms timeout, usually ~= 300ms. With caching removed and on the same
* hardware the method will take ~13000 ms. See SPR-6870.
*/
@Test
(
timeout
=
1000
)
public
void
testByTypeLookupIsFastEnough
()
{
DefaultListableBeanFactory
bf
=
new
DefaultListableBeanFactory
();
for
(
int
i
=
0
;
i
<
1000
;
i
++)
{
bf
.
registerBeanDefinition
(
"a"
+
i
,
new
RootBeanDefinition
(
A
.
class
));
}
bf
.
registerBeanDefinition
(
"b"
,
new
RootBeanDefinition
(
B
.
class
));
for
(
int
i
=
0
;
i
<
10000
;
i
++)
{
bf
.
getBean
(
B
.
class
);
}
}
public
static
class
NoDependencies
{
private
NoDependencies
()
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录